xref: /petsc/src/mat/impls/shell/shell.c (revision c134de8d2530e1d0e12b3d536a25fd1369966ab4)
173f4d377SMatthew Knepley /*$Id: shell.c,v 1.88 2001/09/07 20:09:41 bsmith Exp $*/
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);
14ef66eb69SBarry Smith   int         (*mult)(Mat,Vec,Vec);
15ef66eb69SBarry Smith   PetscTruth  scale,shift;
16ef66eb69SBarry Smith   PetscScalar vscale,vshift;
1720563c6bSBarry Smith   void        *ctx;
1888cf3e7dSBarry Smith } Mat_Shell;
19e51e0e81SBarry Smith 
20711e205bSSatish Balay #undef __FUNCT__
21711e205bSSatish Balay #define __FUNCT__ "MatShellGetContext"
22b4fd4287SBarry Smith /*@
23a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
24b4fd4287SBarry Smith 
25c7fcc2eaSBarry Smith     Not Collective
26c7fcc2eaSBarry 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 
3315091d37SBarry Smith     Level: advanced
3415091d37SBarry Smith 
35a62d957aSLois Curfman McInnes     Notes:
36a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
37a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
38a62d957aSLois Curfman McInnes 
39a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
40a62d957aSLois Curfman McInnes 
41a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation()
42b4fd4287SBarry Smith @*/
43b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx)
44b4fd4287SBarry Smith {
45273d9f13SBarry Smith   int        ierr;
46273d9f13SBarry Smith   PetscTruth flg;
47273d9f13SBarry Smith 
483a40ed3dSBarry Smith   PetscFunctionBegin;
4977c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
50273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
51273d9f13SBarry Smith   if (!flg) *ctx = 0;
52b4fd4287SBarry Smith   else      *ctx = ((Mat_Shell*)(mat->data))->ctx;
533a40ed3dSBarry Smith   PetscFunctionReturn(0);
54b4fd4287SBarry Smith }
55b4fd4287SBarry Smith 
56711e205bSSatish Balay #undef __FUNCT__
57711e205bSSatish Balay #define __FUNCT__ "MatDestroy_Shell"
58e1311b90SBarry Smith int MatDestroy_Shell(Mat mat)
59e51e0e81SBarry Smith {
60b9fa9cd0SBarry Smith   int       ierr;
6188cf3e7dSBarry Smith   Mat_Shell *shell;
62ed3cc1f0SBarry Smith 
633a40ed3dSBarry Smith   PetscFunctionBegin;
6488cf3e7dSBarry Smith   shell = (Mat_Shell*)mat->data;
653a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
66606d414cSSatish Balay   ierr = PetscFree(shell);CHKERRQ(ierr);
673a40ed3dSBarry Smith   PetscFunctionReturn(0);
68e51e0e81SBarry Smith }
69e51e0e81SBarry Smith 
70711e205bSSatish Balay #undef __FUNCT__
71ef66eb69SBarry Smith #define __FUNCT__ "MatMult_Shell"
72ef66eb69SBarry Smith int MatMult_Shell(Mat A,Vec x,Vec y)
73ef66eb69SBarry Smith {
74ef66eb69SBarry Smith   Mat_Shell   *shell = (Mat_Shell*)A->data;
75ef66eb69SBarry Smith   int         ierr;
76ef66eb69SBarry Smith 
77ef66eb69SBarry Smith   PetscFunctionBegin;
78ef66eb69SBarry Smith   ierr = (*shell->mult)(A,x,y);CHKERRQ(ierr);
79ef66eb69SBarry Smith   if (shell->shift && shell->scale) {
80ef66eb69SBarry Smith     ierr = VecAXPBY(&shell->vshift,&shell->vscale,x,y);CHKERRQ(ierr);
81ef66eb69SBarry Smith   } else if (shell->scale) {
82ef66eb69SBarry Smith     ierr = VecScale(&shell->vscale,y);CHKERRQ(ierr);
83ef66eb69SBarry Smith   } else {
84ef66eb69SBarry Smith     ierr = VecAXPY(&shell->vshift,x,y);CHKERRQ(ierr);
85ef66eb69SBarry Smith   }
86ef66eb69SBarry Smith   PetscFunctionReturn(0);
87ef66eb69SBarry Smith }
88ef66eb69SBarry Smith 
89ef66eb69SBarry Smith #undef __FUNCT__
90ef66eb69SBarry Smith #define __FUNCT__ "MatShift_Shell"
91ef66eb69SBarry Smith int MatShift_Shell(PetscScalar *a,Mat Y)
92ef66eb69SBarry Smith {
93ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
94ef66eb69SBarry Smith   PetscFunctionBegin;
95ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
96ef66eb69SBarry Smith     shell->vshift += *a;
97ef66eb69SBarry Smith   } else {
98ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
99ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
100ef66eb69SBarry Smith     shell->vshift = *a;
101ef66eb69SBarry Smith   }
102ef66eb69SBarry Smith   shell->shift  =  PETSC_TRUE;
103ef66eb69SBarry Smith   PetscFunctionReturn(0);
104ef66eb69SBarry Smith }
105ef66eb69SBarry Smith 
106ef66eb69SBarry Smith #undef __FUNCT__
107ef66eb69SBarry Smith #define __FUNCT__ "MatScale_Shell"
108ef66eb69SBarry Smith int MatScale_Shell(PetscScalar *a,Mat Y)
109ef66eb69SBarry Smith {
110ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
111ef66eb69SBarry Smith   PetscFunctionBegin;
112ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
113ef66eb69SBarry Smith     shell->vscale *= *a;
114ef66eb69SBarry Smith   } else {
115ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
116ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
117ef66eb69SBarry Smith     shell->vscale = *a;
118ef66eb69SBarry Smith   }
119ef66eb69SBarry Smith   shell->scale  =  PETSC_TRUE;
120ef66eb69SBarry Smith   PetscFunctionReturn(0);
121ef66eb69SBarry Smith }
122ef66eb69SBarry Smith 
123ef66eb69SBarry Smith #undef __FUNCT__
124ef66eb69SBarry Smith #define __FUNCT__ "MatAssemblyEnd_Shell"
125ef66eb69SBarry Smith int MatAssemblyEnd_Shell(Mat Y,MatAssemblyType t)
126ef66eb69SBarry Smith {
127ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
128ef66eb69SBarry Smith 
129ef66eb69SBarry Smith   PetscFunctionBegin;
130ef66eb69SBarry Smith   if ((shell->shift || shell->scale) && t == MAT_FINAL_ASSEMBLY) {
131ef66eb69SBarry Smith     shell->scale  = PETSC_FALSE;
132ef66eb69SBarry Smith     shell->shift  = PETSC_FALSE;
133ef66eb69SBarry Smith     shell->vshift = 0.0;
134ef66eb69SBarry Smith     shell->vscale = 1.0;
135ef66eb69SBarry Smith     Y->ops->mult  = shell->mult;
136ef66eb69SBarry Smith   }
137ef66eb69SBarry Smith   PetscFunctionReturn(0);
138ef66eb69SBarry Smith }
139ef66eb69SBarry Smith 
140273d9f13SBarry Smith extern int MatConvert_Shell(Mat,MatType,Mat*);
141b951964fSBarry Smith 
14209dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
14320563c6bSBarry Smith        0,
14420563c6bSBarry Smith        0,
14520563c6bSBarry Smith        0,
14620563c6bSBarry Smith        0,
147b951964fSBarry Smith        0,
148b951964fSBarry Smith        0,
149b951964fSBarry Smith        0,
150b951964fSBarry Smith        0,
151b951964fSBarry Smith        0,
152b951964fSBarry Smith        0,
153b951964fSBarry Smith        0,
154b951964fSBarry Smith        0,
155b951964fSBarry Smith        0,
156b951964fSBarry Smith        0,
157b951964fSBarry Smith        0,
158b951964fSBarry Smith        0,
159b951964fSBarry Smith        0,
160b951964fSBarry Smith        0,
161b951964fSBarry Smith        0,
162b951964fSBarry Smith        0,
163ef66eb69SBarry Smith        MatAssemblyEnd_Shell,
164b951964fSBarry Smith        0,
165b951964fSBarry Smith        0,
166b951964fSBarry Smith        0,
167b951964fSBarry Smith        0,
168b951964fSBarry Smith        0,
169b951964fSBarry Smith        0,
170b951964fSBarry Smith        0,
171b951964fSBarry Smith        0,
172273d9f13SBarry Smith        0,
173b951964fSBarry Smith        0,
174b951964fSBarry Smith        0,
175b951964fSBarry Smith        0,
176b951964fSBarry 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        0,
18509dc0095SBarry Smith        0,
18609dc0095SBarry Smith        0,
18709dc0095SBarry Smith        0,
18809dc0095SBarry Smith        0,
189ef66eb69SBarry Smith        MatScale_Shell,
190ef66eb69SBarry Smith        MatShift_Shell,
19109dc0095SBarry Smith        0,
19209dc0095SBarry Smith        0,
19309dc0095SBarry Smith        0,
19409dc0095SBarry Smith        0,
19509dc0095SBarry Smith        0,
19609dc0095SBarry Smith        0,
19709dc0095SBarry Smith        0,
19809dc0095SBarry Smith        0,
19909dc0095SBarry Smith        0,
20009dc0095SBarry Smith        0,
20109dc0095SBarry Smith        0,
20209dc0095SBarry Smith        0,
203273d9f13SBarry Smith        0,
204b9b97703SBarry Smith        MatDestroy_Shell,
20509dc0095SBarry Smith        0,
2068a124369SBarry Smith        MatGetPetscMaps_Petsc,
207273d9f13SBarry Smith        0,
208273d9f13SBarry Smith        0,
209273d9f13SBarry Smith        0,
210273d9f13SBarry Smith        0,
211273d9f13SBarry Smith        0,
212273d9f13SBarry Smith        0,
213273d9f13SBarry Smith        0,
214273d9f13SBarry Smith        MatConvert_Shell};
215273d9f13SBarry Smith 
216273d9f13SBarry Smith EXTERN_C_BEGIN
217711e205bSSatish Balay #undef __FUNCT__
218711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
219273d9f13SBarry Smith int MatCreate_Shell(Mat A)
220273d9f13SBarry Smith {
221273d9f13SBarry Smith   Mat_Shell *b;
222273d9f13SBarry Smith   int       ierr;
223273d9f13SBarry Smith 
224273d9f13SBarry Smith   PetscFunctionBegin;
225273d9f13SBarry Smith   ierr            = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
226273d9f13SBarry Smith 
227b0a32e0cSBarry Smith   ierr = PetscNew(Mat_Shell,&b);CHKERRQ(ierr);
228b0a32e0cSBarry Smith   PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
229273d9f13SBarry Smith   ierr    = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr);
230273d9f13SBarry Smith   A->data = (void*)b;
231273d9f13SBarry Smith 
232273d9f13SBarry Smith   if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) {
233273d9f13SBarry Smith     SETERRQ(1,"Must give local row and column count for matrix");
234273d9f13SBarry Smith   }
235273d9f13SBarry Smith 
236273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->m,&A->M);CHKERRQ(ierr);
237273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->n,&A->N);CHKERRQ(ierr);
238273d9f13SBarry Smith 
2398a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->m,A->M,&A->rmap);CHKERRQ(ierr);
2408a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->n,A->N,&A->cmap);CHKERRQ(ierr);
241273d9f13SBarry Smith 
242273d9f13SBarry Smith   b->ctx          = 0;
243ef66eb69SBarry Smith   b->scale        = PETSC_FALSE;
244ef66eb69SBarry Smith   b->shift        = PETSC_FALSE;
245ef66eb69SBarry Smith   b->vshift       = 0.0;
246ef66eb69SBarry Smith   b->vscale       = 1.0;
247ef66eb69SBarry Smith   b->mult         = 0;
248273d9f13SBarry Smith   A->assembled    = PETSC_TRUE;
249273d9f13SBarry Smith   A->preallocated = PETSC_TRUE;
250273d9f13SBarry Smith   PetscFunctionReturn(0);
251273d9f13SBarry Smith }
252273d9f13SBarry Smith EXTERN_C_END
253e51e0e81SBarry Smith 
254711e205bSSatish Balay #undef __FUNCT__
255711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
2564b828684SBarry Smith /*@C
257052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
258ff756334SLois Curfman McInnes    private data storage format.
259e51e0e81SBarry Smith 
260c7fcc2eaSBarry Smith   Collective on MPI_Comm
261c7fcc2eaSBarry Smith 
262e51e0e81SBarry Smith    Input Parameters:
263c7fcc2eaSBarry Smith +  comm - MPI communicator
264c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
265c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
266c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
267c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
268c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
269e51e0e81SBarry Smith 
270ff756334SLois Curfman McInnes    Output Parameter:
27144cd7ae7SLois Curfman McInnes .  A - the matrix
272e51e0e81SBarry Smith 
273ff2fd236SBarry Smith    Level: advanced
274ff2fd236SBarry Smith 
275f39d1f56SLois Curfman McInnes   Usage:
2767b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
277f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
278*c134de8dSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
279f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
280f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
281f39d1f56SLois Curfman McInnes 
282ff756334SLois Curfman McInnes    Notes:
283ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
284ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
285ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
286e51e0e81SBarry Smith 
287f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
288f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
289645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
290645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
291645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
292645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
293645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
294645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
295645985a0SLois Curfman McInnes    For example,
296f39d1f56SLois Curfman McInnes 
297f39d1f56SLois Curfman McInnes $
298f39d1f56SLois Curfman McInnes $     Vec x, y
2997b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
300645985a0SLois Curfman McInnes $     Mat A
301f39d1f56SLois Curfman McInnes $
302c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
303c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
304f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
305c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
306c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
307*c134de8dSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
308645985a0SLois Curfman McInnes $     MatMult(A,x,y);
309645985a0SLois Curfman McInnes $     MatDestroy(A);
310f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
311645985a0SLois Curfman McInnes $
312e51e0e81SBarry Smith 
3130b627109SLois Curfman McInnes .keywords: matrix, shell, create
3140b627109SLois Curfman McInnes 
3153a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
316e51e0e81SBarry Smith @*/
317f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
318e51e0e81SBarry Smith {
319c7fcc2eaSBarry Smith   int       ierr;
320ed3cc1f0SBarry Smith 
3213a40ed3dSBarry Smith   PetscFunctionBegin;
322273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,M,N,A);CHKERRQ(ierr);
323273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
324273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
325273d9f13SBarry Smith   PetscFunctionReturn(0);
326c7fcc2eaSBarry Smith }
327c7fcc2eaSBarry Smith 
328711e205bSSatish Balay #undef __FUNCT__
329711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
330273d9f13SBarry Smith /*@C
331273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
332c7fcc2eaSBarry Smith 
333273d9f13SBarry Smith    Collective on Mat
334c7fcc2eaSBarry Smith 
335273d9f13SBarry Smith     Input Parameters:
336273d9f13SBarry Smith +   mat - the shell matrix
337273d9f13SBarry Smith -   ctx - the context
338273d9f13SBarry Smith 
339273d9f13SBarry Smith    Level: advanced
340273d9f13SBarry Smith 
341273d9f13SBarry Smith 
342273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
343273d9f13SBarry Smith @*/
344273d9f13SBarry Smith int MatShellSetContext(Mat mat,void *ctx)
345273d9f13SBarry Smith {
346273d9f13SBarry Smith   Mat_Shell  *shell = (Mat_Shell*)mat->data;
347273d9f13SBarry Smith   int        ierr;
348273d9f13SBarry Smith   PetscTruth flg;
349273d9f13SBarry Smith 
350273d9f13SBarry Smith   PetscFunctionBegin;
351273d9f13SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
352273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
353273d9f13SBarry Smith   if (flg) {
354273d9f13SBarry Smith     shell->ctx = ctx;
355273d9f13SBarry Smith   }
3563a40ed3dSBarry Smith   PetscFunctionReturn(0);
357e51e0e81SBarry Smith }
358e51e0e81SBarry Smith 
359711e205bSSatish Balay #undef __FUNCT__
360711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
361c16cb8f2SBarry Smith /*@C
3623a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
3633a3eedf2SBarry Smith                            a shell matrix.
364e51e0e81SBarry Smith 
365fee21e36SBarry Smith    Collective on Mat
366fee21e36SBarry Smith 
367c7fcc2eaSBarry Smith     Input Parameters:
368c7fcc2eaSBarry Smith +   mat - the shell matrix
369c7fcc2eaSBarry Smith .   op - the name of the operation
370c7fcc2eaSBarry Smith -   f - the function that provides the operation.
371c7fcc2eaSBarry Smith 
37215091d37SBarry Smith    Level: advanced
37315091d37SBarry Smith 
374fae171e0SBarry Smith     Usage:
375a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
376f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
377*c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
3780b627109SLois Curfman McInnes 
379a62d957aSLois Curfman McInnes     Notes:
380e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
3811c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
382a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
3831c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
384a62d957aSLois Curfman McInnes 
385a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
386deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
387deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
388deebb3c3SLois Curfman McInnes     routines, e.g.,
389a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
390a62d957aSLois Curfman McInnes 
391a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
392a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
393a62d957aSLois Curfman McInnes     set by MatCreateShell().
394a62d957aSLois Curfman McInnes 
395a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
396a62d957aSLois Curfman McInnes 
397d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
398e51e0e81SBarry Smith @*/
399*c134de8dSSatish Balay int MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
400e51e0e81SBarry Smith {
401273d9f13SBarry Smith   int        ierr;
402273d9f13SBarry Smith   PetscTruth flg;
403273d9f13SBarry Smith 
4043a40ed3dSBarry Smith   PetscFunctionBegin;
40577c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
4061c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
407273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
408273d9f13SBarry Smith     if (flg) {
409a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
4103a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
4110c0c84c0SBarry Smith     } else mat->ops->destroy            = (int (*)(Mat)) f;
412a62d957aSLois Curfman McInnes   }
413b0a32e0cSBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,PetscViewer)) f;
414*c134de8dSSatish Balay   else                       (((void(**)(void))mat->ops)[op]) = f;
415a62d957aSLois Curfman McInnes 
4163a40ed3dSBarry Smith   PetscFunctionReturn(0);
417e51e0e81SBarry Smith }
418f0479e8cSBarry Smith 
419711e205bSSatish Balay #undef __FUNCT__
420711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
421d4bb536fSBarry Smith /*@C
422d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
423d4bb536fSBarry Smith 
424c7fcc2eaSBarry Smith     Not Collective
425c7fcc2eaSBarry Smith 
426d4bb536fSBarry Smith     Input Parameters:
427c7fcc2eaSBarry Smith +   mat - the shell matrix
428c7fcc2eaSBarry Smith -   op - the name of the operation
429d4bb536fSBarry Smith 
430d4bb536fSBarry Smith     Output Parameter:
431d4bb536fSBarry Smith .   f - the function that provides the operation.
432d4bb536fSBarry Smith 
43315091d37SBarry Smith     Level: advanced
43415091d37SBarry Smith 
435d4bb536fSBarry Smith     Notes:
436e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
437d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
438d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
439d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
440d4bb536fSBarry Smith 
441d4bb536fSBarry Smith     All user-provided functions have the same calling
442d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
443d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
444d4bb536fSBarry Smith     routines, e.g.,
445d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
446d4bb536fSBarry Smith 
447d4bb536fSBarry Smith     Within each user-defined routine, the user should call
448d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
449d4bb536fSBarry Smith     set by MatCreateShell().
450d4bb536fSBarry Smith 
451d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
452d4bb536fSBarry Smith 
453d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
454d4bb536fSBarry Smith @*/
455*c134de8dSSatish Balay int MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
456d4bb536fSBarry Smith {
457273d9f13SBarry Smith   int        ierr;
458273d9f13SBarry Smith   PetscTruth flg;
459273d9f13SBarry Smith 
4603a40ed3dSBarry Smith   PetscFunctionBegin;
461d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
462d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
463273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
464273d9f13SBarry Smith     if (flg) {
465d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
466*c134de8dSSatish Balay       *f = (void(*)(void))shell->destroy;
467c7fcc2eaSBarry Smith     } else {
468*c134de8dSSatish Balay       *f = (void(*)(void))mat->ops->destroy;
469d4bb536fSBarry Smith     }
470c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
471*c134de8dSSatish Balay     *f = (void(*)(void))mat->ops->view;
472c7fcc2eaSBarry Smith   } else {
473*c134de8dSSatish Balay     *f = (((void(**)(void))mat->ops)[op]);
474d4bb536fSBarry Smith   }
475d4bb536fSBarry Smith 
4763a40ed3dSBarry Smith   PetscFunctionReturn(0);
477d4bb536fSBarry Smith }
478d4bb536fSBarry Smith 
479