xref: /petsc/src/mat/impls/shell/shell.c (revision b2863d3a52358f7ee22ca3a1f84f250141973e94)
1*b2863d3aSBarry Smith /*$Id: shell.c,v 1.77 2000/02/02 20:09:02 bsmith Exp bsmith $*/
2e51e0e81SBarry Smith 
3e51e0e81SBarry Smith /*
420563c6bSBarry Smith    This provides a simple shell for Fortran (and C programmers) to
520563c6bSBarry Smith   create a very simple matrix class for use with KSP without coding
6ed3cc1f0SBarry Smith   much of anything.
7e51e0e81SBarry Smith */
8e51e0e81SBarry Smith 
970f55243SBarry Smith #include "src/mat/matimpl.h"        /*I "mat.h" I*/
10f5eb4b81SSatish Balay #include "src/vec/vecimpl.h"
11e51e0e81SBarry Smith 
1220563c6bSBarry Smith typedef struct {
13f39d1f56SLois Curfman McInnes   int  M,N;                  /* number of global rows, columns */
14f39d1f56SLois Curfman McInnes   int  m,n;                  /* number of local rows, columns */
153a3eedf2SBarry Smith   int  (*destroy)(Mat);
1620563c6bSBarry Smith   void *ctx;
1788cf3e7dSBarry Smith } Mat_Shell;
18e51e0e81SBarry Smith 
195615d1e5SSatish Balay #undef __FUNC__
20*b2863d3aSBarry Smith #define  __FUNC__ /*<a name=""></a>*/"MatShellGetContext"
21b4fd4287SBarry Smith /*@
22a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
23b4fd4287SBarry Smith 
24c7fcc2eaSBarry Smith     Not Collective
25c7fcc2eaSBarry Smith 
26b4fd4287SBarry Smith     Input Parameter:
27b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
28b4fd4287SBarry Smith 
29b4fd4287SBarry Smith     Output Parameter:
30b4fd4287SBarry Smith .   ctx - the user provided context
31b4fd4287SBarry Smith 
3215091d37SBarry Smith     Level: advanced
3315091d37SBarry Smith 
34a62d957aSLois Curfman McInnes     Notes:
35a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
36a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
37a62d957aSLois Curfman McInnes 
38a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
39a62d957aSLois Curfman McInnes 
40a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation()
41b4fd4287SBarry Smith @*/
42b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx)
43b4fd4287SBarry Smith {
443a40ed3dSBarry Smith   PetscFunctionBegin;
4577c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
46b4fd4287SBarry Smith   if (mat->type != MATSHELL) *ctx = 0;
47b4fd4287SBarry Smith   else                       *ctx = ((Mat_Shell*)(mat->data))->ctx;
483a40ed3dSBarry Smith   PetscFunctionReturn(0);
49b4fd4287SBarry Smith }
50b4fd4287SBarry Smith 
515615d1e5SSatish Balay #undef __FUNC__
52*b2863d3aSBarry Smith #define  __FUNC__ /*<a name=""></a>*/"MatGetSize_Shell"
538f6be9afSLois Curfman McInnes int MatGetSize_Shell(Mat mat,int *M,int *N)
5471b459e3SLois Curfman McInnes {
5571b459e3SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell*)mat->data;
563a40ed3dSBarry Smith 
573a40ed3dSBarry Smith   PetscFunctionBegin;
58f830108cSBarry Smith   if (M) *M = shell->M;
59f830108cSBarry Smith   if (N) *N = shell->N;
603a40ed3dSBarry Smith   PetscFunctionReturn(0);
61f39d1f56SLois Curfman McInnes }
62f39d1f56SLois Curfman McInnes 
635615d1e5SSatish Balay #undef __FUNC__
64*b2863d3aSBarry Smith #define  __FUNC__ /*<a name=""></a>*/"MatGetLocalSize_Shell"
658f6be9afSLois Curfman McInnes int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
66f39d1f56SLois Curfman McInnes {
67f39d1f56SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell*)mat->data;
683a40ed3dSBarry Smith 
693a40ed3dSBarry Smith   PetscFunctionBegin;
70f830108cSBarry Smith   if (m) *m = shell->m;
71f830108cSBarry Smith   if (n) *n = shell->n;
723a40ed3dSBarry Smith   PetscFunctionReturn(0);
7371b459e3SLois Curfman McInnes }
7471b459e3SLois Curfman McInnes 
755615d1e5SSatish Balay #undef __FUNC__
76*b2863d3aSBarry Smith #define  __FUNC__ /*<a name=""></a>*/"MatDestroy_Shell"
77e1311b90SBarry Smith int MatDestroy_Shell(Mat mat)
78e51e0e81SBarry Smith {
79b9fa9cd0SBarry Smith   int       ierr;
8088cf3e7dSBarry Smith   Mat_Shell *shell;
81ed3cc1f0SBarry Smith 
823a40ed3dSBarry Smith   PetscFunctionBegin;
8394d884c6SBarry Smith 
8494d884c6SBarry Smith   if (mat->mapping) {
8594d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->mapping);CHKERRQ(ierr);
8694d884c6SBarry Smith   }
8794d884c6SBarry Smith   if (mat->bmapping) {
8894d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->bmapping);CHKERRQ(ierr);
8994d884c6SBarry Smith   }
9061b13de0SBarry Smith   if (mat->rmap) {
9161b13de0SBarry Smith     ierr = MapDestroy(mat->rmap);CHKERRQ(ierr);
9261b13de0SBarry Smith   }
9361b13de0SBarry Smith   if (mat->cmap) {
9461b13de0SBarry Smith     ierr = MapDestroy(mat->cmap);CHKERRQ(ierr);
9561b13de0SBarry Smith   }
9688cf3e7dSBarry Smith   shell = (Mat_Shell*)mat->data;
973a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
98606d414cSSatish Balay   ierr = PetscFree(shell);CHKERRQ(ierr);
993a3eedf2SBarry Smith   PLogObjectDestroy(mat);
1003a3eedf2SBarry Smith   PetscHeaderDestroy(mat);
1013a40ed3dSBarry Smith   PetscFunctionReturn(0);
102e51e0e81SBarry Smith }
103e51e0e81SBarry Smith 
104433994e6SBarry Smith #undef __FUNC__
105*b2863d3aSBarry Smith #define  __FUNC__ /*<a name=""></a>*/"MatGetOwnershipRange_Shell"
1068f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat,int *rstart,int *rend)
107b951964fSBarry Smith {
1084c49b128SBarry Smith   int ierr,tmp;
109ca161407SBarry Smith 
110ca161407SBarry Smith   PetscFunctionBegin;
1114c49b128SBarry Smith   ierr = MPI_Scan(&mat->m,&tmp,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr);
1124c49b128SBarry Smith   if (rstart) *rstart = tmp - mat->m;
1134c49b128SBarry Smith   if (rend)   *rend   = tmp;
1143a40ed3dSBarry Smith   PetscFunctionReturn(0);
115b951964fSBarry Smith }
116b951964fSBarry Smith 
11709dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
11820563c6bSBarry Smith        0,
11920563c6bSBarry Smith        0,
12020563c6bSBarry Smith        0,
12120563c6bSBarry 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        0,
144b951964fSBarry Smith        0,
145b951964fSBarry Smith        0,
146b951964fSBarry Smith        0,
147b951964fSBarry Smith        MatGetSize_Shell,
148b951964fSBarry Smith        MatGetLocalSize_Shell,
149b951964fSBarry Smith        MatGetOwnershipRange_Shell,
150b951964fSBarry Smith        0,
151b951964fSBarry Smith        0,
152b951964fSBarry Smith        0,
153b951964fSBarry Smith        0,
15409dc0095SBarry Smith        0,
15509dc0095SBarry Smith        0,
15609dc0095SBarry Smith        0,
15709dc0095SBarry Smith        0,
15809dc0095SBarry Smith        0,
15909dc0095SBarry Smith        0,
16009dc0095SBarry Smith        0,
16109dc0095SBarry Smith        0,
16209dc0095SBarry Smith        0,
16309dc0095SBarry Smith        0,
16409dc0095SBarry Smith        0,
16509dc0095SBarry Smith        0,
16609dc0095SBarry Smith        0,
16709dc0095SBarry Smith        0,
16809dc0095SBarry Smith        0,
16909dc0095SBarry Smith        0,
17009dc0095SBarry Smith        0,
17109dc0095SBarry Smith        0,
17209dc0095SBarry Smith        0,
17309dc0095SBarry Smith        0,
17409dc0095SBarry Smith        0,
17509dc0095SBarry Smith        0,
17609dc0095SBarry Smith        0,
17709dc0095SBarry Smith        0,
17809dc0095SBarry Smith        0,
17909dc0095SBarry Smith        0,
18009dc0095SBarry Smith        0,
18109dc0095SBarry Smith        0,
18209dc0095SBarry Smith        MatGetMaps_Petsc};
183e51e0e81SBarry Smith 
1845615d1e5SSatish Balay #undef __FUNC__
185*b2863d3aSBarry Smith #define  __FUNC__ /*<a name=""></a>*/"MatCreateShell"
1864b828684SBarry Smith /*@C
187052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
188ff756334SLois Curfman McInnes    private data storage format.
189e51e0e81SBarry Smith 
190c7fcc2eaSBarry Smith   Collective on MPI_Comm
191c7fcc2eaSBarry Smith 
192e51e0e81SBarry Smith    Input Parameters:
193c7fcc2eaSBarry Smith +  comm - MPI communicator
194c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
195c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
196c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
197c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
198c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
199e51e0e81SBarry Smith 
200ff756334SLois Curfman McInnes    Output Parameter:
20144cd7ae7SLois Curfman McInnes .  A - the matrix
202e51e0e81SBarry Smith 
203ff2fd236SBarry Smith    Level: advanced
204ff2fd236SBarry Smith 
205f39d1f56SLois Curfman McInnes   Usage:
2067b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
207f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
2087b2a1423SBarry Smith $    MatShellSetOperation(mat,MATOP_MULT,(void *)mult);
209f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
210f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
211f39d1f56SLois Curfman McInnes 
212ff756334SLois Curfman McInnes    Notes:
213ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
214ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
215ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
216e51e0e81SBarry Smith 
217f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
218f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
219645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
220645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
221645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
222645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
223645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
224645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
225645985a0SLois Curfman McInnes    For example,
226f39d1f56SLois Curfman McInnes 
227f39d1f56SLois Curfman McInnes $
228f39d1f56SLois Curfman McInnes $     Vec x, y
2297b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
230645985a0SLois Curfman McInnes $     Mat A
231f39d1f56SLois Curfman McInnes $
232c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
233c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
234f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
235c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
236c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
2377b2a1423SBarry Smith $     MatShellSetOperation(mat,MATOP_MULT,(void *)mult);
238645985a0SLois Curfman McInnes $     MatMult(A,x,y);
239645985a0SLois Curfman McInnes $     MatDestroy(A);
240f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
241645985a0SLois Curfman McInnes $
242e51e0e81SBarry Smith 
2430b627109SLois Curfman McInnes .keywords: matrix, shell, create
2440b627109SLois Curfman McInnes 
2453a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
246e51e0e81SBarry Smith @*/
247f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
248e51e0e81SBarry Smith {
24944cd7ae7SLois Curfman McInnes   Mat       B;
25044cd7ae7SLois Curfman McInnes   Mat_Shell *b;
251c7fcc2eaSBarry Smith   int       ierr;
252ed3cc1f0SBarry Smith 
2533a40ed3dSBarry Smith   PetscFunctionBegin;
2543f1db9ecSBarry Smith   PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,"Mat",comm,MatDestroy,MatView);
25544cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
25644cd7ae7SLois Curfman McInnes   B->factor       = 0;
25744cd7ae7SLois Curfman McInnes   B->assembled    = PETSC_TRUE;
258549d3d68SSatish Balay   ierr            = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
259e1311b90SBarry Smith   B->ops->destroy = MatDestroy_Shell;
260227d817aSBarry Smith 
26144cd7ae7SLois Curfman McInnes   b       = PetscNew(Mat_Shell);CHKPTRQ(b);
262eed86810SBarry Smith   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
263549d3d68SSatish Balay   ierr    = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr);
26444cd7ae7SLois Curfman McInnes   B->data = (void*)b;
265c7fcc2eaSBarry Smith 
266c7fcc2eaSBarry Smith   if (m == PETSC_DECIDE || n == PETSC_DECIDE) {
267c7fcc2eaSBarry Smith     SETERRQ(1,1,"Must give local row and column count for matrix");
268c7fcc2eaSBarry Smith   }
269c7fcc2eaSBarry Smith 
2700462333dSBarry Smith   ierr = PetscSplitOwnership(comm,&m,&M);CHKERRQ(ierr);
2710462333dSBarry Smith   ierr = PetscSplitOwnership(comm,&n,&N);CHKERRQ(ierr);
272f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
273f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
274f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
275f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
276c7fcc2eaSBarry Smith 
277488ecbafSBarry Smith   ierr = MapCreateMPI(comm,m,M,&B->rmap);CHKERRQ(ierr);
278488ecbafSBarry Smith   ierr = MapCreateMPI(comm,n,N,&B->cmap);CHKERRQ(ierr);
279c7fcc2eaSBarry Smith 
28044cd7ae7SLois Curfman McInnes   b->ctx = ctx;
28144cd7ae7SLois Curfman McInnes   *A     = B;
2823a40ed3dSBarry Smith   PetscFunctionReturn(0);
283e51e0e81SBarry Smith }
284e51e0e81SBarry Smith 
2855615d1e5SSatish Balay #undef __FUNC__
286*b2863d3aSBarry Smith #define  __FUNC__ /*<a name=""></a>*/"MatShellSetOperation"
287c16cb8f2SBarry Smith /*@C
2883a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2893a3eedf2SBarry Smith                            a shell matrix.
290e51e0e81SBarry Smith 
291fee21e36SBarry Smith    Collective on Mat
292fee21e36SBarry Smith 
293c7fcc2eaSBarry Smith     Input Parameters:
294c7fcc2eaSBarry Smith +   mat - the shell matrix
295c7fcc2eaSBarry Smith .   op - the name of the operation
296c7fcc2eaSBarry Smith -   f - the function that provides the operation.
297c7fcc2eaSBarry Smith 
29815091d37SBarry Smith    Level: advanced
29915091d37SBarry Smith 
300fae171e0SBarry Smith     Usage:
301a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
302f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
303c94f878dSBarry Smith $      ierr = MatShellSetOperation(A,MATOP_MULT,(void*) usermult);
3040b627109SLois Curfman McInnes 
305a62d957aSLois Curfman McInnes     Notes:
3067fc3c18eSBarry Smith     See the file include/mat.h for a complete list of matrix
3071c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
308a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
3091c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
310a62d957aSLois Curfman McInnes 
311a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
312deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
313deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
314deebb3c3SLois Curfman McInnes     routines, e.g.,
315a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
316a62d957aSLois Curfman McInnes 
317a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
318a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
319a62d957aSLois Curfman McInnes     set by MatCreateShell().
320a62d957aSLois Curfman McInnes 
321a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
322a62d957aSLois Curfman McInnes 
323d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
324e51e0e81SBarry Smith @*/
325fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op,void *f)
326e51e0e81SBarry Smith {
3273a40ed3dSBarry Smith   PetscFunctionBegin;
32877c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
329fae171e0SBarry Smith 
3301c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
331a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
332a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
3333a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
3340c0c84c0SBarry Smith     } else mat->ops->destroy            = (int (*)(Mat)) f;
335a62d957aSLois Curfman McInnes   }
336e1311b90SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,Viewer)) f;
337f830108cSBarry Smith   else                       (((void**)mat->ops)[op]) = f;
338a62d957aSLois Curfman McInnes 
3393a40ed3dSBarry Smith   PetscFunctionReturn(0);
340e51e0e81SBarry Smith }
341f0479e8cSBarry Smith 
342d4bb536fSBarry Smith #undef __FUNC__
343*b2863d3aSBarry Smith #define  __FUNC__ /*<a name=""></a>*/"MatShellGetOperation"
344d4bb536fSBarry Smith /*@C
345d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
346d4bb536fSBarry Smith 
347c7fcc2eaSBarry Smith     Not Collective
348c7fcc2eaSBarry Smith 
349d4bb536fSBarry Smith     Input Parameters:
350c7fcc2eaSBarry Smith +   mat - the shell matrix
351c7fcc2eaSBarry Smith -   op - the name of the operation
352d4bb536fSBarry Smith 
353d4bb536fSBarry Smith     Output Parameter:
354d4bb536fSBarry Smith .   f - the function that provides the operation.
355d4bb536fSBarry Smith 
35615091d37SBarry Smith     Level: advanced
35715091d37SBarry Smith 
358d4bb536fSBarry Smith     Notes:
3597fc3c18eSBarry Smith     See the file include/mat.h for a complete list of matrix
360d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
361d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
362d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
363d4bb536fSBarry Smith 
364d4bb536fSBarry Smith     All user-provided functions have the same calling
365d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
366d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
367d4bb536fSBarry Smith     routines, e.g.,
368d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
369d4bb536fSBarry Smith 
370d4bb536fSBarry Smith     Within each user-defined routine, the user should call
371d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
372d4bb536fSBarry Smith     set by MatCreateShell().
373d4bb536fSBarry Smith 
374d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
375d4bb536fSBarry Smith 
376d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
377d4bb536fSBarry Smith @*/
378d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op,void **f)
379d4bb536fSBarry Smith {
3803a40ed3dSBarry Smith   PetscFunctionBegin;
381d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
382d4bb536fSBarry Smith 
383d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
384d4bb536fSBarry Smith     if (mat->type == MATSHELL) {
385d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
386d4bb536fSBarry Smith       *f = (void*)shell->destroy;
387c7fcc2eaSBarry Smith     } else {
388c7fcc2eaSBarry Smith       *f = (void*)mat->ops->destroy;
389d4bb536fSBarry Smith     }
390c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
391c7fcc2eaSBarry Smith     *f = (void*)mat->ops->view;
392c7fcc2eaSBarry Smith   } else {
39341328d39SSatish Balay     *f = (((void**)mat->ops)[op]);
394d4bb536fSBarry Smith   }
395d4bb536fSBarry Smith 
3963a40ed3dSBarry Smith   PetscFunctionReturn(0);
397d4bb536fSBarry Smith }
398d4bb536fSBarry Smith 
399