xref: /petsc/src/mat/impls/shell/shell.c (revision 94d884c6647a2d9b71b6517178bcae041a65139f)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: shell.c,v 1.56 1998/04/13 17:37:39 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 = {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 
152 #undef __FUNC__
153 #define __FUNC__ "MatCreateShell"
154 /*@C
155    MatCreateShell - Creates a new matrix class for use with a user-defined
156    private data storage format.
157 
158    Input Parameters:
159 .  comm - MPI communicator
160 .  m - number of local rows
161 .  n - number of local columns
162 .  M - number of global rows
163 .  N - number of global columns
164 .  ctx - pointer to data needed by the shell matrix routines
165 
166    Output Parameter:
167 .  A - the matrix
168 
169   Collective on MPI_Comm
170 
171   Usage:
172 $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
173 $    MatShellSetOperation(mat,MATOP_MULT,mult);
174 $    [ Use matrix for operations that have been set ]
175 $    MatDestroy(mat);
176 
177    Notes:
178    The shell matrix type is intended to provide a simple class to use
179    with KSP (such as, for use with matrix-free methods). You should not
180    use the shell type if you plan to define a complete matrix class.
181 
182    PETSc requires that matrices and vectors being used for certain
183    operations are partitioned accordingly.  For example, when
184    creating a shell matrix, A, that supports parallel matrix-vector
185    products using MatMult(A,x,y) the user should set the number
186    of local matrix rows to be the number of local elements of the
187    corresponding result vector, y. Note that this is information is
188    required for use of the matrix interface routines, even though
189    the shell matrix may not actually be physically partitioned.
190    For example,
191 
192 $
193 $     Vec x, y
194 $     Mat A
195 $
196 $     VecCreate(comm,PETSC_DECIDE,M,&y);
197 $     VecCreate(comm,PETSC_DECIDE,N,&x);
198 $     VecGetLocalSize(y,&m);
199 $     MatCreateShell(comm,m,N,M,N,ctx,&A);
200 $     MatShellSetOperation(mat,MATOP_MULT,mult);
201 $     MatMult(A,x,y);
202 $     MatDestroy(A);
203 $     VecDestroy(y); VecDestroy(x);
204 $
205 
206 .keywords: matrix, shell, create
207 
208 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
209 @*/
210 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
211 {
212   Mat       B;
213   Mat_Shell *b;
214 
215   PetscFunctionBegin;
216   PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView);
217   PLogObjectCreate(B);
218   B->factor    = 0;
219   B->assembled = PETSC_TRUE;
220   PetscMemcpy(B->ops,&MatOps,sizeof(struct _MatOps));
221   B->ops->destroy   = MatDestroy_Shell;
222 
223   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
224   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
225   PetscMemzero(b,sizeof(Mat_Shell));
226   B->data   = (void *) b;
227   b->M = M; B->M = M;
228   b->N = N; B->N = N;
229   b->m = m; B->m = m;
230   b->n = n; B->n = n;
231   b->ctx     = ctx;
232   *A = B;
233   PetscFunctionReturn(0);
234 }
235 
236 #undef __FUNC__
237 #define __FUNC__ "MatShellSetOperation"
238 /*@C
239     MatShellSetOperation - Allows user to set a matrix operation for
240                            a shell matrix.
241 
242     Input Parameters:
243 .   mat - the shell matrix
244 .   op - the name of the operation
245 .   f - the function that provides the operation.
246 
247    Collective on Mat
248 
249     Usage:
250 $      extern int usermult(Mat,Vec,Vec);
251 $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
252 $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
253 
254     Notes:
255     See the file petsc/include/mat.h for a complete list of matrix
256     operations, which all have the form MATOP_<OPERATION>, where
257     <OPERATION> is the name (in all capital letters) of the
258     user interface routine (e.g., MatMult() -> MATOP_MULT).
259 
260     All user-provided functions should have the same calling
261     sequence as the usual matrix interface routines, since they
262     are intended to be accessed via the usual matrix interface
263     routines, e.g.,
264 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
265 
266     Within each user-defined routine, the user should call
267     MatShellGetContext() to obtain the user-defined context that was
268     set by MatCreateShell().
269 
270 .keywords: matrix, shell, set, operation
271 
272 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
273 @*/
274 int MatShellSetOperation(Mat mat,MatOperation op, void *f)
275 {
276   PetscFunctionBegin;
277   PetscValidHeaderSpecific(mat,MAT_COOKIE);
278 
279   if (op == MATOP_DESTROY) {
280     if (mat->type == MATSHELL) {
281        Mat_Shell *shell = (Mat_Shell *) mat->data;
282        shell->destroy                 = (int (*)(Mat)) f;
283     }
284     else mat->ops->destroy            = (int (*)(Mat)) f;
285   }
286   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,Viewer)) f;
287   else      (((void**)mat->ops)[op]) = f;
288 
289   PetscFunctionReturn(0);
290 }
291 
292 #undef __FUNC__
293 #define __FUNC__ "MatShellGetOperation"
294 /*@C
295     MatShellGetOperation - Gets a matrix function for a shell matrix.
296 
297     Input Parameters:
298 .   mat - the shell matrix
299 .   op - the name of the operation
300 
301     Output Parameter:
302 .   f - the function that provides the operation.
303 
304     Not Collective
305 
306     Notes:
307     See the file petsc/include/mat.h for a complete list of matrix
308     operations, which all have the form MATOP_<OPERATION>, where
309     <OPERATION> is the name (in all capital letters) of the
310     user interface routine (e.g., MatMult() -> MATOP_MULT).
311 
312     All user-provided functions have the same calling
313     sequence as the usual matrix interface routines, since they
314     are intended to be accessed via the usual matrix interface
315     routines, e.g.,
316 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
317 
318     Within each user-defined routine, the user should call
319     MatShellGetContext() to obtain the user-defined context that was
320     set by MatCreateShell().
321 
322 .keywords: matrix, shell, set, operation
323 
324 .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
325 @*/
326 int MatShellGetOperation(Mat mat,MatOperation op, void **f)
327 {
328   PetscFunctionBegin;
329   PetscValidHeaderSpecific(mat,MAT_COOKIE);
330 
331   if (op == MATOP_DESTROY) {
332     if (mat->type == MATSHELL) {
333        Mat_Shell *shell = (Mat_Shell *) mat->data;
334        *f = (void *) shell->destroy;
335     }
336     else *f = (void *) mat->ops->destroy;
337   }
338   else if (op == MATOP_VIEW) *f = (void *) mat->ops->view;
339   else      *f = (((void**)&mat->ops)[op]);
340 
341   PetscFunctionReturn(0);
342 }
343 
344