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