xref: /petsc/src/mat/impls/shell/shell.c (revision 3a40ed3dce77c081171d005ae1a6ff4bb9d13b6f)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: shell.c,v 1.50 1997/08/22 15:13:51 bsmith Exp bsmith $";
3 #endif
4 
5 /*
6    This provides a simple shell for Fortran (and C programmers) to
7   create a very simple matrix class for use with KSP without coding
8   much of anything.
9 */
10 
11 #include "petsc.h"
12 #include "src/mat/matimpl.h"        /*I "mat.h" I*/
13 #include "src/vec/vecimpl.h"
14 
15 typedef struct {
16   int  M, N;                  /* number of global rows, columns */
17   int  m, n;                  /* number of local rows, columns */
18   int  (*destroy)(Mat);
19   void *ctx;
20 } Mat_Shell;
21 
22 #undef __FUNC__
23 #define __FUNC__ "MatShellGetContext"
24 /*@
25     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
26 
27     Input Parameter:
28 .   mat - the matrix, should have been created with MatCreateShell()
29 
30     Output Parameter:
31 .   ctx - the user provided context
32 
33     Notes:
34     This routine is intended for use within various shell matrix routines,
35     as set with MatShellSetOperation().
36 
37 .keywords: matrix, shell, get, context
38 
39 .seealso: MatCreateShell(), MatShellSetOperation()
40 @*/
41 int MatShellGetContext(Mat mat,void **ctx)
42 {
43   PetscFunctionBegin;
44   PetscValidHeaderSpecific(mat,MAT_COOKIE);
45   if (mat->type != MATSHELL) *ctx = 0;
46   else                       *ctx = ((Mat_Shell *) (mat->data))->ctx;
47   PetscFunctionReturn(0);
48 }
49 
50 #undef __FUNC__
51 #define __FUNC__ "MatGetSize_Shell"
52 int MatGetSize_Shell(Mat mat,int *M,int *N)
53 {
54   Mat_Shell *shell = (Mat_Shell *) mat->data;
55 
56   PetscFunctionBegin;
57   *M = shell->M; *N = shell->N;
58   PetscFunctionReturn(0);
59 }
60 
61 #undef __FUNC__
62 #define __FUNC__ "MatGetLocalSize_Shell"
63 int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
64 {
65   Mat_Shell *shell = (Mat_Shell *) mat->data;
66 
67   PetscFunctionBegin;
68   *m = shell->n; *n = shell->n;
69   PetscFunctionReturn(0);
70 }
71 
72 #undef __FUNC__
73 #define __FUNC__ "MatDestroy_Shell"
74 int MatDestroy_Shell(PetscObject obj)
75 {
76   int       ierr;
77   Mat       mat = (Mat) obj;
78   Mat_Shell *shell;
79 
80   PetscFunctionBegin;
81   shell = (Mat_Shell *) mat->data;
82   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
83   PetscFree(shell);
84   PLogObjectDestroy(mat);
85   PetscHeaderDestroy(mat);
86   PetscFunctionReturn(0);
87 }
88 
89 int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
90 {
91   MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);
92   *rstart = *rend - mat->m;
93   PetscFunctionReturn(0);
94 }
95 
96 
97 
98 
99 static struct _MatOps MatOps = {0,
100        0,
101        0,
102        0,
103        0,
104        0,
105        0,
106        0,
107        0,
108        0,
109        0,
110        0,
111        0,
112        0,
113        0,
114        0,
115        0,
116        0,
117        0,
118        0,
119        0,
120        0,
121        0,
122        0,
123        0,
124        0,
125        0,
126        0,
127        0,
128        0,
129        MatGetSize_Shell,
130        MatGetLocalSize_Shell,
131        MatGetOwnershipRange_Shell,
132        0,
133        0,
134        0,
135        0,
136        0 };
137 
138 #undef __FUNC__
139 #define __FUNC__ "MatCreateShell"
140 /*@C
141    MatCreateShell - Creates a new matrix class for use with a user-defined
142    private data storage format.
143 
144    Input Parameters:
145 .  comm - MPI communicator
146 .  m - number of local rows
147 .  n - number of local columns
148 .  M - number of global rows
149 .  N - number of global columns
150 .  ctx - pointer to data needed by the shell matrix routines
151 
152    Output Parameter:
153 .  A - the matrix
154 
155    Usage:
156 $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
157 $    MatShellSetOperation(mat,MATOP_MULT,mult);
158 $    [ Use matrix for operations that have been set ]
159 $    MatDestroy(mat);
160 
161    Notes:
162    The shell matrix type is intended to provide a simple class to use
163    with KSP (such as, for use with matrix-free methods). You should not
164    use the shell type if you plan to define a complete matrix class.
165 
166    PETSc requires that matrices and vectors being used for certain
167    operations are partitioned accordingly.  For example, when
168    creating a shell matrix, A, that supports parallel matrix-vector
169    products using MatMult(A,x,y) the user should set the number
170    of local matrix rows to be the number of local elements of the
171    corresponding result vector, y. Note that this is information is
172    required for use of the matrix interface routines, even though
173    the shell matrix may not actually be physically partitioned.
174    For example,
175 
176 $
177 $     Vec x, y
178 $     Mat A
179 $
180 $     VecCreate(comm,M,&y);
181 $     VecCreate(comm,N,&x);
182 $     VecGetLocalSize(y,&m);
183 $     MatCreateShell(comm,m,N,M,N,ctx,&A);
184 $     MatShellSetOperation(mat,MATOP_MULT,mult);
185 $     MatMult(A,x,y);
186 $     MatDestroy(A);
187 $     VecDestroy(y); VecDestroy(x);
188 $
189 
190 .keywords: matrix, shell, create
191 
192 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
193 @*/
194 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
195 {
196   Mat       B;
197   Mat_Shell *b;
198 
199   PetscFunctionBegin;
200   PetscHeaderCreate(B,_p_Mat,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView);
201   PLogObjectCreate(B);
202   B->factor    = 0;
203   B->destroy   = MatDestroy_Shell;
204   B->assembled = PETSC_TRUE;
205   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
206 
207   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
208   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
209   PetscMemzero(b,sizeof(Mat_Shell));
210   B->data   = (void *) b;
211   b->M = M; B->M = M;
212   b->N = N; B->N = N;
213   b->m = m; B->m = m;
214   b->n = n; B->n = n;
215   b->ctx     = ctx;
216   *A = B;
217   PetscFunctionReturn(0);
218 }
219 
220 #undef __FUNC__
221 #define __FUNC__ "MatShellSetOperation"
222 /*@C
223     MatShellSetOperation - Allows user to set a matrix operation for
224                            a shell matrix.
225 
226     Input Parameters:
227 .   mat - the shell matrix
228 .   op - the name of the operation
229 .   f - the function that provides the operation.
230 
231     Usage:
232 $      extern int usermult(Mat,Vec,Vec);
233 $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
234 $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
235 
236     Notes:
237     See the file petsc/include/mat.h for a complete list of matrix
238     operations, which all have the form MATOP_<OPERATION>, where
239     <OPERATION> is the name (in all capital letters) of the
240     user interface routine (e.g., MatMult() -> MATOP_MULT).
241 
242     All user-provided functions should have the same calling
243     sequence as the usual matrix interface routines, since they
244     are intended to be accessed via the usual matrix interface
245     routines, e.g.,
246 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
247 
248     Within each user-defined routine, the user should call
249     MatShellGetContext() to obtain the user-defined context that was
250     set by MatCreateShell().
251 
252 .keywords: matrix, shell, set, operation
253 
254 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
255 @*/
256 int MatShellSetOperation(Mat mat,MatOperation op, void *f)
257 {
258   PetscFunctionBegin;
259   PetscValidHeaderSpecific(mat,MAT_COOKIE);
260 
261   if (op == MATOP_DESTROY) {
262     if (mat->type == MATSHELL) {
263        Mat_Shell *shell = (Mat_Shell *) mat->data;
264        shell->destroy                 = (int (*)(Mat)) f;
265     }
266     else mat->destroy                 = (int (*)(PetscObject)) f;
267   }
268   else if (op == MATOP_VIEW) mat->view  = (int (*)(PetscObject,Viewer)) f;
269   else      (((void**)&mat->ops)[op]) = f;
270 
271   PetscFunctionReturn(0);
272 }
273 
274 #undef __FUNC__
275 #define __FUNC__ "MatShellGetOperation"
276 /*@C
277     MatShellGetOperation - Gets a matrix function for a shell matrix.
278 
279     Input Parameters:
280 .   mat - the shell matrix
281 .   op - the name of the operation
282 
283     Output Parameter:
284 .   f - the function that provides the operation.
285 
286     Notes:
287     See the file petsc/include/mat.h for a complete list of matrix
288     operations, which all have the form MATOP_<OPERATION>, where
289     <OPERATION> is the name (in all capital letters) of the
290     user interface routine (e.g., MatMult() -> MATOP_MULT).
291 
292     All user-provided functions have the same calling
293     sequence as the usual matrix interface routines, since they
294     are intended to be accessed via the usual matrix interface
295     routines, e.g.,
296 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
297 
298     Within each user-defined routine, the user should call
299     MatShellGetContext() to obtain the user-defined context that was
300     set by MatCreateShell().
301 
302 .keywords: matrix, shell, set, operation
303 
304 .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
305 @*/
306 int MatShellGetOperation(Mat mat,MatOperation op, void **f)
307 {
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(mat,MAT_COOKIE);
310 
311   if (op == MATOP_DESTROY) {
312     if (mat->type == MATSHELL) {
313        Mat_Shell *shell = (Mat_Shell *) mat->data;
314        *f = (void *) shell->destroy;
315     }
316     else *f = (void *) mat->destroy;
317   }
318   else if (op == MATOP_VIEW) *f = (void *) mat->view;
319   else      *f = (((void**)&mat->ops)[op]);
320 
321   PetscFunctionReturn(0);
322 }
323 
324