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