xref: /petsc/src/mat/impls/shell/shell.c (revision f830108c1b82f9284b2125d4c9c5a60284ab26f4)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*f830108cSBarry Smith static char vcid[] = "$Id: shell.c,v 1.53 1997/11/28 16:19:55 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 
33a62d957aSLois Curfman McInnes     Notes:
34a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
35a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
36a62d957aSLois Curfman McInnes 
37a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
38a62d957aSLois Curfman McInnes 
39a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation()
40b4fd4287SBarry Smith @*/
41b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx)
42b4fd4287SBarry Smith {
433a40ed3dSBarry Smith   PetscFunctionBegin;
4477c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
45b4fd4287SBarry Smith   if (mat->type != MATSHELL) *ctx = 0;
46b4fd4287SBarry Smith   else                       *ctx = ((Mat_Shell *) (mat->data))->ctx;
473a40ed3dSBarry Smith   PetscFunctionReturn(0);
48b4fd4287SBarry Smith }
49b4fd4287SBarry Smith 
505615d1e5SSatish Balay #undef __FUNC__
51d4bb536fSBarry Smith #define __FUNC__ "MatGetSize_Shell"
528f6be9afSLois Curfman McInnes int MatGetSize_Shell(Mat mat,int *M,int *N)
5371b459e3SLois Curfman McInnes {
5471b459e3SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
553a40ed3dSBarry Smith 
563a40ed3dSBarry Smith   PetscFunctionBegin;
57*f830108cSBarry Smith   if (M) *M = shell->M;
58*f830108cSBarry Smith   if (N) *N = shell->N;
593a40ed3dSBarry Smith   PetscFunctionReturn(0);
60f39d1f56SLois Curfman McInnes }
61f39d1f56SLois Curfman McInnes 
625615d1e5SSatish Balay #undef __FUNC__
63d4bb536fSBarry Smith #define __FUNC__ "MatGetLocalSize_Shell"
648f6be9afSLois Curfman McInnes int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
65f39d1f56SLois Curfman McInnes {
66f39d1f56SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
673a40ed3dSBarry Smith 
683a40ed3dSBarry Smith   PetscFunctionBegin;
69*f830108cSBarry Smith   if (m) *m = shell->m;
70*f830108cSBarry Smith   if (n) *n = shell->n;
713a40ed3dSBarry Smith   PetscFunctionReturn(0);
7271b459e3SLois Curfman McInnes }
7371b459e3SLois Curfman McInnes 
745615d1e5SSatish Balay #undef __FUNC__
75d4bb536fSBarry Smith #define __FUNC__ "MatDestroy_Shell"
768f6be9afSLois Curfman McInnes int MatDestroy_Shell(PetscObject obj)
77e51e0e81SBarry Smith {
78b9fa9cd0SBarry Smith   int       ierr;
7920563c6bSBarry Smith   Mat       mat = (Mat) obj;
8088cf3e7dSBarry Smith   Mat_Shell *shell;
81ed3cc1f0SBarry Smith 
823a40ed3dSBarry Smith   PetscFunctionBegin;
8388cf3e7dSBarry Smith   shell = (Mat_Shell *) mat->data;
843a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
850452661fSBarry Smith   PetscFree(shell);
863a3eedf2SBarry Smith   PLogObjectDestroy(mat);
873a3eedf2SBarry Smith   PetscHeaderDestroy(mat);
883a40ed3dSBarry Smith   PetscFunctionReturn(0);
89e51e0e81SBarry Smith }
90e51e0e81SBarry Smith 
918f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
92b951964fSBarry Smith {
93ca161407SBarry Smith   int ierr;
94ca161407SBarry Smith 
95ca161407SBarry Smith   PetscFunctionBegin;
96ca161407SBarry Smith   ierr = MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr);
97b951964fSBarry Smith   *rstart = *rend - mat->m;
983a40ed3dSBarry Smith   PetscFunctionReturn(0);
99b951964fSBarry Smith }
100b951964fSBarry Smith 
101b951964fSBarry Smith 
102b951964fSBarry Smith 
103b951964fSBarry Smith 
104b951964fSBarry Smith static struct _MatOps MatOps = {0,
10520563c6bSBarry Smith        0,
10620563c6bSBarry Smith        0,
10720563c6bSBarry Smith        0,
10820563c6bSBarry Smith        0,
109b951964fSBarry 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        MatGetSize_Shell,
135b951964fSBarry Smith        MatGetLocalSize_Shell,
136b951964fSBarry Smith        MatGetOwnershipRange_Shell,
137b951964fSBarry Smith        0,
138b951964fSBarry Smith        0,
139b951964fSBarry Smith        0,
140b951964fSBarry Smith        0,
141b951964fSBarry Smith        0 };
142e51e0e81SBarry Smith 
1435615d1e5SSatish Balay #undef __FUNC__
144d4bb536fSBarry Smith #define __FUNC__ "MatCreateShell"
1454b828684SBarry Smith /*@C
146052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
147ff756334SLois Curfman McInnes    private data storage format.
148e51e0e81SBarry Smith 
149e51e0e81SBarry Smith    Input Parameters:
1506b5873e3SBarry Smith .  comm - MPI communicator
151f39d1f56SLois Curfman McInnes .  m - number of local rows
152f39d1f56SLois Curfman McInnes .  n - number of local columns
153f39d1f56SLois Curfman McInnes .  M - number of global rows
154f39d1f56SLois Curfman McInnes .  N - number of global columns
155deebb3c3SLois Curfman McInnes .  ctx - pointer to data needed by the shell matrix routines
156e51e0e81SBarry Smith 
157ff756334SLois Curfman McInnes    Output Parameter:
15844cd7ae7SLois Curfman McInnes .  A - the matrix
159e51e0e81SBarry Smith 
160f39d1f56SLois Curfman McInnes    Usage:
161f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
1621c1c02c0SLois Curfman McInnes $    MatShellSetOperation(mat,MATOP_MULT,mult);
163f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
164f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
165f39d1f56SLois Curfman McInnes 
166ff756334SLois Curfman McInnes    Notes:
167ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
168ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
169ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
170e51e0e81SBarry Smith 
171f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
172f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
173645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
174645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
175645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
176645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
177645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
178645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
179645985a0SLois Curfman McInnes    For example,
180f39d1f56SLois Curfman McInnes 
181f39d1f56SLois Curfman McInnes $
182f39d1f56SLois Curfman McInnes $     Vec x, y
183645985a0SLois Curfman McInnes $     Mat A
184f39d1f56SLois Curfman McInnes $
185522c5e43SBarry Smith $     VecCreate(comm,PETSC_DECIDE,M,&y);
186522c5e43SBarry Smith $     VecCreate(comm,PETSC_DECIDE,N,&x);
187f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
188645985a0SLois Curfman McInnes $     MatCreateShell(comm,m,N,M,N,ctx,&A);
1891c1c02c0SLois Curfman McInnes $     MatShellSetOperation(mat,MATOP_MULT,mult);
190645985a0SLois Curfman McInnes $     MatMult(A,x,y);
191645985a0SLois Curfman McInnes $     MatDestroy(A);
192f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
193645985a0SLois Curfman McInnes $
194e51e0e81SBarry Smith 
1950b627109SLois Curfman McInnes .keywords: matrix, shell, create
1960b627109SLois Curfman McInnes 
1973a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
198e51e0e81SBarry Smith @*/
199f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
200e51e0e81SBarry Smith {
20144cd7ae7SLois Curfman McInnes   Mat       B;
20244cd7ae7SLois Curfman McInnes   Mat_Shell *b;
203ed3cc1f0SBarry Smith 
2043a40ed3dSBarry Smith   PetscFunctionBegin;
205*f830108cSBarry Smith   PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView);
20644cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
20744cd7ae7SLois Curfman McInnes   B->factor    = 0;
20844cd7ae7SLois Curfman McInnes   B->destroy   = MatDestroy_Shell;
20944cd7ae7SLois Curfman McInnes   B->assembled = PETSC_TRUE;
210*f830108cSBarry Smith   PetscMemcpy(B->ops,&MatOps,sizeof(struct _MatOps));
211227d817aSBarry Smith 
21244cd7ae7SLois Curfman McInnes   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
213eed86810SBarry Smith   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
21444cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_Shell));
21544cd7ae7SLois Curfman McInnes   B->data   = (void *) b;
216f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
217f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
218f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
219f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
22044cd7ae7SLois Curfman McInnes   b->ctx     = ctx;
22144cd7ae7SLois Curfman McInnes   *A = B;
2223a40ed3dSBarry Smith   PetscFunctionReturn(0);
223e51e0e81SBarry Smith }
224e51e0e81SBarry Smith 
2255615d1e5SSatish Balay #undef __FUNC__
226d4bb536fSBarry Smith #define __FUNC__ "MatShellSetOperation"
227c16cb8f2SBarry Smith /*@C
2283a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2293a3eedf2SBarry Smith                            a shell matrix.
230e51e0e81SBarry Smith 
231e51e0e81SBarry Smith     Input Parameters:
232fae171e0SBarry Smith .   mat - the shell matrix
233fae171e0SBarry Smith .   op - the name of the operation
234fae171e0SBarry Smith .   f - the function that provides the operation.
235e51e0e81SBarry Smith 
236fae171e0SBarry Smith     Usage:
237a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
238f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
2391c1c02c0SLois Curfman McInnes $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
2400b627109SLois Curfman McInnes 
241a62d957aSLois Curfman McInnes     Notes:
242a62d957aSLois Curfman McInnes     See the file petsc/include/mat.h for a complete list of matrix
2431c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
244a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
2451c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
246a62d957aSLois Curfman McInnes 
247a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
248deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
249deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
250deebb3c3SLois Curfman McInnes     routines, e.g.,
251a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
252a62d957aSLois Curfman McInnes 
253a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
254a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
255a62d957aSLois Curfman McInnes     set by MatCreateShell().
256a62d957aSLois Curfman McInnes 
257a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
258a62d957aSLois Curfman McInnes 
259d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
260e51e0e81SBarry Smith @*/
261fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f)
262e51e0e81SBarry Smith {
2633a40ed3dSBarry Smith   PetscFunctionBegin;
26477c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
265fae171e0SBarry Smith 
2661c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
267a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
268a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell *) mat->data;
2693a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
270a62d957aSLois Curfman McInnes     }
271a62d957aSLois Curfman McInnes     else mat->destroy                 = (int (*)(PetscObject)) f;
272a62d957aSLois Curfman McInnes   }
2731c1c02c0SLois Curfman McInnes   else if (op == MATOP_VIEW) mat->view  = (int (*)(PetscObject,Viewer)) f;
274*f830108cSBarry Smith   else      (((void**)mat->ops)[op]) = f;
275a62d957aSLois Curfman McInnes 
2763a40ed3dSBarry Smith   PetscFunctionReturn(0);
277e51e0e81SBarry Smith }
278f0479e8cSBarry Smith 
279d4bb536fSBarry Smith #undef __FUNC__
280d4bb536fSBarry Smith #define __FUNC__ "MatShellGetOperation"
281d4bb536fSBarry Smith /*@C
282d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
283d4bb536fSBarry Smith 
284d4bb536fSBarry Smith     Input Parameters:
285d4bb536fSBarry Smith .   mat - the shell matrix
286d4bb536fSBarry Smith .   op - the name of the operation
287d4bb536fSBarry Smith 
288d4bb536fSBarry Smith     Output Parameter:
289d4bb536fSBarry Smith .   f - the function that provides the operation.
290d4bb536fSBarry Smith 
291d4bb536fSBarry Smith     Notes:
292d4bb536fSBarry Smith     See the file petsc/include/mat.h for a complete list of matrix
293d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
294d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
295d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
296d4bb536fSBarry Smith 
297d4bb536fSBarry Smith     All user-provided functions have the same calling
298d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
299d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
300d4bb536fSBarry Smith     routines, e.g.,
301d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
302d4bb536fSBarry Smith 
303d4bb536fSBarry Smith     Within each user-defined routine, the user should call
304d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
305d4bb536fSBarry Smith     set by MatCreateShell().
306d4bb536fSBarry Smith 
307d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
308d4bb536fSBarry Smith 
309d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
310d4bb536fSBarry Smith @*/
311d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op, void **f)
312d4bb536fSBarry Smith {
3133a40ed3dSBarry Smith   PetscFunctionBegin;
314d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
315d4bb536fSBarry Smith 
316d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
317d4bb536fSBarry Smith     if (mat->type == MATSHELL) {
318d4bb536fSBarry Smith        Mat_Shell *shell = (Mat_Shell *) mat->data;
319d4bb536fSBarry Smith        *f = (void *) shell->destroy;
320d4bb536fSBarry Smith     }
321d4bb536fSBarry Smith     else *f = (void *) mat->destroy;
322d4bb536fSBarry Smith   }
323d4bb536fSBarry Smith   else if (op == MATOP_VIEW) *f = (void *) mat->view;
324d4bb536fSBarry Smith   else      *f = (((void**)&mat->ops)[op]);
325d4bb536fSBarry Smith 
3263a40ed3dSBarry Smith   PetscFunctionReturn(0);
327d4bb536fSBarry Smith }
328d4bb536fSBarry Smith 
329