xref: /petsc/src/mat/impls/shell/shell.c (revision 09dc009565e93429658382de1b2877c8e5b304ef)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*09dc0095SBarry Smith static char vcid[] = "$Id: shell.c,v 1.57 1998/05/29 20:37:11 bsmith Exp bsmith $";
3357feee3SLois Curfman McInnes #endif
4e51e0e81SBarry Smith 
5e51e0e81SBarry Smith /*
620563c6bSBarry Smith    This provides a simple shell for Fortran (and C programmers) to
720563c6bSBarry Smith   create a very simple matrix class for use with KSP without coding
8ed3cc1f0SBarry Smith   much of anything.
9e51e0e81SBarry Smith */
10e51e0e81SBarry Smith 
11e51e0e81SBarry Smith #include "petsc.h"
1270f55243SBarry Smith #include "src/mat/matimpl.h"        /*I "mat.h" I*/
13f5eb4b81SSatish Balay #include "src/vec/vecimpl.h"
14e51e0e81SBarry Smith 
1520563c6bSBarry Smith typedef struct {
16f39d1f56SLois Curfman McInnes   int  M, N;                  /* number of global rows, columns */
17f39d1f56SLois Curfman McInnes   int  m, n;                  /* number of local rows, columns */
183a3eedf2SBarry Smith   int  (*destroy)(Mat);
1920563c6bSBarry Smith   void *ctx;
2088cf3e7dSBarry Smith } Mat_Shell;
21e51e0e81SBarry Smith 
225615d1e5SSatish Balay #undef __FUNC__
23d4bb536fSBarry Smith #define __FUNC__ "MatShellGetContext"
24b4fd4287SBarry Smith /*@
25a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
26b4fd4287SBarry Smith 
27b4fd4287SBarry Smith     Input Parameter:
28b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
29b4fd4287SBarry Smith 
30b4fd4287SBarry Smith     Output Parameter:
31b4fd4287SBarry Smith .   ctx - the user provided context
32b4fd4287SBarry Smith 
33fee21e36SBarry Smith     Not Collective
34fee21e36SBarry Smith 
35a62d957aSLois Curfman McInnes     Notes:
36a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
37a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
38a62d957aSLois Curfman McInnes 
39a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
40a62d957aSLois Curfman McInnes 
41a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation()
42b4fd4287SBarry Smith @*/
43b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx)
44b4fd4287SBarry Smith {
453a40ed3dSBarry Smith   PetscFunctionBegin;
4677c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
47b4fd4287SBarry Smith   if (mat->type != MATSHELL) *ctx = 0;
48b4fd4287SBarry Smith   else                       *ctx = ((Mat_Shell *) (mat->data))->ctx;
493a40ed3dSBarry Smith   PetscFunctionReturn(0);
50b4fd4287SBarry Smith }
51b4fd4287SBarry Smith 
525615d1e5SSatish Balay #undef __FUNC__
53d4bb536fSBarry Smith #define __FUNC__ "MatGetSize_Shell"
548f6be9afSLois Curfman McInnes int MatGetSize_Shell(Mat mat,int *M,int *N)
5571b459e3SLois Curfman McInnes {
5671b459e3SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
573a40ed3dSBarry Smith 
583a40ed3dSBarry Smith   PetscFunctionBegin;
59f830108cSBarry Smith   if (M) *M = shell->M;
60f830108cSBarry Smith   if (N) *N = shell->N;
613a40ed3dSBarry Smith   PetscFunctionReturn(0);
62f39d1f56SLois Curfman McInnes }
63f39d1f56SLois Curfman McInnes 
645615d1e5SSatish Balay #undef __FUNC__
65d4bb536fSBarry Smith #define __FUNC__ "MatGetLocalSize_Shell"
668f6be9afSLois Curfman McInnes int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
67f39d1f56SLois Curfman McInnes {
68f39d1f56SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
693a40ed3dSBarry Smith 
703a40ed3dSBarry Smith   PetscFunctionBegin;
71f830108cSBarry Smith   if (m) *m = shell->m;
72f830108cSBarry Smith   if (n) *n = shell->n;
733a40ed3dSBarry Smith   PetscFunctionReturn(0);
7471b459e3SLois Curfman McInnes }
7571b459e3SLois Curfman McInnes 
765615d1e5SSatish Balay #undef __FUNC__
77d4bb536fSBarry Smith #define __FUNC__ "MatDestroy_Shell"
78e1311b90SBarry Smith int MatDestroy_Shell(Mat mat)
79e51e0e81SBarry Smith {
80b9fa9cd0SBarry Smith   int       ierr;
8188cf3e7dSBarry Smith   Mat_Shell *shell;
82ed3cc1f0SBarry Smith 
833a40ed3dSBarry Smith   PetscFunctionBegin;
8494d884c6SBarry Smith   if (--mat->refct > 0) PetscFunctionReturn(0);
8594d884c6SBarry Smith 
8694d884c6SBarry Smith   if (mat->mapping) {
8794d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->mapping); CHKERRQ(ierr);
8894d884c6SBarry Smith   }
8994d884c6SBarry Smith   if (mat->bmapping) {
9094d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->bmapping); CHKERRQ(ierr);
9194d884c6SBarry Smith   }
9288cf3e7dSBarry Smith   shell = (Mat_Shell *) mat->data;
933a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
940452661fSBarry Smith   PetscFree(shell);
953a3eedf2SBarry Smith   PLogObjectDestroy(mat);
963a3eedf2SBarry Smith   PetscHeaderDestroy(mat);
973a40ed3dSBarry Smith   PetscFunctionReturn(0);
98e51e0e81SBarry Smith }
99e51e0e81SBarry Smith 
1008f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
101b951964fSBarry Smith {
102ca161407SBarry Smith   int ierr;
103ca161407SBarry Smith 
104ca161407SBarry Smith   PetscFunctionBegin;
105ca161407SBarry Smith   ierr = MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr);
106b951964fSBarry Smith   *rstart = *rend - mat->m;
1073a40ed3dSBarry Smith   PetscFunctionReturn(0);
108b951964fSBarry Smith }
109b951964fSBarry Smith 
110b951964fSBarry Smith 
111b951964fSBarry Smith 
112b951964fSBarry Smith 
113*09dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
11420563c6bSBarry Smith        0,
11520563c6bSBarry Smith        0,
11620563c6bSBarry Smith        0,
11720563c6bSBarry Smith        0,
118b951964fSBarry Smith        0,
119b951964fSBarry Smith        0,
120b951964fSBarry Smith        0,
121b951964fSBarry Smith        0,
122b951964fSBarry Smith        0,
123b951964fSBarry Smith        0,
124b951964fSBarry Smith        0,
125b951964fSBarry Smith        0,
126b951964fSBarry Smith        0,
127b951964fSBarry Smith        0,
128b951964fSBarry Smith        0,
129b951964fSBarry Smith        0,
130b951964fSBarry Smith        0,
131b951964fSBarry Smith        0,
132b951964fSBarry Smith        0,
133b951964fSBarry Smith        0,
134b951964fSBarry Smith        0,
135b951964fSBarry Smith        0,
136b951964fSBarry Smith        0,
137b951964fSBarry Smith        0,
138b951964fSBarry Smith        0,
139b951964fSBarry Smith        0,
140b951964fSBarry Smith        0,
141b951964fSBarry Smith        0,
142b951964fSBarry Smith        0,
143b951964fSBarry Smith        MatGetSize_Shell,
144b951964fSBarry Smith        MatGetLocalSize_Shell,
145b951964fSBarry Smith        MatGetOwnershipRange_Shell,
146b951964fSBarry Smith        0,
147b951964fSBarry Smith        0,
148b951964fSBarry Smith        0,
149b951964fSBarry Smith        0,
150*09dc0095SBarry Smith        0,
151*09dc0095SBarry Smith        0,
152*09dc0095SBarry Smith        0,
153*09dc0095SBarry Smith        0,
154*09dc0095SBarry Smith        0,
155*09dc0095SBarry Smith        0,
156*09dc0095SBarry Smith        0,
157*09dc0095SBarry Smith        0,
158*09dc0095SBarry Smith        0,
159*09dc0095SBarry Smith        0,
160*09dc0095SBarry Smith        0,
161*09dc0095SBarry Smith        0,
162*09dc0095SBarry Smith        0,
163*09dc0095SBarry Smith        0,
164*09dc0095SBarry Smith        0,
165*09dc0095SBarry Smith        0,
166*09dc0095SBarry Smith        0,
167*09dc0095SBarry Smith        0,
168*09dc0095SBarry Smith        0,
169*09dc0095SBarry Smith        0,
170*09dc0095SBarry Smith        0,
171*09dc0095SBarry Smith        0,
172*09dc0095SBarry Smith        0,
173*09dc0095SBarry Smith        0,
174*09dc0095SBarry Smith        0,
175*09dc0095SBarry Smith        0,
176*09dc0095SBarry Smith        0,
177*09dc0095SBarry Smith        0,
178*09dc0095SBarry Smith        MatGetMaps_Petsc};
179e51e0e81SBarry Smith 
1805615d1e5SSatish Balay #undef __FUNC__
181d4bb536fSBarry Smith #define __FUNC__ "MatCreateShell"
1824b828684SBarry Smith /*@C
183052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
184ff756334SLois Curfman McInnes    private data storage format.
185e51e0e81SBarry Smith 
186e51e0e81SBarry Smith    Input Parameters:
1876b5873e3SBarry Smith .  comm - MPI communicator
188f39d1f56SLois Curfman McInnes .  m - number of local rows
189f39d1f56SLois Curfman McInnes .  n - number of local columns
190f39d1f56SLois Curfman McInnes .  M - number of global rows
191f39d1f56SLois Curfman McInnes .  N - number of global columns
192deebb3c3SLois Curfman McInnes .  ctx - pointer to data needed by the shell matrix routines
193e51e0e81SBarry Smith 
194ff756334SLois Curfman McInnes    Output Parameter:
19544cd7ae7SLois Curfman McInnes .  A - the matrix
196e51e0e81SBarry Smith 
197fee21e36SBarry Smith   Collective on MPI_Comm
198fee21e36SBarry Smith 
199f39d1f56SLois Curfman McInnes   Usage:
200f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
2011c1c02c0SLois Curfman McInnes $    MatShellSetOperation(mat,MATOP_MULT,mult);
202f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
203f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
204f39d1f56SLois Curfman McInnes 
205ff756334SLois Curfman McInnes    Notes:
206ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
207ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
208ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
209e51e0e81SBarry Smith 
210f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
211f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
212645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
213645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
214645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
215645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
216645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
217645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
218645985a0SLois Curfman McInnes    For example,
219f39d1f56SLois Curfman McInnes 
220f39d1f56SLois Curfman McInnes $
221f39d1f56SLois Curfman McInnes $     Vec x, y
222645985a0SLois Curfman McInnes $     Mat A
223f39d1f56SLois Curfman McInnes $
224522c5e43SBarry Smith $     VecCreate(comm,PETSC_DECIDE,M,&y);
225522c5e43SBarry Smith $     VecCreate(comm,PETSC_DECIDE,N,&x);
226f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
227645985a0SLois Curfman McInnes $     MatCreateShell(comm,m,N,M,N,ctx,&A);
2281c1c02c0SLois Curfman McInnes $     MatShellSetOperation(mat,MATOP_MULT,mult);
229645985a0SLois Curfman McInnes $     MatMult(A,x,y);
230645985a0SLois Curfman McInnes $     MatDestroy(A);
231f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
232645985a0SLois Curfman McInnes $
233e51e0e81SBarry Smith 
2340b627109SLois Curfman McInnes .keywords: matrix, shell, create
2350b627109SLois Curfman McInnes 
2363a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
237e51e0e81SBarry Smith @*/
238f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
239e51e0e81SBarry Smith {
24044cd7ae7SLois Curfman McInnes   Mat       B;
24144cd7ae7SLois Curfman McInnes   Mat_Shell *b;
242ed3cc1f0SBarry Smith 
2433a40ed3dSBarry Smith   PetscFunctionBegin;
244f830108cSBarry Smith   PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView);
24544cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
24644cd7ae7SLois Curfman McInnes   B->factor    = 0;
24744cd7ae7SLois Curfman McInnes   B->assembled = PETSC_TRUE;
248*09dc0095SBarry Smith   PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
249e1311b90SBarry Smith   B->ops->destroy   = MatDestroy_Shell;
250227d817aSBarry Smith 
25144cd7ae7SLois Curfman McInnes   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
252eed86810SBarry Smith   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
25344cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_Shell));
25444cd7ae7SLois Curfman McInnes   B->data   = (void *) b;
255f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
256f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
257f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
258f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
25944cd7ae7SLois Curfman McInnes   b->ctx     = ctx;
26044cd7ae7SLois Curfman McInnes   *A = B;
2613a40ed3dSBarry Smith   PetscFunctionReturn(0);
262e51e0e81SBarry Smith }
263e51e0e81SBarry Smith 
2645615d1e5SSatish Balay #undef __FUNC__
265d4bb536fSBarry Smith #define __FUNC__ "MatShellSetOperation"
266c16cb8f2SBarry Smith /*@C
2673a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2683a3eedf2SBarry Smith                            a shell matrix.
269e51e0e81SBarry Smith 
270e51e0e81SBarry Smith     Input Parameters:
271fae171e0SBarry Smith .   mat - the shell matrix
272fae171e0SBarry Smith .   op - the name of the operation
273fae171e0SBarry Smith .   f - the function that provides the operation.
274e51e0e81SBarry Smith 
275fee21e36SBarry Smith    Collective on Mat
276fee21e36SBarry Smith 
277fae171e0SBarry Smith     Usage:
278a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
279f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
2801c1c02c0SLois Curfman McInnes $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
2810b627109SLois Curfman McInnes 
282a62d957aSLois Curfman McInnes     Notes:
283a62d957aSLois Curfman McInnes     See the file petsc/include/mat.h for a complete list of matrix
2841c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
285a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
2861c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
287a62d957aSLois Curfman McInnes 
288a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
289deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
290deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
291deebb3c3SLois Curfman McInnes     routines, e.g.,
292a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
293a62d957aSLois Curfman McInnes 
294a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
295a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
296a62d957aSLois Curfman McInnes     set by MatCreateShell().
297a62d957aSLois Curfman McInnes 
298a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
299a62d957aSLois Curfman McInnes 
300d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
301e51e0e81SBarry Smith @*/
302fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f)
303e51e0e81SBarry Smith {
3043a40ed3dSBarry Smith   PetscFunctionBegin;
30577c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
306fae171e0SBarry Smith 
3071c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
308a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
309a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell *) mat->data;
3103a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
311a62d957aSLois Curfman McInnes     }
312e1311b90SBarry Smith     else mat->ops->destroy            = (int (*)(Mat)) f;
313a62d957aSLois Curfman McInnes   }
314e1311b90SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,Viewer)) f;
315f830108cSBarry Smith   else      (((void**)mat->ops)[op]) = f;
316a62d957aSLois Curfman McInnes 
3173a40ed3dSBarry Smith   PetscFunctionReturn(0);
318e51e0e81SBarry Smith }
319f0479e8cSBarry Smith 
320d4bb536fSBarry Smith #undef __FUNC__
321d4bb536fSBarry Smith #define __FUNC__ "MatShellGetOperation"
322d4bb536fSBarry Smith /*@C
323d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
324d4bb536fSBarry Smith 
325d4bb536fSBarry Smith     Input Parameters:
326d4bb536fSBarry Smith .   mat - the shell matrix
327d4bb536fSBarry Smith .   op - the name of the operation
328d4bb536fSBarry Smith 
329d4bb536fSBarry Smith     Output Parameter:
330d4bb536fSBarry Smith .   f - the function that provides the operation.
331d4bb536fSBarry Smith 
332fee21e36SBarry Smith     Not Collective
333fee21e36SBarry Smith 
334d4bb536fSBarry Smith     Notes:
335d4bb536fSBarry Smith     See the file petsc/include/mat.h for a complete list of matrix
336d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
337d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
338d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
339d4bb536fSBarry Smith 
340d4bb536fSBarry Smith     All user-provided functions have the same calling
341d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
342d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
343d4bb536fSBarry Smith     routines, e.g.,
344d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
345d4bb536fSBarry Smith 
346d4bb536fSBarry Smith     Within each user-defined routine, the user should call
347d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
348d4bb536fSBarry Smith     set by MatCreateShell().
349d4bb536fSBarry Smith 
350d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
351d4bb536fSBarry Smith 
352d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
353d4bb536fSBarry Smith @*/
354d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op, void **f)
355d4bb536fSBarry Smith {
3563a40ed3dSBarry Smith   PetscFunctionBegin;
357d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
358d4bb536fSBarry Smith 
359d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
360d4bb536fSBarry Smith     if (mat->type == MATSHELL) {
361d4bb536fSBarry Smith        Mat_Shell *shell = (Mat_Shell *) mat->data;
362d4bb536fSBarry Smith        *f = (void *) shell->destroy;
363d4bb536fSBarry Smith     }
364e1311b90SBarry Smith     else *f = (void *) mat->ops->destroy;
365d4bb536fSBarry Smith   }
366e1311b90SBarry Smith   else if (op == MATOP_VIEW) *f = (void *) mat->ops->view;
367d4bb536fSBarry Smith   else      *f = (((void**)&mat->ops)[op]);
368d4bb536fSBarry Smith 
3693a40ed3dSBarry Smith   PetscFunctionReturn(0);
370d4bb536fSBarry Smith }
371d4bb536fSBarry Smith 
372