xref: /petsc/src/mat/impls/shell/shell.c (revision d4bb536f0e426e9a0292bbfd5743770a9b03f0d5)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*d4bb536fSBarry Smith static char vcid[] = "$Id: shell.c,v 1.49 1997/07/09 20:54:17 balay 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__
23*d4bb536fSBarry 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 {
4377c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
44b4fd4287SBarry Smith   if (mat->type != MATSHELL) *ctx = 0;
45b4fd4287SBarry Smith   else                       *ctx = ((Mat_Shell *) (mat->data))->ctx;
46b4fd4287SBarry Smith   return 0;
47b4fd4287SBarry Smith }
48b4fd4287SBarry Smith 
495615d1e5SSatish Balay #undef __FUNC__
50*d4bb536fSBarry Smith #define __FUNC__ "MatGetSize_Shell"
518f6be9afSLois Curfman McInnes int MatGetSize_Shell(Mat mat,int *M,int *N)
5271b459e3SLois Curfman McInnes {
5371b459e3SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
54f39d1f56SLois Curfman McInnes   *M = shell->M; *N = shell->N;
55f39d1f56SLois Curfman McInnes   return 0;
56f39d1f56SLois Curfman McInnes }
57f39d1f56SLois Curfman McInnes 
585615d1e5SSatish Balay #undef __FUNC__
59*d4bb536fSBarry Smith #define __FUNC__ "MatGetLocalSize_Shell"
608f6be9afSLois Curfman McInnes int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
61f39d1f56SLois Curfman McInnes {
62f39d1f56SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
63f39d1f56SLois Curfman McInnes   *m = shell->n; *n = shell->n;
6471b459e3SLois Curfman McInnes   return 0;
6571b459e3SLois Curfman McInnes }
6671b459e3SLois Curfman McInnes 
675615d1e5SSatish Balay #undef __FUNC__
68*d4bb536fSBarry Smith #define __FUNC__ "MatDestroy_Shell"
698f6be9afSLois Curfman McInnes int MatDestroy_Shell(PetscObject obj)
70e51e0e81SBarry Smith {
71b9fa9cd0SBarry Smith   int       ierr;
7220563c6bSBarry Smith   Mat       mat = (Mat) obj;
7388cf3e7dSBarry Smith   Mat_Shell *shell;
74ed3cc1f0SBarry Smith 
7588cf3e7dSBarry Smith   shell = (Mat_Shell *) mat->data;
763a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
770452661fSBarry Smith   PetscFree(shell);
783a3eedf2SBarry Smith   PLogObjectDestroy(mat);
793a3eedf2SBarry Smith   PetscHeaderDestroy(mat);
80e51e0e81SBarry Smith   return 0;
81e51e0e81SBarry Smith }
82e51e0e81SBarry Smith 
838f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
84b951964fSBarry Smith {
85b951964fSBarry Smith   MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);
86b951964fSBarry Smith   *rstart = *rend - mat->m;
87b951964fSBarry Smith   return 0;
88b951964fSBarry Smith }
89b951964fSBarry Smith 
90b951964fSBarry Smith 
91b951964fSBarry Smith 
92b951964fSBarry Smith 
93b951964fSBarry Smith static struct _MatOps MatOps = {0,
9420563c6bSBarry Smith        0,
9520563c6bSBarry Smith        0,
9620563c6bSBarry Smith        0,
9720563c6bSBarry Smith        0,
98b951964fSBarry Smith        0,
99b951964fSBarry Smith        0,
100b951964fSBarry Smith        0,
101b951964fSBarry Smith        0,
102b951964fSBarry Smith        0,
103b951964fSBarry 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        MatGetSize_Shell,
124b951964fSBarry Smith        MatGetLocalSize_Shell,
125b951964fSBarry Smith        MatGetOwnershipRange_Shell,
126b951964fSBarry Smith        0,
127b951964fSBarry Smith        0,
128b951964fSBarry Smith        0,
129b951964fSBarry Smith        0,
130b951964fSBarry Smith        0 };
131e51e0e81SBarry Smith 
1325615d1e5SSatish Balay #undef __FUNC__
133*d4bb536fSBarry Smith #define __FUNC__ "MatCreateShell"
1344b828684SBarry Smith /*@C
135052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
136ff756334SLois Curfman McInnes    private data storage format.
137e51e0e81SBarry Smith 
138e51e0e81SBarry Smith    Input Parameters:
1396b5873e3SBarry Smith .  comm - MPI communicator
140f39d1f56SLois Curfman McInnes .  m - number of local rows
141f39d1f56SLois Curfman McInnes .  n - number of local columns
142f39d1f56SLois Curfman McInnes .  M - number of global rows
143f39d1f56SLois Curfman McInnes .  N - number of global columns
144deebb3c3SLois Curfman McInnes .  ctx - pointer to data needed by the shell matrix routines
145e51e0e81SBarry Smith 
146ff756334SLois Curfman McInnes    Output Parameter:
14744cd7ae7SLois Curfman McInnes .  A - the matrix
148e51e0e81SBarry Smith 
149f39d1f56SLois Curfman McInnes    Usage:
150f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
1511c1c02c0SLois Curfman McInnes $    MatShellSetOperation(mat,MATOP_MULT,mult);
152f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
153f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
154f39d1f56SLois Curfman McInnes 
155ff756334SLois Curfman McInnes    Notes:
156ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
157ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
158ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
159e51e0e81SBarry Smith 
160f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
161f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
162645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
163645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
164645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
165645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
166645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
167645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
168645985a0SLois Curfman McInnes    For example,
169f39d1f56SLois Curfman McInnes 
170f39d1f56SLois Curfman McInnes $
171f39d1f56SLois Curfman McInnes $     Vec x, y
172645985a0SLois Curfman McInnes $     Mat A
173f39d1f56SLois Curfman McInnes $
174f39d1f56SLois Curfman McInnes $     VecCreate(comm,M,&y);
175f39d1f56SLois Curfman McInnes $     VecCreate(comm,N,&x);
176f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
177645985a0SLois Curfman McInnes $     MatCreateShell(comm,m,N,M,N,ctx,&A);
1781c1c02c0SLois Curfman McInnes $     MatShellSetOperation(mat,MATOP_MULT,mult);
179645985a0SLois Curfman McInnes $     MatMult(A,x,y);
180645985a0SLois Curfman McInnes $     MatDestroy(A);
181f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
182645985a0SLois Curfman McInnes $
183e51e0e81SBarry Smith 
1840b627109SLois Curfman McInnes .keywords: matrix, shell, create
1850b627109SLois Curfman McInnes 
1863a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
187e51e0e81SBarry Smith @*/
188f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
189e51e0e81SBarry Smith {
19044cd7ae7SLois Curfman McInnes   Mat       B;
19144cd7ae7SLois Curfman McInnes   Mat_Shell *b;
192ed3cc1f0SBarry Smith 
193*d4bb536fSBarry Smith   PetscHeaderCreate(B,_p_Mat,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView);
19444cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
19544cd7ae7SLois Curfman McInnes   B->factor    = 0;
19644cd7ae7SLois Curfman McInnes   B->destroy   = MatDestroy_Shell;
19744cd7ae7SLois Curfman McInnes   B->assembled = PETSC_TRUE;
19844cd7ae7SLois Curfman McInnes   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
199227d817aSBarry Smith 
20044cd7ae7SLois Curfman McInnes   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
201eed86810SBarry Smith   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
20244cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_Shell));
20344cd7ae7SLois Curfman McInnes   B->data   = (void *) b;
204f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
205f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
206f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
207f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
20844cd7ae7SLois Curfman McInnes   b->ctx     = ctx;
20944cd7ae7SLois Curfman McInnes   *A = B;
210e51e0e81SBarry Smith   return 0;
211e51e0e81SBarry Smith }
212e51e0e81SBarry Smith 
2135615d1e5SSatish Balay #undef __FUNC__
214*d4bb536fSBarry Smith #define __FUNC__ "MatShellSetOperation"
215c16cb8f2SBarry Smith /*@C
2163a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2173a3eedf2SBarry Smith                            a shell matrix.
218e51e0e81SBarry Smith 
219e51e0e81SBarry Smith     Input Parameters:
220fae171e0SBarry Smith .   mat - the shell matrix
221fae171e0SBarry Smith .   op - the name of the operation
222fae171e0SBarry Smith .   f - the function that provides the operation.
223e51e0e81SBarry Smith 
224fae171e0SBarry Smith     Usage:
225a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
226f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
2271c1c02c0SLois Curfman McInnes $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
2280b627109SLois Curfman McInnes 
229a62d957aSLois Curfman McInnes     Notes:
230a62d957aSLois Curfman McInnes     See the file petsc/include/mat.h for a complete list of matrix
2311c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
232a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
2331c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
234a62d957aSLois Curfman McInnes 
235a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
236deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
237deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
238deebb3c3SLois Curfman McInnes     routines, e.g.,
239a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
240a62d957aSLois Curfman McInnes 
241a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
242a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
243a62d957aSLois Curfman McInnes     set by MatCreateShell().
244a62d957aSLois Curfman McInnes 
245a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
246a62d957aSLois Curfman McInnes 
247*d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
248e51e0e81SBarry Smith @*/
249fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f)
250e51e0e81SBarry Smith {
25177c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
252fae171e0SBarry Smith 
2531c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
254a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
255a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell *) mat->data;
2563a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
257a62d957aSLois Curfman McInnes     }
258a62d957aSLois Curfman McInnes     else mat->destroy                 = (int (*)(PetscObject)) f;
259a62d957aSLois Curfman McInnes   }
2601c1c02c0SLois Curfman McInnes   else if (op == MATOP_VIEW) mat->view  = (int (*)(PetscObject,Viewer)) f;
261fae171e0SBarry Smith   else      (((void**)&mat->ops)[op]) = f;
262a62d957aSLois Curfman McInnes 
26320563c6bSBarry Smith   return 0;
264e51e0e81SBarry Smith }
265f0479e8cSBarry Smith 
2663a3eedf2SBarry Smith 
2673a3eedf2SBarry Smith 
268*d4bb536fSBarry Smith #undef __FUNC__
269*d4bb536fSBarry Smith #define __FUNC__ "MatShellGetOperation"
270*d4bb536fSBarry Smith /*@C
271*d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
272*d4bb536fSBarry Smith 
273*d4bb536fSBarry Smith     Input Parameters:
274*d4bb536fSBarry Smith .   mat - the shell matrix
275*d4bb536fSBarry Smith .   op - the name of the operation
276*d4bb536fSBarry Smith 
277*d4bb536fSBarry Smith     Output Parameter:
278*d4bb536fSBarry Smith .   f - the function that provides the operation.
279*d4bb536fSBarry Smith 
280*d4bb536fSBarry Smith     Notes:
281*d4bb536fSBarry Smith     See the file petsc/include/mat.h for a complete list of matrix
282*d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
283*d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
284*d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
285*d4bb536fSBarry Smith 
286*d4bb536fSBarry Smith     All user-provided functions have the same calling
287*d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
288*d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
289*d4bb536fSBarry Smith     routines, e.g.,
290*d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
291*d4bb536fSBarry Smith 
292*d4bb536fSBarry Smith     Within each user-defined routine, the user should call
293*d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
294*d4bb536fSBarry Smith     set by MatCreateShell().
295*d4bb536fSBarry Smith 
296*d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
297*d4bb536fSBarry Smith 
298*d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
299*d4bb536fSBarry Smith @*/
300*d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op, void **f)
301*d4bb536fSBarry Smith {
302*d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
303*d4bb536fSBarry Smith 
304*d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
305*d4bb536fSBarry Smith     if (mat->type == MATSHELL) {
306*d4bb536fSBarry Smith        Mat_Shell *shell = (Mat_Shell *) mat->data;
307*d4bb536fSBarry Smith        *f = (void *) shell->destroy;
308*d4bb536fSBarry Smith     }
309*d4bb536fSBarry Smith     else *f = (void *) mat->destroy;
310*d4bb536fSBarry Smith   }
311*d4bb536fSBarry Smith   else if (op == MATOP_VIEW) *f = (void *) mat->view;
312*d4bb536fSBarry Smith   else      *f = (((void**)&mat->ops)[op]);
313*d4bb536fSBarry Smith 
314*d4bb536fSBarry Smith   return 0;
315*d4bb536fSBarry Smith }
316*d4bb536fSBarry Smith 
317