xref: /petsc/src/mat/impls/shell/shell.c (revision 09dc009565e93429658382de1b2877c8e5b304ef)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: shell.c,v 1.57 1998/05/29 20:37:11 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   shell = (Mat_Shell *) mat->data;
93   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
94   PetscFree(shell);
95   PLogObjectDestroy(mat);
96   PetscHeaderDestroy(mat);
97   PetscFunctionReturn(0);
98 }
99 
100 int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
101 {
102   int ierr;
103 
104   PetscFunctionBegin;
105   ierr = MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr);
106   *rstart = *rend - mat->m;
107   PetscFunctionReturn(0);
108 }
109 
110 
111 
112 
113 static struct _MatOps MatOps_Values = {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        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        MatGetSize_Shell,
144        MatGetLocalSize_Shell,
145        MatGetOwnershipRange_Shell,
146        0,
147        0,
148        0,
149        0,
150        0,
151        0,
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        MatGetMaps_Petsc};
179 
180 #undef __FUNC__
181 #define __FUNC__ "MatCreateShell"
182 /*@C
183    MatCreateShell - Creates a new matrix class for use with a user-defined
184    private data storage format.
185 
186    Input Parameters:
187 .  comm - MPI communicator
188 .  m - number of local rows
189 .  n - number of local columns
190 .  M - number of global rows
191 .  N - number of global columns
192 .  ctx - pointer to data needed by the shell matrix routines
193 
194    Output Parameter:
195 .  A - the matrix
196 
197   Collective on MPI_Comm
198 
199   Usage:
200 $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
201 $    MatShellSetOperation(mat,MATOP_MULT,mult);
202 $    [ Use matrix for operations that have been set ]
203 $    MatDestroy(mat);
204 
205    Notes:
206    The shell matrix type is intended to provide a simple class to use
207    with KSP (such as, for use with matrix-free methods). You should not
208    use the shell type if you plan to define a complete matrix class.
209 
210    PETSc requires that matrices and vectors being used for certain
211    operations are partitioned accordingly.  For example, when
212    creating a shell matrix, A, that supports parallel matrix-vector
213    products using MatMult(A,x,y) the user should set the number
214    of local matrix rows to be the number of local elements of the
215    corresponding result vector, y. Note that this is information is
216    required for use of the matrix interface routines, even though
217    the shell matrix may not actually be physically partitioned.
218    For example,
219 
220 $
221 $     Vec x, y
222 $     Mat A
223 $
224 $     VecCreate(comm,PETSC_DECIDE,M,&y);
225 $     VecCreate(comm,PETSC_DECIDE,N,&x);
226 $     VecGetLocalSize(y,&m);
227 $     MatCreateShell(comm,m,N,M,N,ctx,&A);
228 $     MatShellSetOperation(mat,MATOP_MULT,mult);
229 $     MatMult(A,x,y);
230 $     MatDestroy(A);
231 $     VecDestroy(y); VecDestroy(x);
232 $
233 
234 .keywords: matrix, shell, create
235 
236 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
237 @*/
238 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
239 {
240   Mat       B;
241   Mat_Shell *b;
242 
243   PetscFunctionBegin;
244   PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView);
245   PLogObjectCreate(B);
246   B->factor    = 0;
247   B->assembled = PETSC_TRUE;
248   PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
249   B->ops->destroy   = MatDestroy_Shell;
250 
251   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
252   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
253   PetscMemzero(b,sizeof(Mat_Shell));
254   B->data   = (void *) b;
255   b->M = M; B->M = M;
256   b->N = N; B->N = N;
257   b->m = m; B->m = m;
258   b->n = n; B->n = n;
259   b->ctx     = ctx;
260   *A = B;
261   PetscFunctionReturn(0);
262 }
263 
264 #undef __FUNC__
265 #define __FUNC__ "MatShellSetOperation"
266 /*@C
267     MatShellSetOperation - Allows user to set a matrix operation for
268                            a shell matrix.
269 
270     Input Parameters:
271 .   mat - the shell matrix
272 .   op - the name of the operation
273 .   f - the function that provides the operation.
274 
275    Collective on Mat
276 
277     Usage:
278 $      extern int usermult(Mat,Vec,Vec);
279 $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
280 $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
281 
282     Notes:
283     See the file petsc/include/mat.h for a complete list of matrix
284     operations, which all have the form MATOP_<OPERATION>, where
285     <OPERATION> is the name (in all capital letters) of the
286     user interface routine (e.g., MatMult() -> MATOP_MULT).
287 
288     All user-provided functions should have the same calling
289     sequence as the usual matrix interface routines, since they
290     are intended to be accessed via the usual matrix interface
291     routines, e.g.,
292 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
293 
294     Within each user-defined routine, the user should call
295     MatShellGetContext() to obtain the user-defined context that was
296     set by MatCreateShell().
297 
298 .keywords: matrix, shell, set, operation
299 
300 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
301 @*/
302 int MatShellSetOperation(Mat mat,MatOperation op, void *f)
303 {
304   PetscFunctionBegin;
305   PetscValidHeaderSpecific(mat,MAT_COOKIE);
306 
307   if (op == MATOP_DESTROY) {
308     if (mat->type == MATSHELL) {
309        Mat_Shell *shell = (Mat_Shell *) mat->data;
310        shell->destroy                 = (int (*)(Mat)) f;
311     }
312     else mat->ops->destroy            = (int (*)(Mat)) f;
313   }
314   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,Viewer)) f;
315   else      (((void**)mat->ops)[op]) = f;
316 
317   PetscFunctionReturn(0);
318 }
319 
320 #undef __FUNC__
321 #define __FUNC__ "MatShellGetOperation"
322 /*@C
323     MatShellGetOperation - Gets a matrix function for a shell matrix.
324 
325     Input Parameters:
326 .   mat - the shell matrix
327 .   op - the name of the operation
328 
329     Output Parameter:
330 .   f - the function that provides the operation.
331 
332     Not Collective
333 
334     Notes:
335     See the file petsc/include/mat.h for a complete list of matrix
336     operations, which all have the form MATOP_<OPERATION>, where
337     <OPERATION> is the name (in all capital letters) of the
338     user interface routine (e.g., MatMult() -> MATOP_MULT).
339 
340     All user-provided functions have the same calling
341     sequence as the usual matrix interface routines, since they
342     are intended to be accessed via the usual matrix interface
343     routines, e.g.,
344 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
345 
346     Within each user-defined routine, the user should call
347     MatShellGetContext() to obtain the user-defined context that was
348     set by MatCreateShell().
349 
350 .keywords: matrix, shell, set, operation
351 
352 .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
353 @*/
354 int MatShellGetOperation(Mat mat,MatOperation op, void **f)
355 {
356   PetscFunctionBegin;
357   PetscValidHeaderSpecific(mat,MAT_COOKIE);
358 
359   if (op == MATOP_DESTROY) {
360     if (mat->type == MATSHELL) {
361        Mat_Shell *shell = (Mat_Shell *) mat->data;
362        *f = (void *) shell->destroy;
363     }
364     else *f = (void *) mat->ops->destroy;
365   }
366   else if (op == MATOP_VIEW) *f = (void *) mat->ops->view;
367   else      *f = (((void**)&mat->ops)[op]);
368 
369   PetscFunctionReturn(0);
370 }
371 
372