xref: /petsc/src/mat/impls/shell/shell.c (revision fee21e364a2af8f69c0e7984443fdef19f844ae9)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*fee21e36SBarry Smith static char vcid[] = "$Id: shell.c,v 1.55 1998/04/03 23:15: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 
33*fee21e36SBarry Smith     Not Collective
34*fee21e36SBarry 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;
8488cf3e7dSBarry Smith   shell = (Mat_Shell *) mat->data;
853a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
860452661fSBarry Smith   PetscFree(shell);
873a3eedf2SBarry Smith   PLogObjectDestroy(mat);
883a3eedf2SBarry Smith   PetscHeaderDestroy(mat);
893a40ed3dSBarry Smith   PetscFunctionReturn(0);
90e51e0e81SBarry Smith }
91e51e0e81SBarry Smith 
928f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
93b951964fSBarry Smith {
94ca161407SBarry Smith   int ierr;
95ca161407SBarry Smith 
96ca161407SBarry Smith   PetscFunctionBegin;
97ca161407SBarry Smith   ierr = MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr);
98b951964fSBarry Smith   *rstart = *rend - mat->m;
993a40ed3dSBarry Smith   PetscFunctionReturn(0);
100b951964fSBarry Smith }
101b951964fSBarry Smith 
102b951964fSBarry Smith 
103b951964fSBarry Smith 
104b951964fSBarry Smith 
105b951964fSBarry Smith static struct _MatOps MatOps = {0,
10620563c6bSBarry Smith        0,
10720563c6bSBarry Smith        0,
10820563c6bSBarry Smith        0,
10920563c6bSBarry Smith        0,
110b951964fSBarry Smith        0,
111b951964fSBarry Smith        0,
112b951964fSBarry Smith        0,
113b951964fSBarry Smith        0,
114b951964fSBarry Smith        0,
115b951964fSBarry Smith        0,
116b951964fSBarry Smith        0,
117b951964fSBarry 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        MatGetSize_Shell,
136b951964fSBarry Smith        MatGetLocalSize_Shell,
137b951964fSBarry Smith        MatGetOwnershipRange_Shell,
138b951964fSBarry Smith        0,
139b951964fSBarry Smith        0,
140b951964fSBarry Smith        0,
141b951964fSBarry Smith        0,
142b951964fSBarry Smith        0 };
143e51e0e81SBarry Smith 
1445615d1e5SSatish Balay #undef __FUNC__
145d4bb536fSBarry Smith #define __FUNC__ "MatCreateShell"
1464b828684SBarry Smith /*@C
147052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
148ff756334SLois Curfman McInnes    private data storage format.
149e51e0e81SBarry Smith 
150e51e0e81SBarry Smith    Input Parameters:
1516b5873e3SBarry Smith .  comm - MPI communicator
152f39d1f56SLois Curfman McInnes .  m - number of local rows
153f39d1f56SLois Curfman McInnes .  n - number of local columns
154f39d1f56SLois Curfman McInnes .  M - number of global rows
155f39d1f56SLois Curfman McInnes .  N - number of global columns
156deebb3c3SLois Curfman McInnes .  ctx - pointer to data needed by the shell matrix routines
157e51e0e81SBarry Smith 
158ff756334SLois Curfman McInnes    Output Parameter:
15944cd7ae7SLois Curfman McInnes .  A - the matrix
160e51e0e81SBarry Smith 
161*fee21e36SBarry Smith   Collective on MPI_Comm
162*fee21e36SBarry Smith 
163f39d1f56SLois Curfman McInnes   Usage:
164f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
1651c1c02c0SLois Curfman McInnes $    MatShellSetOperation(mat,MATOP_MULT,mult);
166f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
167f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
168f39d1f56SLois Curfman McInnes 
169ff756334SLois Curfman McInnes    Notes:
170ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
171ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
172ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
173e51e0e81SBarry Smith 
174f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
175f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
176645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
177645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
178645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
179645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
180645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
181645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
182645985a0SLois Curfman McInnes    For example,
183f39d1f56SLois Curfman McInnes 
184f39d1f56SLois Curfman McInnes $
185f39d1f56SLois Curfman McInnes $     Vec x, y
186645985a0SLois Curfman McInnes $     Mat A
187f39d1f56SLois Curfman McInnes $
188522c5e43SBarry Smith $     VecCreate(comm,PETSC_DECIDE,M,&y);
189522c5e43SBarry Smith $     VecCreate(comm,PETSC_DECIDE,N,&x);
190f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
191645985a0SLois Curfman McInnes $     MatCreateShell(comm,m,N,M,N,ctx,&A);
1921c1c02c0SLois Curfman McInnes $     MatShellSetOperation(mat,MATOP_MULT,mult);
193645985a0SLois Curfman McInnes $     MatMult(A,x,y);
194645985a0SLois Curfman McInnes $     MatDestroy(A);
195f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
196645985a0SLois Curfman McInnes $
197e51e0e81SBarry Smith 
1980b627109SLois Curfman McInnes .keywords: matrix, shell, create
1990b627109SLois Curfman McInnes 
2003a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
201e51e0e81SBarry Smith @*/
202f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
203e51e0e81SBarry Smith {
20444cd7ae7SLois Curfman McInnes   Mat       B;
20544cd7ae7SLois Curfman McInnes   Mat_Shell *b;
206ed3cc1f0SBarry Smith 
2073a40ed3dSBarry Smith   PetscFunctionBegin;
208f830108cSBarry Smith   PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView);
20944cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
21044cd7ae7SLois Curfman McInnes   B->factor    = 0;
21144cd7ae7SLois Curfman McInnes   B->assembled = PETSC_TRUE;
212f830108cSBarry Smith   PetscMemcpy(B->ops,&MatOps,sizeof(struct _MatOps));
213e1311b90SBarry Smith   B->ops->destroy   = MatDestroy_Shell;
214227d817aSBarry Smith 
21544cd7ae7SLois Curfman McInnes   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
216eed86810SBarry Smith   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
21744cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_Shell));
21844cd7ae7SLois Curfman McInnes   B->data   = (void *) b;
219f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
220f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
221f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
222f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
22344cd7ae7SLois Curfman McInnes   b->ctx     = ctx;
22444cd7ae7SLois Curfman McInnes   *A = B;
2253a40ed3dSBarry Smith   PetscFunctionReturn(0);
226e51e0e81SBarry Smith }
227e51e0e81SBarry Smith 
2285615d1e5SSatish Balay #undef __FUNC__
229d4bb536fSBarry Smith #define __FUNC__ "MatShellSetOperation"
230c16cb8f2SBarry Smith /*@C
2313a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2323a3eedf2SBarry Smith                            a shell matrix.
233e51e0e81SBarry Smith 
234e51e0e81SBarry Smith     Input Parameters:
235fae171e0SBarry Smith .   mat - the shell matrix
236fae171e0SBarry Smith .   op - the name of the operation
237fae171e0SBarry Smith .   f - the function that provides the operation.
238e51e0e81SBarry Smith 
239*fee21e36SBarry Smith    Collective on Mat
240*fee21e36SBarry Smith 
241fae171e0SBarry Smith     Usage:
242a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
243f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
2441c1c02c0SLois Curfman McInnes $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
2450b627109SLois Curfman McInnes 
246a62d957aSLois Curfman McInnes     Notes:
247a62d957aSLois Curfman McInnes     See the file petsc/include/mat.h for a complete list of matrix
2481c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
249a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
2501c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
251a62d957aSLois Curfman McInnes 
252a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
253deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
254deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
255deebb3c3SLois Curfman McInnes     routines, e.g.,
256a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
257a62d957aSLois Curfman McInnes 
258a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
259a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
260a62d957aSLois Curfman McInnes     set by MatCreateShell().
261a62d957aSLois Curfman McInnes 
262a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
263a62d957aSLois Curfman McInnes 
264d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
265e51e0e81SBarry Smith @*/
266fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f)
267e51e0e81SBarry Smith {
2683a40ed3dSBarry Smith   PetscFunctionBegin;
26977c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
270fae171e0SBarry Smith 
2711c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
272a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
273a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell *) mat->data;
2743a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
275a62d957aSLois Curfman McInnes     }
276e1311b90SBarry Smith     else mat->ops->destroy            = (int (*)(Mat)) f;
277a62d957aSLois Curfman McInnes   }
278e1311b90SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,Viewer)) f;
279f830108cSBarry Smith   else      (((void**)mat->ops)[op]) = f;
280a62d957aSLois Curfman McInnes 
2813a40ed3dSBarry Smith   PetscFunctionReturn(0);
282e51e0e81SBarry Smith }
283f0479e8cSBarry Smith 
284d4bb536fSBarry Smith #undef __FUNC__
285d4bb536fSBarry Smith #define __FUNC__ "MatShellGetOperation"
286d4bb536fSBarry Smith /*@C
287d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
288d4bb536fSBarry Smith 
289d4bb536fSBarry Smith     Input Parameters:
290d4bb536fSBarry Smith .   mat - the shell matrix
291d4bb536fSBarry Smith .   op - the name of the operation
292d4bb536fSBarry Smith 
293d4bb536fSBarry Smith     Output Parameter:
294d4bb536fSBarry Smith .   f - the function that provides the operation.
295d4bb536fSBarry Smith 
296*fee21e36SBarry Smith     Not Collective
297*fee21e36SBarry Smith 
298d4bb536fSBarry Smith     Notes:
299d4bb536fSBarry Smith     See the file petsc/include/mat.h for a complete list of matrix
300d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
301d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
302d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
303d4bb536fSBarry Smith 
304d4bb536fSBarry Smith     All user-provided functions have the same calling
305d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
306d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
307d4bb536fSBarry Smith     routines, e.g.,
308d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
309d4bb536fSBarry Smith 
310d4bb536fSBarry Smith     Within each user-defined routine, the user should call
311d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
312d4bb536fSBarry Smith     set by MatCreateShell().
313d4bb536fSBarry Smith 
314d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
315d4bb536fSBarry Smith 
316d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
317d4bb536fSBarry Smith @*/
318d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op, void **f)
319d4bb536fSBarry Smith {
3203a40ed3dSBarry Smith   PetscFunctionBegin;
321d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
322d4bb536fSBarry Smith 
323d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
324d4bb536fSBarry Smith     if (mat->type == MATSHELL) {
325d4bb536fSBarry Smith        Mat_Shell *shell = (Mat_Shell *) mat->data;
326d4bb536fSBarry Smith        *f = (void *) shell->destroy;
327d4bb536fSBarry Smith     }
328e1311b90SBarry Smith     else *f = (void *) mat->ops->destroy;
329d4bb536fSBarry Smith   }
330e1311b90SBarry Smith   else if (op == MATOP_VIEW) *f = (void *) mat->ops->view;
331d4bb536fSBarry Smith   else      *f = (((void**)&mat->ops)[op]);
332d4bb536fSBarry Smith 
3333a40ed3dSBarry Smith   PetscFunctionReturn(0);
334d4bb536fSBarry Smith }
335d4bb536fSBarry Smith 
336