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