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