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