xref: /petsc/src/mat/impls/shell/shell.c (revision 433994e6f6ce70ad8bdf6278bd516e26e00757e0)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*433994e6SBarry Smith static char vcid[] = "$Id: shell.c,v 1.73 1999/09/02 14:53:23 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 
27c7fcc2eaSBarry Smith     Not Collective
28c7fcc2eaSBarry Smith 
29b4fd4287SBarry Smith     Input Parameter:
30b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
31b4fd4287SBarry Smith 
32b4fd4287SBarry Smith     Output Parameter:
33b4fd4287SBarry Smith .   ctx - the user provided context
34b4fd4287SBarry Smith 
3515091d37SBarry Smith     Level: advanced
3615091d37SBarry Smith 
37a62d957aSLois Curfman McInnes     Notes:
38a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
39a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
40a62d957aSLois Curfman McInnes 
41a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
42a62d957aSLois Curfman McInnes 
43a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation()
44b4fd4287SBarry Smith @*/
45b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx)
46b4fd4287SBarry Smith {
473a40ed3dSBarry Smith   PetscFunctionBegin;
4877c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
49b4fd4287SBarry Smith   if (mat->type != MATSHELL) *ctx = 0;
50b4fd4287SBarry Smith   else                       *ctx = ((Mat_Shell *) (mat->data))->ctx;
513a40ed3dSBarry Smith   PetscFunctionReturn(0);
52b4fd4287SBarry Smith }
53b4fd4287SBarry Smith 
545615d1e5SSatish Balay #undef __FUNC__
55d4bb536fSBarry Smith #define __FUNC__ "MatGetSize_Shell"
568f6be9afSLois Curfman McInnes int MatGetSize_Shell(Mat mat,int *M,int *N)
5771b459e3SLois Curfman McInnes {
5871b459e3SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
593a40ed3dSBarry Smith 
603a40ed3dSBarry Smith   PetscFunctionBegin;
61f830108cSBarry Smith   if (M) *M = shell->M;
62f830108cSBarry Smith   if (N) *N = shell->N;
633a40ed3dSBarry Smith   PetscFunctionReturn(0);
64f39d1f56SLois Curfman McInnes }
65f39d1f56SLois Curfman McInnes 
665615d1e5SSatish Balay #undef __FUNC__
67d4bb536fSBarry Smith #define __FUNC__ "MatGetLocalSize_Shell"
688f6be9afSLois Curfman McInnes int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
69f39d1f56SLois Curfman McInnes {
70f39d1f56SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
713a40ed3dSBarry Smith 
723a40ed3dSBarry Smith   PetscFunctionBegin;
73f830108cSBarry Smith   if (m) *m = shell->m;
74f830108cSBarry Smith   if (n) *n = shell->n;
753a40ed3dSBarry Smith   PetscFunctionReturn(0);
7671b459e3SLois Curfman McInnes }
7771b459e3SLois Curfman McInnes 
785615d1e5SSatish Balay #undef __FUNC__
79d4bb536fSBarry Smith #define __FUNC__ "MatDestroy_Shell"
80e1311b90SBarry Smith int MatDestroy_Shell(Mat mat)
81e51e0e81SBarry Smith {
82b9fa9cd0SBarry Smith   int       ierr;
8388cf3e7dSBarry Smith   Mat_Shell *shell;
84ed3cc1f0SBarry Smith 
853a40ed3dSBarry Smith   PetscFunctionBegin;
8694d884c6SBarry Smith 
8794d884c6SBarry Smith   if (mat->mapping) {
8894d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->mapping);CHKERRQ(ierr);
8994d884c6SBarry Smith   }
9094d884c6SBarry Smith   if (mat->bmapping) {
9194d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->bmapping);CHKERRQ(ierr);
9294d884c6SBarry Smith   }
9361b13de0SBarry Smith   if (mat->rmap) {
9461b13de0SBarry Smith     ierr = MapDestroy(mat->rmap);CHKERRQ(ierr);
9561b13de0SBarry Smith   }
9661b13de0SBarry Smith   if (mat->cmap) {
9761b13de0SBarry Smith     ierr = MapDestroy(mat->cmap);CHKERRQ(ierr);
9861b13de0SBarry Smith   }
9988cf3e7dSBarry Smith   shell = (Mat_Shell *) mat->data;
1003a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
101606d414cSSatish Balay   ierr = PetscFree(shell);CHKERRQ(ierr);
1023a3eedf2SBarry Smith   PLogObjectDestroy(mat);
1033a3eedf2SBarry Smith   PetscHeaderDestroy(mat);
1043a40ed3dSBarry Smith   PetscFunctionReturn(0);
105e51e0e81SBarry Smith }
106e51e0e81SBarry Smith 
107*433994e6SBarry Smith #undef __FUNC__
108*433994e6SBarry Smith #define __FUNC__ "MatGetOwnershipRange_Shell"
1098f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
110b951964fSBarry Smith {
111ca161407SBarry Smith   int ierr;
112ca161407SBarry Smith 
113ca161407SBarry Smith   PetscFunctionBegin;
114ca161407SBarry Smith   ierr = MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr);
115b951964fSBarry Smith   *rstart = *rend - mat->m;
1163a40ed3dSBarry Smith   PetscFunctionReturn(0);
117b951964fSBarry Smith }
118b951964fSBarry Smith 
11909dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
12020563c6bSBarry Smith        0,
12120563c6bSBarry Smith        0,
12220563c6bSBarry Smith        0,
12320563c6bSBarry 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        0,
148b951964fSBarry Smith        0,
149b951964fSBarry Smith        MatGetSize_Shell,
150b951964fSBarry Smith        MatGetLocalSize_Shell,
151b951964fSBarry Smith        MatGetOwnershipRange_Shell,
152b951964fSBarry Smith        0,
153b951964fSBarry Smith        0,
154b951964fSBarry Smith        0,
155b951964fSBarry 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        0,
18309dc0095SBarry Smith        0,
18409dc0095SBarry Smith        MatGetMaps_Petsc};
185e51e0e81SBarry Smith 
1865615d1e5SSatish Balay #undef __FUNC__
187d4bb536fSBarry Smith #define __FUNC__ "MatCreateShell"
1884b828684SBarry Smith /*@C
189052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
190ff756334SLois Curfman McInnes    private data storage format.
191e51e0e81SBarry Smith 
192c7fcc2eaSBarry Smith   Collective on MPI_Comm
193c7fcc2eaSBarry Smith 
194e51e0e81SBarry Smith    Input Parameters:
195c7fcc2eaSBarry Smith +  comm - MPI communicator
196c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
197c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
198c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
199c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
200c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
201e51e0e81SBarry Smith 
202ff756334SLois Curfman McInnes    Output Parameter:
20344cd7ae7SLois Curfman McInnes .  A - the matrix
204e51e0e81SBarry Smith 
205ff2fd236SBarry Smith    Level: advanced
206ff2fd236SBarry Smith 
207f39d1f56SLois Curfman McInnes   Usage:
2087b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
209f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
2107b2a1423SBarry Smith $    MatShellSetOperation(mat,MATOP_MULT,(void *)mult);
211f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
212f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
213f39d1f56SLois Curfman McInnes 
214ff756334SLois Curfman McInnes    Notes:
215ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
216ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
217ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
218e51e0e81SBarry Smith 
219f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
220f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
221645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
222645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
223645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
224645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
225645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
226645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
227645985a0SLois Curfman McInnes    For example,
228f39d1f56SLois Curfman McInnes 
229f39d1f56SLois Curfman McInnes $
230f39d1f56SLois Curfman McInnes $     Vec x, y
2317b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
232645985a0SLois Curfman McInnes $     Mat A
233f39d1f56SLois Curfman McInnes $
234c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
235c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
236f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
237c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
238c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
2397b2a1423SBarry Smith $     MatShellSetOperation(mat,MATOP_MULT,(void *)mult);
240645985a0SLois Curfman McInnes $     MatMult(A,x,y);
241645985a0SLois Curfman McInnes $     MatDestroy(A);
242f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
243645985a0SLois Curfman McInnes $
244e51e0e81SBarry Smith 
2450b627109SLois Curfman McInnes .keywords: matrix, shell, create
2460b627109SLois Curfman McInnes 
2473a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
248e51e0e81SBarry Smith @*/
249f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
250e51e0e81SBarry Smith {
25144cd7ae7SLois Curfman McInnes   Mat       B;
25244cd7ae7SLois Curfman McInnes   Mat_Shell *b;
253c7fcc2eaSBarry Smith   int       ierr;
254ed3cc1f0SBarry Smith 
2553a40ed3dSBarry Smith   PetscFunctionBegin;
2563f1db9ecSBarry Smith   PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,"Mat",comm,MatDestroy,MatView);
25744cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
25844cd7ae7SLois Curfman McInnes   B->factor       = 0;
25944cd7ae7SLois Curfman McInnes   B->assembled    = PETSC_TRUE;
260549d3d68SSatish Balay   ierr            = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
261e1311b90SBarry Smith   B->ops->destroy = MatDestroy_Shell;
262227d817aSBarry Smith 
26344cd7ae7SLois Curfman McInnes   b       = PetscNew(Mat_Shell);CHKPTRQ(b);
264eed86810SBarry Smith   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
265549d3d68SSatish Balay   ierr    = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr);
26644cd7ae7SLois Curfman McInnes   B->data = (void *) b;
267c7fcc2eaSBarry Smith 
268c7fcc2eaSBarry Smith   if (m == PETSC_DECIDE || n == PETSC_DECIDE) {
269c7fcc2eaSBarry Smith     SETERRQ(1,1,"Must give local row and column count for matrix");
270c7fcc2eaSBarry Smith   }
271c7fcc2eaSBarry Smith 
2720462333dSBarry Smith   ierr = PetscSplitOwnership(comm,&m,&M);CHKERRQ(ierr);
2730462333dSBarry Smith   ierr = PetscSplitOwnership(comm,&n,&N);CHKERRQ(ierr);
274f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
275f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
276f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
277f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
278c7fcc2eaSBarry Smith 
279488ecbafSBarry Smith   ierr = MapCreateMPI(comm,m,M,&B->rmap);CHKERRQ(ierr);
280488ecbafSBarry Smith   ierr = MapCreateMPI(comm,n,N,&B->cmap);CHKERRQ(ierr);
281c7fcc2eaSBarry Smith 
28244cd7ae7SLois Curfman McInnes   b->ctx = ctx;
28344cd7ae7SLois Curfman McInnes   *A     = B;
2843a40ed3dSBarry Smith   PetscFunctionReturn(0);
285e51e0e81SBarry Smith }
286e51e0e81SBarry Smith 
2875615d1e5SSatish Balay #undef __FUNC__
288d4bb536fSBarry Smith #define __FUNC__ "MatShellSetOperation"
289c16cb8f2SBarry Smith /*@C
2903a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2913a3eedf2SBarry Smith                            a shell matrix.
292e51e0e81SBarry Smith 
293fee21e36SBarry Smith    Collective on Mat
294fee21e36SBarry Smith 
295c7fcc2eaSBarry Smith     Input Parameters:
296c7fcc2eaSBarry Smith +   mat - the shell matrix
297c7fcc2eaSBarry Smith .   op - the name of the operation
298c7fcc2eaSBarry Smith -   f - the function that provides the operation.
299c7fcc2eaSBarry Smith 
30015091d37SBarry Smith    Level: advanced
30115091d37SBarry Smith 
302fae171e0SBarry Smith     Usage:
303a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
304f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
305c94f878dSBarry Smith $      ierr = MatShellSetOperation(A,MATOP_MULT,(void*) usermult);
3060b627109SLois Curfman McInnes 
307a62d957aSLois Curfman McInnes     Notes:
3087fc3c18eSBarry Smith     See the file include/mat.h for a complete list of matrix
3091c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
310a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
3111c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
312a62d957aSLois Curfman McInnes 
313a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
314deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
315deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
316deebb3c3SLois Curfman McInnes     routines, e.g.,
317a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
318a62d957aSLois Curfman McInnes 
319a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
320a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
321a62d957aSLois Curfman McInnes     set by MatCreateShell().
322a62d957aSLois Curfman McInnes 
323a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
324a62d957aSLois Curfman McInnes 
325d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
326e51e0e81SBarry Smith @*/
327fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f)
328e51e0e81SBarry Smith {
3293a40ed3dSBarry Smith   PetscFunctionBegin;
33077c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
331fae171e0SBarry Smith 
3321c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
333a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
334a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell *) mat->data;
3353a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
3360c0c84c0SBarry Smith     } else mat->ops->destroy            = (int (*)(Mat)) f;
337a62d957aSLois Curfman McInnes   }
338e1311b90SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,Viewer)) f;
339f830108cSBarry Smith   else                       (((void**)mat->ops)[op]) = f;
340a62d957aSLois Curfman McInnes 
3413a40ed3dSBarry Smith   PetscFunctionReturn(0);
342e51e0e81SBarry Smith }
343f0479e8cSBarry Smith 
344d4bb536fSBarry Smith #undef __FUNC__
345d4bb536fSBarry Smith #define __FUNC__ "MatShellGetOperation"
346d4bb536fSBarry Smith /*@C
347d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
348d4bb536fSBarry Smith 
349c7fcc2eaSBarry Smith     Not Collective
350c7fcc2eaSBarry Smith 
351d4bb536fSBarry Smith     Input Parameters:
352c7fcc2eaSBarry Smith +   mat - the shell matrix
353c7fcc2eaSBarry Smith -   op - the name of the operation
354d4bb536fSBarry Smith 
355d4bb536fSBarry Smith     Output Parameter:
356d4bb536fSBarry Smith .   f - the function that provides the operation.
357d4bb536fSBarry Smith 
35815091d37SBarry Smith     Level: advanced
35915091d37SBarry Smith 
360d4bb536fSBarry Smith     Notes:
3617fc3c18eSBarry Smith     See the file include/mat.h for a complete list of matrix
362d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
363d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
364d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
365d4bb536fSBarry Smith 
366d4bb536fSBarry Smith     All user-provided functions have the same calling
367d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
368d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
369d4bb536fSBarry Smith     routines, e.g.,
370d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
371d4bb536fSBarry Smith 
372d4bb536fSBarry Smith     Within each user-defined routine, the user should call
373d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
374d4bb536fSBarry Smith     set by MatCreateShell().
375d4bb536fSBarry Smith 
376d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
377d4bb536fSBarry Smith 
378d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
379d4bb536fSBarry Smith @*/
380d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op, void **f)
381d4bb536fSBarry Smith {
3823a40ed3dSBarry Smith   PetscFunctionBegin;
383d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
384d4bb536fSBarry Smith 
385d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
386d4bb536fSBarry Smith     if (mat->type == MATSHELL) {
387d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell *) mat->data;
388d4bb536fSBarry Smith       *f = (void *) shell->destroy;
389c7fcc2eaSBarry Smith     } else {
390c7fcc2eaSBarry Smith       *f = (void *) mat->ops->destroy;
391d4bb536fSBarry Smith     }
392c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
393c7fcc2eaSBarry Smith     *f = (void *) mat->ops->view;
394c7fcc2eaSBarry Smith   } else {
39541328d39SSatish Balay     *f = (((void**)mat->ops)[op]);
396d4bb536fSBarry Smith   }
397d4bb536fSBarry Smith 
3983a40ed3dSBarry Smith   PetscFunctionReturn(0);
399d4bb536fSBarry Smith }
400d4bb536fSBarry Smith 
401