xref: /petsc/src/mat/impls/shell/shell.c (revision 3a40ed3dce77c081171d005ae1a6ff4bb9d13b6f)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*3a40ed3dSBarry Smith static char vcid[] = "$Id: shell.c,v 1.50 1997/08/22 15:13:51 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 {
43*3a40ed3dSBarry 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;
47*3a40ed3dSBarry 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;
55*3a40ed3dSBarry Smith 
56*3a40ed3dSBarry Smith   PetscFunctionBegin;
57f39d1f56SLois Curfman McInnes   *M = shell->M; *N = shell->N;
58*3a40ed3dSBarry Smith   PetscFunctionReturn(0);
59f39d1f56SLois Curfman McInnes }
60f39d1f56SLois Curfman McInnes 
615615d1e5SSatish Balay #undef __FUNC__
62d4bb536fSBarry Smith #define __FUNC__ "MatGetLocalSize_Shell"
638f6be9afSLois Curfman McInnes int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
64f39d1f56SLois Curfman McInnes {
65f39d1f56SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
66*3a40ed3dSBarry Smith 
67*3a40ed3dSBarry Smith   PetscFunctionBegin;
68f39d1f56SLois Curfman McInnes   *m = shell->n; *n = shell->n;
69*3a40ed3dSBarry Smith   PetscFunctionReturn(0);
7071b459e3SLois Curfman McInnes }
7171b459e3SLois Curfman McInnes 
725615d1e5SSatish Balay #undef __FUNC__
73d4bb536fSBarry Smith #define __FUNC__ "MatDestroy_Shell"
748f6be9afSLois Curfman McInnes int MatDestroy_Shell(PetscObject obj)
75e51e0e81SBarry Smith {
76b9fa9cd0SBarry Smith   int       ierr;
7720563c6bSBarry Smith   Mat       mat = (Mat) obj;
7888cf3e7dSBarry Smith   Mat_Shell *shell;
79ed3cc1f0SBarry Smith 
80*3a40ed3dSBarry Smith   PetscFunctionBegin;
8188cf3e7dSBarry Smith   shell = (Mat_Shell *) mat->data;
823a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
830452661fSBarry Smith   PetscFree(shell);
843a3eedf2SBarry Smith   PLogObjectDestroy(mat);
853a3eedf2SBarry Smith   PetscHeaderDestroy(mat);
86*3a40ed3dSBarry Smith   PetscFunctionReturn(0);
87e51e0e81SBarry Smith }
88e51e0e81SBarry Smith 
898f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
90b951964fSBarry Smith {
91b951964fSBarry Smith   MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);
92b951964fSBarry Smith   *rstart = *rend - mat->m;
93*3a40ed3dSBarry Smith   PetscFunctionReturn(0);
94b951964fSBarry Smith }
95b951964fSBarry Smith 
96b951964fSBarry Smith 
97b951964fSBarry Smith 
98b951964fSBarry Smith 
99b951964fSBarry Smith static struct _MatOps MatOps = {0,
10020563c6bSBarry Smith        0,
10120563c6bSBarry Smith        0,
10220563c6bSBarry Smith        0,
10320563c6bSBarry Smith        0,
104b951964fSBarry Smith        0,
105b951964fSBarry Smith        0,
106b951964fSBarry Smith        0,
107b951964fSBarry Smith        0,
108b951964fSBarry 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        MatGetSize_Shell,
130b951964fSBarry Smith        MatGetLocalSize_Shell,
131b951964fSBarry Smith        MatGetOwnershipRange_Shell,
132b951964fSBarry Smith        0,
133b951964fSBarry Smith        0,
134b951964fSBarry Smith        0,
135b951964fSBarry Smith        0,
136b951964fSBarry Smith        0 };
137e51e0e81SBarry Smith 
1385615d1e5SSatish Balay #undef __FUNC__
139d4bb536fSBarry Smith #define __FUNC__ "MatCreateShell"
1404b828684SBarry Smith /*@C
141052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
142ff756334SLois Curfman McInnes    private data storage format.
143e51e0e81SBarry Smith 
144e51e0e81SBarry Smith    Input Parameters:
1456b5873e3SBarry Smith .  comm - MPI communicator
146f39d1f56SLois Curfman McInnes .  m - number of local rows
147f39d1f56SLois Curfman McInnes .  n - number of local columns
148f39d1f56SLois Curfman McInnes .  M - number of global rows
149f39d1f56SLois Curfman McInnes .  N - number of global columns
150deebb3c3SLois Curfman McInnes .  ctx - pointer to data needed by the shell matrix routines
151e51e0e81SBarry Smith 
152ff756334SLois Curfman McInnes    Output Parameter:
15344cd7ae7SLois Curfman McInnes .  A - the matrix
154e51e0e81SBarry Smith 
155f39d1f56SLois Curfman McInnes    Usage:
156f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
1571c1c02c0SLois Curfman McInnes $    MatShellSetOperation(mat,MATOP_MULT,mult);
158f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
159f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
160f39d1f56SLois Curfman McInnes 
161ff756334SLois Curfman McInnes    Notes:
162ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
163ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
164ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
165e51e0e81SBarry Smith 
166f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
167f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
168645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
169645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
170645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
171645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
172645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
173645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
174645985a0SLois Curfman McInnes    For example,
175f39d1f56SLois Curfman McInnes 
176f39d1f56SLois Curfman McInnes $
177f39d1f56SLois Curfman McInnes $     Vec x, y
178645985a0SLois Curfman McInnes $     Mat A
179f39d1f56SLois Curfman McInnes $
180f39d1f56SLois Curfman McInnes $     VecCreate(comm,M,&y);
181f39d1f56SLois Curfman McInnes $     VecCreate(comm,N,&x);
182f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
183645985a0SLois Curfman McInnes $     MatCreateShell(comm,m,N,M,N,ctx,&A);
1841c1c02c0SLois Curfman McInnes $     MatShellSetOperation(mat,MATOP_MULT,mult);
185645985a0SLois Curfman McInnes $     MatMult(A,x,y);
186645985a0SLois Curfman McInnes $     MatDestroy(A);
187f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
188645985a0SLois Curfman McInnes $
189e51e0e81SBarry Smith 
1900b627109SLois Curfman McInnes .keywords: matrix, shell, create
1910b627109SLois Curfman McInnes 
1923a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
193e51e0e81SBarry Smith @*/
194f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
195e51e0e81SBarry Smith {
19644cd7ae7SLois Curfman McInnes   Mat       B;
19744cd7ae7SLois Curfman McInnes   Mat_Shell *b;
198ed3cc1f0SBarry Smith 
199*3a40ed3dSBarry Smith   PetscFunctionBegin;
200d4bb536fSBarry Smith   PetscHeaderCreate(B,_p_Mat,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView);
20144cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
20244cd7ae7SLois Curfman McInnes   B->factor    = 0;
20344cd7ae7SLois Curfman McInnes   B->destroy   = MatDestroy_Shell;
20444cd7ae7SLois Curfman McInnes   B->assembled = PETSC_TRUE;
20544cd7ae7SLois Curfman McInnes   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
206227d817aSBarry Smith 
20744cd7ae7SLois Curfman McInnes   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
208eed86810SBarry Smith   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
20944cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_Shell));
21044cd7ae7SLois Curfman McInnes   B->data   = (void *) b;
211f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
212f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
213f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
214f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
21544cd7ae7SLois Curfman McInnes   b->ctx     = ctx;
21644cd7ae7SLois Curfman McInnes   *A = B;
217*3a40ed3dSBarry Smith   PetscFunctionReturn(0);
218e51e0e81SBarry Smith }
219e51e0e81SBarry Smith 
2205615d1e5SSatish Balay #undef __FUNC__
221d4bb536fSBarry Smith #define __FUNC__ "MatShellSetOperation"
222c16cb8f2SBarry Smith /*@C
2233a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2243a3eedf2SBarry Smith                            a shell matrix.
225e51e0e81SBarry Smith 
226e51e0e81SBarry Smith     Input Parameters:
227fae171e0SBarry Smith .   mat - the shell matrix
228fae171e0SBarry Smith .   op - the name of the operation
229fae171e0SBarry Smith .   f - the function that provides the operation.
230e51e0e81SBarry Smith 
231fae171e0SBarry Smith     Usage:
232a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
233f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
2341c1c02c0SLois Curfman McInnes $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
2350b627109SLois Curfman McInnes 
236a62d957aSLois Curfman McInnes     Notes:
237a62d957aSLois Curfman McInnes     See the file petsc/include/mat.h for a complete list of matrix
2381c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
239a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
2401c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
241a62d957aSLois Curfman McInnes 
242a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
243deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
244deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
245deebb3c3SLois Curfman McInnes     routines, e.g.,
246a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
247a62d957aSLois Curfman McInnes 
248a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
249a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
250a62d957aSLois Curfman McInnes     set by MatCreateShell().
251a62d957aSLois Curfman McInnes 
252a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
253a62d957aSLois Curfman McInnes 
254d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
255e51e0e81SBarry Smith @*/
256fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f)
257e51e0e81SBarry Smith {
258*3a40ed3dSBarry Smith   PetscFunctionBegin;
25977c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
260fae171e0SBarry Smith 
2611c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
262a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
263a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell *) mat->data;
2643a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
265a62d957aSLois Curfman McInnes     }
266a62d957aSLois Curfman McInnes     else mat->destroy                 = (int (*)(PetscObject)) f;
267a62d957aSLois Curfman McInnes   }
2681c1c02c0SLois Curfman McInnes   else if (op == MATOP_VIEW) mat->view  = (int (*)(PetscObject,Viewer)) f;
269fae171e0SBarry Smith   else      (((void**)&mat->ops)[op]) = f;
270a62d957aSLois Curfman McInnes 
271*3a40ed3dSBarry Smith   PetscFunctionReturn(0);
272e51e0e81SBarry Smith }
273f0479e8cSBarry Smith 
274d4bb536fSBarry Smith #undef __FUNC__
275d4bb536fSBarry Smith #define __FUNC__ "MatShellGetOperation"
276d4bb536fSBarry Smith /*@C
277d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
278d4bb536fSBarry Smith 
279d4bb536fSBarry Smith     Input Parameters:
280d4bb536fSBarry Smith .   mat - the shell matrix
281d4bb536fSBarry Smith .   op - the name of the operation
282d4bb536fSBarry Smith 
283d4bb536fSBarry Smith     Output Parameter:
284d4bb536fSBarry Smith .   f - the function that provides the operation.
285d4bb536fSBarry Smith 
286d4bb536fSBarry Smith     Notes:
287d4bb536fSBarry Smith     See the file petsc/include/mat.h for a complete list of matrix
288d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
289d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
290d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
291d4bb536fSBarry Smith 
292d4bb536fSBarry Smith     All user-provided functions have the same calling
293d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
294d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
295d4bb536fSBarry Smith     routines, e.g.,
296d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
297d4bb536fSBarry Smith 
298d4bb536fSBarry Smith     Within each user-defined routine, the user should call
299d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
300d4bb536fSBarry Smith     set by MatCreateShell().
301d4bb536fSBarry Smith 
302d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
303d4bb536fSBarry Smith 
304d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
305d4bb536fSBarry Smith @*/
306d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op, void **f)
307d4bb536fSBarry Smith {
308*3a40ed3dSBarry Smith   PetscFunctionBegin;
309d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
310d4bb536fSBarry Smith 
311d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
312d4bb536fSBarry Smith     if (mat->type == MATSHELL) {
313d4bb536fSBarry Smith        Mat_Shell *shell = (Mat_Shell *) mat->data;
314d4bb536fSBarry Smith        *f = (void *) shell->destroy;
315d4bb536fSBarry Smith     }
316d4bb536fSBarry Smith     else *f = (void *) mat->destroy;
317d4bb536fSBarry Smith   }
318d4bb536fSBarry Smith   else if (op == MATOP_VIEW) *f = (void *) mat->view;
319d4bb536fSBarry Smith   else      *f = (((void**)&mat->ops)[op]);
320d4bb536fSBarry Smith 
321*3a40ed3dSBarry Smith   PetscFunctionReturn(0);
322d4bb536fSBarry Smith }
323d4bb536fSBarry Smith 
324