xref: /petsc/src/mat/impls/shell/shell.c (revision b9b9770376f6bdad54cc53bb7a8b79bbb53b7e80)
1*b9b97703SBarry Smith /*$Id: shell.c,v 1.80 2000/05/05 22:15:48 balay 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 
9e090d566SSatish Balay #include "src/mat/matimpl.h"        /*I "petscmat.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__
20b2863d3aSBarry 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__
52b2863d3aSBarry 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__
64b2863d3aSBarry 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__
76b2863d3aSBarry 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__
105b2863d3aSBarry 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,
180*b9b97703SBarry Smith        MatDestroy_Shell,
18109dc0095SBarry Smith        0,
18209dc0095SBarry Smith        MatGetMaps_Petsc};
183e51e0e81SBarry Smith 
1845615d1e5SSatish Balay #undef __FUNC__
185b2863d3aSBarry 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);
259227d817aSBarry Smith 
26044cd7ae7SLois Curfman McInnes   b       = PetscNew(Mat_Shell);CHKPTRQ(b);
261eed86810SBarry Smith   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
262549d3d68SSatish Balay   ierr    = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr);
26344cd7ae7SLois Curfman McInnes   B->data = (void*)b;
264c7fcc2eaSBarry Smith 
265c7fcc2eaSBarry Smith   if (m == PETSC_DECIDE || n == PETSC_DECIDE) {
266c7fcc2eaSBarry Smith     SETERRQ(1,1,"Must give local row and column count for matrix");
267c7fcc2eaSBarry Smith   }
268c7fcc2eaSBarry Smith 
2690462333dSBarry Smith   ierr = PetscSplitOwnership(comm,&m,&M);CHKERRQ(ierr);
2700462333dSBarry Smith   ierr = PetscSplitOwnership(comm,&n,&N);CHKERRQ(ierr);
271f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
272f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
273f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
274f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
275c7fcc2eaSBarry Smith 
276488ecbafSBarry Smith   ierr = MapCreateMPI(comm,m,M,&B->rmap);CHKERRQ(ierr);
277488ecbafSBarry Smith   ierr = MapCreateMPI(comm,n,N,&B->cmap);CHKERRQ(ierr);
278c7fcc2eaSBarry Smith 
27944cd7ae7SLois Curfman McInnes   b->ctx = ctx;
28044cd7ae7SLois Curfman McInnes   *A     = B;
2813a40ed3dSBarry Smith   PetscFunctionReturn(0);
282e51e0e81SBarry Smith }
283e51e0e81SBarry Smith 
2845615d1e5SSatish Balay #undef __FUNC__
285b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"MatShellSetOperation"
286c16cb8f2SBarry Smith /*@C
2873a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2883a3eedf2SBarry Smith                            a shell matrix.
289e51e0e81SBarry Smith 
290fee21e36SBarry Smith    Collective on Mat
291fee21e36SBarry Smith 
292c7fcc2eaSBarry Smith     Input Parameters:
293c7fcc2eaSBarry Smith +   mat - the shell matrix
294c7fcc2eaSBarry Smith .   op - the name of the operation
295c7fcc2eaSBarry Smith -   f - the function that provides the operation.
296c7fcc2eaSBarry Smith 
29715091d37SBarry Smith    Level: advanced
29815091d37SBarry Smith 
299fae171e0SBarry Smith     Usage:
300a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
301f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
302c94f878dSBarry Smith $      ierr = MatShellSetOperation(A,MATOP_MULT,(void*) usermult);
3030b627109SLois Curfman McInnes 
304a62d957aSLois Curfman McInnes     Notes:
305e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
3061c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
307a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
3081c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
309a62d957aSLois Curfman McInnes 
310a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
311deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
312deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
313deebb3c3SLois Curfman McInnes     routines, e.g.,
314a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
315a62d957aSLois Curfman McInnes 
316a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
317a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
318a62d957aSLois Curfman McInnes     set by MatCreateShell().
319a62d957aSLois Curfman McInnes 
320a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
321a62d957aSLois Curfman McInnes 
322d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
323e51e0e81SBarry Smith @*/
324fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op,void *f)
325e51e0e81SBarry Smith {
3263a40ed3dSBarry Smith   PetscFunctionBegin;
32777c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
328fae171e0SBarry Smith 
3291c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
330a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
331a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
3323a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
3330c0c84c0SBarry Smith     } else mat->ops->destroy            = (int (*)(Mat)) f;
334a62d957aSLois Curfman McInnes   }
335e1311b90SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,Viewer)) f;
336f830108cSBarry Smith   else                       (((void**)mat->ops)[op]) = f;
337a62d957aSLois Curfman McInnes 
3383a40ed3dSBarry Smith   PetscFunctionReturn(0);
339e51e0e81SBarry Smith }
340f0479e8cSBarry Smith 
341d4bb536fSBarry Smith #undef __FUNC__
342b2863d3aSBarry Smith #define __FUNC__ /*<a name=""></a>*/"MatShellGetOperation"
343d4bb536fSBarry Smith /*@C
344d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
345d4bb536fSBarry Smith 
346c7fcc2eaSBarry Smith     Not Collective
347c7fcc2eaSBarry Smith 
348d4bb536fSBarry Smith     Input Parameters:
349c7fcc2eaSBarry Smith +   mat - the shell matrix
350c7fcc2eaSBarry Smith -   op - the name of the operation
351d4bb536fSBarry Smith 
352d4bb536fSBarry Smith     Output Parameter:
353d4bb536fSBarry Smith .   f - the function that provides the operation.
354d4bb536fSBarry Smith 
35515091d37SBarry Smith     Level: advanced
35615091d37SBarry Smith 
357d4bb536fSBarry Smith     Notes:
358e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
359d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
360d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
361d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
362d4bb536fSBarry Smith 
363d4bb536fSBarry Smith     All user-provided functions have the same calling
364d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
365d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
366d4bb536fSBarry Smith     routines, e.g.,
367d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
368d4bb536fSBarry Smith 
369d4bb536fSBarry Smith     Within each user-defined routine, the user should call
370d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
371d4bb536fSBarry Smith     set by MatCreateShell().
372d4bb536fSBarry Smith 
373d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
374d4bb536fSBarry Smith 
375d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
376d4bb536fSBarry Smith @*/
377d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op,void **f)
378d4bb536fSBarry Smith {
3793a40ed3dSBarry Smith   PetscFunctionBegin;
380d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
381d4bb536fSBarry Smith 
382d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
383d4bb536fSBarry Smith     if (mat->type == MATSHELL) {
384d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
385d4bb536fSBarry Smith       *f = (void*)shell->destroy;
386c7fcc2eaSBarry Smith     } else {
387c7fcc2eaSBarry Smith       *f = (void*)mat->ops->destroy;
388d4bb536fSBarry Smith     }
389c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
390c7fcc2eaSBarry Smith     *f = (void*)mat->ops->view;
391c7fcc2eaSBarry Smith   } else {
39241328d39SSatish Balay     *f = (((void**)mat->ops)[op]);
393d4bb536fSBarry Smith   }
394d4bb536fSBarry Smith 
3953a40ed3dSBarry Smith   PetscFunctionReturn(0);
396d4bb536fSBarry Smith }
397d4bb536fSBarry Smith 
398