xref: /petsc/src/mat/impls/shell/shell.c (revision b0a32e0c6855ee6a6cd3495fa7da12ea9885bc5d)
1*b0a32e0cSBarry Smith /*$Id: shell.c,v 1.83 2000/10/24 20:25:38 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 
9e090d566SSatish Balay #include "src/mat/matimpl.h"        /*I "petscmat.h" I*/
10f5eb4b81SSatish Balay #include "src/vec/vecimpl.h"
11e51e0e81SBarry Smith 
1220563c6bSBarry Smith typedef struct {
133a3eedf2SBarry Smith   int  (*destroy)(Mat);
1420563c6bSBarry Smith   void *ctx;
1588cf3e7dSBarry Smith } Mat_Shell;
16e51e0e81SBarry Smith 
175615d1e5SSatish Balay #undef __FUNC__
18*b0a32e0cSBarry Smith #define __FUNC__ "MatShellGetContext"
19b4fd4287SBarry Smith /*@
20a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
21b4fd4287SBarry Smith 
22c7fcc2eaSBarry Smith     Not Collective
23c7fcc2eaSBarry Smith 
24b4fd4287SBarry Smith     Input Parameter:
25b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
26b4fd4287SBarry Smith 
27b4fd4287SBarry Smith     Output Parameter:
28b4fd4287SBarry Smith .   ctx - the user provided context
29b4fd4287SBarry Smith 
3015091d37SBarry Smith     Level: advanced
3115091d37SBarry Smith 
32a62d957aSLois Curfman McInnes     Notes:
33a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
34a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
35a62d957aSLois Curfman McInnes 
36a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
37a62d957aSLois Curfman McInnes 
38a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation()
39b4fd4287SBarry Smith @*/
40b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx)
41b4fd4287SBarry Smith {
42273d9f13SBarry Smith   int        ierr;
43273d9f13SBarry Smith   PetscTruth flg;
44273d9f13SBarry Smith 
453a40ed3dSBarry Smith   PetscFunctionBegin;
4677c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
47273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
48273d9f13SBarry Smith   if (!flg) *ctx = 0;
49b4fd4287SBarry Smith   else      *ctx = ((Mat_Shell*)(mat->data))->ctx;
503a40ed3dSBarry Smith   PetscFunctionReturn(0);
51b4fd4287SBarry Smith }
52b4fd4287SBarry Smith 
535615d1e5SSatish Balay #undef __FUNC__
54*b0a32e0cSBarry Smith #define __FUNC__ "MatDestroy_Shell"
55e1311b90SBarry Smith int MatDestroy_Shell(Mat mat)
56e51e0e81SBarry Smith {
57b9fa9cd0SBarry Smith   int       ierr;
5888cf3e7dSBarry Smith   Mat_Shell *shell;
59ed3cc1f0SBarry Smith 
603a40ed3dSBarry Smith   PetscFunctionBegin;
6188cf3e7dSBarry Smith   shell = (Mat_Shell*)mat->data;
623a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
63606d414cSSatish Balay   ierr = PetscFree(shell);CHKERRQ(ierr);
643a40ed3dSBarry Smith   PetscFunctionReturn(0);
65e51e0e81SBarry Smith }
66e51e0e81SBarry Smith 
67433994e6SBarry Smith #undef __FUNC__
68*b0a32e0cSBarry Smith #define __FUNC__ "MatGetOwnershipRange_Shell"
698f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat,int *rstart,int *rend)
70b951964fSBarry Smith {
714c49b128SBarry Smith   int ierr,tmp;
72ca161407SBarry Smith 
73ca161407SBarry Smith   PetscFunctionBegin;
744c49b128SBarry Smith   ierr = MPI_Scan(&mat->m,&tmp,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr);
754c49b128SBarry Smith   if (rstart) *rstart = tmp - mat->m;
764c49b128SBarry Smith   if (rend)   *rend   = tmp;
773a40ed3dSBarry Smith   PetscFunctionReturn(0);
78b951964fSBarry Smith }
79273d9f13SBarry Smith extern int MatConvert_Shell(Mat,MatType,Mat*);
80b951964fSBarry Smith 
8109dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
8220563c6bSBarry Smith        0,
8320563c6bSBarry Smith        0,
8420563c6bSBarry Smith        0,
8520563c6bSBarry Smith        0,
86b951964fSBarry Smith        0,
87b951964fSBarry Smith        0,
88b951964fSBarry Smith        0,
89b951964fSBarry Smith        0,
90b951964fSBarry Smith        0,
91b951964fSBarry Smith        0,
92b951964fSBarry Smith        0,
93b951964fSBarry Smith        0,
94b951964fSBarry Smith        0,
95b951964fSBarry Smith        0,
96b951964fSBarry Smith        0,
97b951964fSBarry 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,
111273d9f13SBarry Smith        0,
112b951964fSBarry Smith        MatGetOwnershipRange_Shell,
113b951964fSBarry Smith        0,
114b951964fSBarry Smith        0,
115b951964fSBarry Smith        0,
116b951964fSBarry Smith        0,
11709dc0095SBarry Smith        0,
11809dc0095SBarry Smith        0,
11909dc0095SBarry Smith        0,
12009dc0095SBarry Smith        0,
12109dc0095SBarry Smith        0,
12209dc0095SBarry Smith        0,
12309dc0095SBarry Smith        0,
12409dc0095SBarry Smith        0,
12509dc0095SBarry Smith        0,
12609dc0095SBarry Smith        0,
12709dc0095SBarry Smith        0,
12809dc0095SBarry Smith        0,
12909dc0095SBarry Smith        0,
13009dc0095SBarry Smith        0,
13109dc0095SBarry Smith        0,
13209dc0095SBarry Smith        0,
13309dc0095SBarry Smith        0,
13409dc0095SBarry Smith        0,
13509dc0095SBarry Smith        0,
13609dc0095SBarry Smith        0,
13709dc0095SBarry Smith        0,
13809dc0095SBarry Smith        0,
13909dc0095SBarry Smith        0,
14009dc0095SBarry Smith        0,
14109dc0095SBarry Smith        0,
14209dc0095SBarry Smith        0,
143273d9f13SBarry Smith        0,
144b9b97703SBarry Smith        MatDestroy_Shell,
14509dc0095SBarry Smith        0,
146273d9f13SBarry Smith        MatGetMaps_Petsc,
147273d9f13SBarry Smith        0,
148273d9f13SBarry Smith        0,
149273d9f13SBarry Smith        0,
150273d9f13SBarry Smith        0,
151273d9f13SBarry Smith        0,
152273d9f13SBarry Smith        0,
153273d9f13SBarry Smith        0,
154273d9f13SBarry Smith        MatConvert_Shell};
155273d9f13SBarry Smith 
156273d9f13SBarry Smith EXTERN_C_BEGIN
157273d9f13SBarry Smith #undef __FUNC__
158*b0a32e0cSBarry Smith #define __FUNC__ "MatCreate_Shell"
159273d9f13SBarry Smith int MatCreate_Shell(Mat A)
160273d9f13SBarry Smith {
161273d9f13SBarry Smith   Mat_Shell *b;
162273d9f13SBarry Smith   int       ierr;
163273d9f13SBarry Smith 
164273d9f13SBarry Smith   PetscFunctionBegin;
165273d9f13SBarry Smith   ierr            = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
166273d9f13SBarry Smith 
167*b0a32e0cSBarry Smith   ierr = PetscNew(Mat_Shell,&b);CHKERRQ(ierr);
168*b0a32e0cSBarry Smith   PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
169273d9f13SBarry Smith   ierr    = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr);
170273d9f13SBarry Smith   A->data = (void*)b;
171273d9f13SBarry Smith 
172273d9f13SBarry Smith   if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) {
173273d9f13SBarry Smith     SETERRQ(1,"Must give local row and column count for matrix");
174273d9f13SBarry Smith   }
175273d9f13SBarry Smith 
176273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->m,&A->M);CHKERRQ(ierr);
177273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->n,&A->N);CHKERRQ(ierr);
178273d9f13SBarry Smith 
179273d9f13SBarry Smith   ierr = MapCreateMPI(A->comm,A->m,A->M,&A->rmap);CHKERRQ(ierr);
180273d9f13SBarry Smith   ierr = MapCreateMPI(A->comm,A->n,A->N,&A->cmap);CHKERRQ(ierr);
181273d9f13SBarry Smith 
182273d9f13SBarry Smith   b->ctx = 0;
183273d9f13SBarry Smith   A->assembled    = PETSC_TRUE;
184273d9f13SBarry Smith   A->preallocated = PETSC_TRUE;
185273d9f13SBarry Smith   PetscFunctionReturn(0);
186273d9f13SBarry Smith }
187273d9f13SBarry Smith EXTERN_C_END
188e51e0e81SBarry Smith 
1895615d1e5SSatish Balay #undef __FUNC__
190*b0a32e0cSBarry Smith #define __FUNC__ "MatCreateShell"
1914b828684SBarry Smith /*@C
192052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
193ff756334SLois Curfman McInnes    private data storage format.
194e51e0e81SBarry Smith 
195c7fcc2eaSBarry Smith   Collective on MPI_Comm
196c7fcc2eaSBarry Smith 
197e51e0e81SBarry Smith    Input Parameters:
198c7fcc2eaSBarry Smith +  comm - MPI communicator
199c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
200c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
201c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
202c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
203c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
204e51e0e81SBarry Smith 
205ff756334SLois Curfman McInnes    Output Parameter:
20644cd7ae7SLois Curfman McInnes .  A - the matrix
207e51e0e81SBarry Smith 
208ff2fd236SBarry Smith    Level: advanced
209ff2fd236SBarry Smith 
210f39d1f56SLois Curfman McInnes   Usage:
2117b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
212f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
2137b2a1423SBarry Smith $    MatShellSetOperation(mat,MATOP_MULT,(void *)mult);
214f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
215f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
216f39d1f56SLois Curfman McInnes 
217ff756334SLois Curfman McInnes    Notes:
218ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
219ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
220ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
221e51e0e81SBarry Smith 
222f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
223f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
224645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
225645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
226645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
227645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
228645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
229645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
230645985a0SLois Curfman McInnes    For example,
231f39d1f56SLois Curfman McInnes 
232f39d1f56SLois Curfman McInnes $
233f39d1f56SLois Curfman McInnes $     Vec x, y
2347b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
235645985a0SLois Curfman McInnes $     Mat A
236f39d1f56SLois Curfman McInnes $
237c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
238c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
239f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
240c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
241c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
2427b2a1423SBarry Smith $     MatShellSetOperation(mat,MATOP_MULT,(void *)mult);
243645985a0SLois Curfman McInnes $     MatMult(A,x,y);
244645985a0SLois Curfman McInnes $     MatDestroy(A);
245f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
246645985a0SLois Curfman McInnes $
247e51e0e81SBarry Smith 
2480b627109SLois Curfman McInnes .keywords: matrix, shell, create
2490b627109SLois Curfman McInnes 
2503a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
251e51e0e81SBarry Smith @*/
252f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
253e51e0e81SBarry Smith {
254c7fcc2eaSBarry Smith   int       ierr;
255ed3cc1f0SBarry Smith 
2563a40ed3dSBarry Smith   PetscFunctionBegin;
257273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,M,N,A);CHKERRQ(ierr);
258273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
259273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
260273d9f13SBarry Smith   PetscFunctionReturn(0);
261c7fcc2eaSBarry Smith }
262c7fcc2eaSBarry Smith 
263273d9f13SBarry Smith #undef __FUNC__
264*b0a32e0cSBarry Smith #define __FUNC__ "MatShellSetContext"
265273d9f13SBarry Smith /*@C
266273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
267c7fcc2eaSBarry Smith 
268273d9f13SBarry Smith    Collective on Mat
269c7fcc2eaSBarry Smith 
270273d9f13SBarry Smith     Input Parameters:
271273d9f13SBarry Smith +   mat - the shell matrix
272273d9f13SBarry Smith -   ctx - the context
273273d9f13SBarry Smith 
274273d9f13SBarry Smith    Level: advanced
275273d9f13SBarry Smith 
276273d9f13SBarry Smith 
277273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
278273d9f13SBarry Smith @*/
279273d9f13SBarry Smith int MatShellSetContext(Mat mat,void *ctx)
280273d9f13SBarry Smith {
281273d9f13SBarry Smith   Mat_Shell  *shell = (Mat_Shell*)mat->data;
282273d9f13SBarry Smith   int        ierr;
283273d9f13SBarry Smith   PetscTruth flg;
284273d9f13SBarry Smith 
285273d9f13SBarry Smith   PetscFunctionBegin;
286273d9f13SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
287273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
288273d9f13SBarry Smith   if (flg) {
289273d9f13SBarry Smith     shell->ctx = ctx;
290273d9f13SBarry Smith   }
2913a40ed3dSBarry Smith   PetscFunctionReturn(0);
292e51e0e81SBarry Smith }
293e51e0e81SBarry Smith 
2945615d1e5SSatish Balay #undef __FUNC__
295*b0a32e0cSBarry Smith #define __FUNC__ "MatShellSetOperation"
296c16cb8f2SBarry Smith /*@C
2973a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2983a3eedf2SBarry Smith                            a shell matrix.
299e51e0e81SBarry Smith 
300fee21e36SBarry Smith    Collective on Mat
301fee21e36SBarry Smith 
302c7fcc2eaSBarry Smith     Input Parameters:
303c7fcc2eaSBarry Smith +   mat - the shell matrix
304c7fcc2eaSBarry Smith .   op - the name of the operation
305c7fcc2eaSBarry Smith -   f - the function that provides the operation.
306c7fcc2eaSBarry Smith 
30715091d37SBarry Smith    Level: advanced
30815091d37SBarry Smith 
309fae171e0SBarry Smith     Usage:
310a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
311f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
312c94f878dSBarry Smith $      ierr = MatShellSetOperation(A,MATOP_MULT,(void*) usermult);
3130b627109SLois Curfman McInnes 
314a62d957aSLois Curfman McInnes     Notes:
315e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
3161c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
317a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
3181c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
319a62d957aSLois Curfman McInnes 
320a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
321deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
322deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
323deebb3c3SLois Curfman McInnes     routines, e.g.,
324a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
325a62d957aSLois Curfman McInnes 
326a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
327a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
328a62d957aSLois Curfman McInnes     set by MatCreateShell().
329a62d957aSLois Curfman McInnes 
330a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
331a62d957aSLois Curfman McInnes 
332d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
333e51e0e81SBarry Smith @*/
334fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op,void *f)
335e51e0e81SBarry Smith {
336273d9f13SBarry Smith   int        ierr;
337273d9f13SBarry Smith   PetscTruth flg;
338273d9f13SBarry Smith 
3393a40ed3dSBarry Smith   PetscFunctionBegin;
34077c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
3411c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
342273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
343273d9f13SBarry Smith     if (flg) {
344a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
3453a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
3460c0c84c0SBarry Smith     } else mat->ops->destroy            = (int (*)(Mat)) f;
347a62d957aSLois Curfman McInnes   }
348*b0a32e0cSBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,PetscViewer)) f;
349f830108cSBarry Smith   else                       (((void**)mat->ops)[op]) = f;
350a62d957aSLois Curfman McInnes 
3513a40ed3dSBarry Smith   PetscFunctionReturn(0);
352e51e0e81SBarry Smith }
353f0479e8cSBarry Smith 
354d4bb536fSBarry Smith #undef __FUNC__
355*b0a32e0cSBarry Smith #define __FUNC__ "MatShellGetOperation"
356d4bb536fSBarry Smith /*@C
357d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
358d4bb536fSBarry Smith 
359c7fcc2eaSBarry Smith     Not Collective
360c7fcc2eaSBarry Smith 
361d4bb536fSBarry Smith     Input Parameters:
362c7fcc2eaSBarry Smith +   mat - the shell matrix
363c7fcc2eaSBarry Smith -   op - the name of the operation
364d4bb536fSBarry Smith 
365d4bb536fSBarry Smith     Output Parameter:
366d4bb536fSBarry Smith .   f - the function that provides the operation.
367d4bb536fSBarry Smith 
36815091d37SBarry Smith     Level: advanced
36915091d37SBarry Smith 
370d4bb536fSBarry Smith     Notes:
371e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
372d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
373d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
374d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
375d4bb536fSBarry Smith 
376d4bb536fSBarry Smith     All user-provided functions have the same calling
377d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
378d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
379d4bb536fSBarry Smith     routines, e.g.,
380d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
381d4bb536fSBarry Smith 
382d4bb536fSBarry Smith     Within each user-defined routine, the user should call
383d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
384d4bb536fSBarry Smith     set by MatCreateShell().
385d4bb536fSBarry Smith 
386d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
387d4bb536fSBarry Smith 
388d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
389d4bb536fSBarry Smith @*/
390d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op,void **f)
391d4bb536fSBarry Smith {
392273d9f13SBarry Smith   int        ierr;
393273d9f13SBarry Smith   PetscTruth flg;
394273d9f13SBarry Smith 
3953a40ed3dSBarry Smith   PetscFunctionBegin;
396d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
397d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
398273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
399273d9f13SBarry Smith     if (flg) {
400d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
401d4bb536fSBarry Smith       *f = (void*)shell->destroy;
402c7fcc2eaSBarry Smith     } else {
403c7fcc2eaSBarry Smith       *f = (void*)mat->ops->destroy;
404d4bb536fSBarry Smith     }
405c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
406c7fcc2eaSBarry Smith     *f = (void*)mat->ops->view;
407c7fcc2eaSBarry Smith   } else {
40841328d39SSatish Balay     *f = (((void**)mat->ops)[op]);
409d4bb536fSBarry Smith   }
410d4bb536fSBarry Smith 
4113a40ed3dSBarry Smith   PetscFunctionReturn(0);
412d4bb536fSBarry Smith }
413d4bb536fSBarry Smith 
414