xref: /petsc/src/mat/impls/shell/shell.c (revision fafad7475eccdf22e42c12aa21085e705729f888)
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 
41ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellSetOperation(), MatShellSetContext()
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"
91268466fbSBarry Smith int MatShift_Shell(const 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"
108268466fbSBarry Smith int MatScale_Shell(const 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,
14697304618SKris Buschelman /* 4*/ 0,
14720563c6bSBarry Smith        0,
148b951964fSBarry Smith        0,
149b951964fSBarry Smith        0,
150b951964fSBarry Smith        0,
151b951964fSBarry Smith        0,
15297304618SKris Buschelman /*10*/ 0,
153b951964fSBarry Smith        0,
154b951964fSBarry Smith        0,
155b951964fSBarry Smith        0,
156b951964fSBarry Smith        0,
15797304618SKris Buschelman /*15*/ 0,
158b951964fSBarry Smith        0,
159b951964fSBarry Smith        0,
160b951964fSBarry Smith        0,
161b951964fSBarry Smith        0,
16297304618SKris Buschelman /*20*/ 0,
163ef66eb69SBarry Smith        MatAssemblyEnd_Shell,
164b951964fSBarry Smith        0,
165b951964fSBarry Smith        0,
166b951964fSBarry Smith        0,
16797304618SKris Buschelman /*25*/ 0,
168b951964fSBarry Smith        0,
169b951964fSBarry Smith        0,
170b951964fSBarry Smith        0,
171b951964fSBarry Smith        0,
17297304618SKris Buschelman /*30*/ 0,
173b951964fSBarry Smith        0,
174273d9f13SBarry Smith        0,
175b951964fSBarry Smith        0,
176b951964fSBarry Smith        0,
17797304618SKris Buschelman /*35*/ 0,
178b951964fSBarry Smith        0,
179b951964fSBarry Smith        0,
18009dc0095SBarry Smith        0,
18109dc0095SBarry Smith        0,
18297304618SKris Buschelman /*40*/ 0,
18309dc0095SBarry Smith        0,
18409dc0095SBarry Smith        0,
18509dc0095SBarry Smith        0,
18609dc0095SBarry Smith        0,
18797304618SKris Buschelman /*45*/ 0,
188ef66eb69SBarry Smith        MatScale_Shell,
189ef66eb69SBarry Smith        MatShift_Shell,
19009dc0095SBarry Smith        0,
19109dc0095SBarry Smith        0,
19297304618SKris Buschelman /*50*/ 0,
19309dc0095SBarry Smith        0,
19409dc0095SBarry Smith        0,
19509dc0095SBarry Smith        0,
19609dc0095SBarry Smith        0,
19797304618SKris Buschelman /*55*/ 0,
19809dc0095SBarry Smith        0,
19909dc0095SBarry Smith        0,
20009dc0095SBarry Smith        0,
20109dc0095SBarry Smith        0,
20297304618SKris Buschelman /*60*/ 0,
203b9b97703SBarry Smith        MatDestroy_Shell,
20409dc0095SBarry Smith        0,
2058a124369SBarry Smith        MatGetPetscMaps_Petsc,
206273d9f13SBarry Smith        0,
20797304618SKris Buschelman /*65*/ 0,
208273d9f13SBarry Smith        0,
209273d9f13SBarry Smith        0,
210273d9f13SBarry Smith        0,
211273d9f13SBarry Smith        0,
21297304618SKris Buschelman /*70*/ 0,
21397304618SKris Buschelman        MatConvert_Shell,
214273d9f13SBarry Smith        0,
215273d9f13SBarry Smith        0,
21697304618SKris Buschelman        0,
21797304618SKris Buschelman /*75*/ 0,
21897304618SKris Buschelman        0,
21997304618SKris Buschelman        0,
22097304618SKris Buschelman        0,
22197304618SKris Buschelman        0,
22297304618SKris Buschelman /*80*/ 0,
22397304618SKris Buschelman        0,
22497304618SKris Buschelman        0,
22597304618SKris Buschelman        0,
22697304618SKris Buschelman        0,
22797304618SKris Buschelman /*85*/ 0
22897304618SKris Buschelman };
229273d9f13SBarry Smith 
2300bad9183SKris Buschelman /*MC
231*fafad747SKris Buschelman    MATSHELL - MATSHELL = "shell" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
2320bad9183SKris Buschelman 
2330bad9183SKris Buschelman   Level: advanced
2340bad9183SKris Buschelman 
2350bad9183SKris Buschelman .seealso: MatCreateShell
2360bad9183SKris Buschelman M*/
2370bad9183SKris Buschelman 
238273d9f13SBarry Smith EXTERN_C_BEGIN
239711e205bSSatish Balay #undef __FUNCT__
240711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
241273d9f13SBarry Smith int MatCreate_Shell(Mat A)
242273d9f13SBarry Smith {
243273d9f13SBarry Smith   Mat_Shell *b;
244273d9f13SBarry Smith   int       ierr;
245273d9f13SBarry Smith 
246273d9f13SBarry Smith   PetscFunctionBegin;
247273d9f13SBarry Smith   ierr            = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
248273d9f13SBarry Smith 
249b0a32e0cSBarry Smith   ierr = PetscNew(Mat_Shell,&b);CHKERRQ(ierr);
250b0a32e0cSBarry Smith   PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
251273d9f13SBarry Smith   ierr    = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr);
252273d9f13SBarry Smith   A->data = (void*)b;
253273d9f13SBarry Smith 
254273d9f13SBarry Smith   if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) {
255273d9f13SBarry Smith     SETERRQ(1,"Must give local row and column count for matrix");
256273d9f13SBarry Smith   }
257273d9f13SBarry Smith 
258273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->m,&A->M);CHKERRQ(ierr);
259273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->n,&A->N);CHKERRQ(ierr);
260273d9f13SBarry Smith 
2618a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->m,A->M,&A->rmap);CHKERRQ(ierr);
2628a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->n,A->N,&A->cmap);CHKERRQ(ierr);
263273d9f13SBarry Smith 
264273d9f13SBarry Smith   b->ctx          = 0;
265ef66eb69SBarry Smith   b->scale        = PETSC_FALSE;
266ef66eb69SBarry Smith   b->shift        = PETSC_FALSE;
267ef66eb69SBarry Smith   b->vshift       = 0.0;
268ef66eb69SBarry Smith   b->vscale       = 1.0;
269ef66eb69SBarry Smith   b->mult         = 0;
270273d9f13SBarry Smith   A->assembled    = PETSC_TRUE;
271273d9f13SBarry Smith   A->preallocated = PETSC_TRUE;
272273d9f13SBarry Smith   PetscFunctionReturn(0);
273273d9f13SBarry Smith }
274273d9f13SBarry Smith EXTERN_C_END
275e51e0e81SBarry Smith 
276711e205bSSatish Balay #undef __FUNCT__
277711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
2784b828684SBarry Smith /*@C
279052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
280ff756334SLois Curfman McInnes    private data storage format.
281e51e0e81SBarry Smith 
282c7fcc2eaSBarry Smith   Collective on MPI_Comm
283c7fcc2eaSBarry Smith 
284e51e0e81SBarry Smith    Input Parameters:
285c7fcc2eaSBarry Smith +  comm - MPI communicator
286c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
287c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
288c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
289c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
290c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
291e51e0e81SBarry Smith 
292ff756334SLois Curfman McInnes    Output Parameter:
29344cd7ae7SLois Curfman McInnes .  A - the matrix
294e51e0e81SBarry Smith 
295ff2fd236SBarry Smith    Level: advanced
296ff2fd236SBarry Smith 
297f39d1f56SLois Curfman McInnes   Usage:
2987b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
299f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
300c134de8dSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
301f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
302f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
303f39d1f56SLois Curfman McInnes 
304ff756334SLois Curfman McInnes    Notes:
305ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
306ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
307ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
308e51e0e81SBarry Smith 
309f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
310f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
311645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
312645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
313645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
314645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
315645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
316645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
317645985a0SLois Curfman McInnes    For example,
318f39d1f56SLois Curfman McInnes 
319f39d1f56SLois Curfman McInnes $
320f39d1f56SLois Curfman McInnes $     Vec x, y
3217b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
322645985a0SLois Curfman McInnes $     Mat A
323f39d1f56SLois Curfman McInnes $
324c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
325c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
326f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
327c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
328c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
329c134de8dSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
330645985a0SLois Curfman McInnes $     MatMult(A,x,y);
331645985a0SLois Curfman McInnes $     MatDestroy(A);
332f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
333645985a0SLois Curfman McInnes $
334e51e0e81SBarry Smith 
3350b627109SLois Curfman McInnes .keywords: matrix, shell, create
3360b627109SLois Curfman McInnes 
337ab50ec6bSBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext(), MatShellSetContext()
338e51e0e81SBarry Smith @*/
339f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
340e51e0e81SBarry Smith {
341c7fcc2eaSBarry Smith   int       ierr;
342ed3cc1f0SBarry Smith 
3433a40ed3dSBarry Smith   PetscFunctionBegin;
344273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,M,N,A);CHKERRQ(ierr);
345273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
346273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
347273d9f13SBarry Smith   PetscFunctionReturn(0);
348c7fcc2eaSBarry Smith }
349c7fcc2eaSBarry Smith 
350711e205bSSatish Balay #undef __FUNCT__
351711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
352273d9f13SBarry Smith /*@C
353273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
354c7fcc2eaSBarry Smith 
355273d9f13SBarry Smith    Collective on Mat
356c7fcc2eaSBarry Smith 
357273d9f13SBarry Smith     Input Parameters:
358273d9f13SBarry Smith +   mat - the shell matrix
359273d9f13SBarry Smith -   ctx - the context
360273d9f13SBarry Smith 
361273d9f13SBarry Smith    Level: advanced
362273d9f13SBarry Smith 
363273d9f13SBarry Smith 
364273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
365273d9f13SBarry Smith @*/
366273d9f13SBarry Smith int MatShellSetContext(Mat mat,void *ctx)
367273d9f13SBarry Smith {
368273d9f13SBarry Smith   Mat_Shell  *shell = (Mat_Shell*)mat->data;
369273d9f13SBarry Smith   int        ierr;
370273d9f13SBarry Smith   PetscTruth flg;
371273d9f13SBarry Smith 
372273d9f13SBarry Smith   PetscFunctionBegin;
373273d9f13SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
374273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
375273d9f13SBarry Smith   if (flg) {
376273d9f13SBarry Smith     shell->ctx = ctx;
377273d9f13SBarry Smith   }
3783a40ed3dSBarry Smith   PetscFunctionReturn(0);
379e51e0e81SBarry Smith }
380e51e0e81SBarry Smith 
381711e205bSSatish Balay #undef __FUNCT__
382711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
383c16cb8f2SBarry Smith /*@C
3843a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
3853a3eedf2SBarry Smith                            a shell matrix.
386e51e0e81SBarry Smith 
387fee21e36SBarry Smith    Collective on Mat
388fee21e36SBarry Smith 
389c7fcc2eaSBarry Smith     Input Parameters:
390c7fcc2eaSBarry Smith +   mat - the shell matrix
391c7fcc2eaSBarry Smith .   op - the name of the operation
392c7fcc2eaSBarry Smith -   f - the function that provides the operation.
393c7fcc2eaSBarry Smith 
39415091d37SBarry Smith    Level: advanced
39515091d37SBarry Smith 
396fae171e0SBarry Smith     Usage:
397a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
398f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
399c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
4000b627109SLois Curfman McInnes 
401a62d957aSLois Curfman McInnes     Notes:
402e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
4031c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
404a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
4051c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
406a62d957aSLois Curfman McInnes 
407a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
408deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
409deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
410deebb3c3SLois Curfman McInnes     routines, e.g.,
411a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
412a62d957aSLois Curfman McInnes 
413a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
414a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
415a62d957aSLois Curfman McInnes     set by MatCreateShell().
416a62d957aSLois Curfman McInnes 
417a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
418a62d957aSLois Curfman McInnes 
419ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellSetContext()
420e51e0e81SBarry Smith @*/
421c134de8dSSatish Balay int MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
422e51e0e81SBarry Smith {
423273d9f13SBarry Smith   int        ierr;
424273d9f13SBarry Smith   PetscTruth flg;
425273d9f13SBarry Smith 
4263a40ed3dSBarry Smith   PetscFunctionBegin;
42777c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
4281c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
429273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
430273d9f13SBarry Smith     if (flg) {
431a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
4323a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
4330c0c84c0SBarry Smith     } else mat->ops->destroy            = (int (*)(Mat)) f;
434a62d957aSLois Curfman McInnes   }
435b0a32e0cSBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,PetscViewer)) f;
436c134de8dSSatish Balay   else                       (((void(**)(void))mat->ops)[op]) = f;
437a62d957aSLois Curfman McInnes 
4383a40ed3dSBarry Smith   PetscFunctionReturn(0);
439e51e0e81SBarry Smith }
440f0479e8cSBarry Smith 
441711e205bSSatish Balay #undef __FUNCT__
442711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
443d4bb536fSBarry Smith /*@C
444d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
445d4bb536fSBarry Smith 
446c7fcc2eaSBarry Smith     Not Collective
447c7fcc2eaSBarry Smith 
448d4bb536fSBarry Smith     Input Parameters:
449c7fcc2eaSBarry Smith +   mat - the shell matrix
450c7fcc2eaSBarry Smith -   op - the name of the operation
451d4bb536fSBarry Smith 
452d4bb536fSBarry Smith     Output Parameter:
453d4bb536fSBarry Smith .   f - the function that provides the operation.
454d4bb536fSBarry Smith 
45515091d37SBarry Smith     Level: advanced
45615091d37SBarry Smith 
457d4bb536fSBarry Smith     Notes:
458e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
459d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
460d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
461d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
462d4bb536fSBarry Smith 
463d4bb536fSBarry Smith     All user-provided functions have the same calling
464d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
465d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
466d4bb536fSBarry Smith     routines, e.g.,
467d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
468d4bb536fSBarry Smith 
469d4bb536fSBarry Smith     Within each user-defined routine, the user should call
470d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
471d4bb536fSBarry Smith     set by MatCreateShell().
472d4bb536fSBarry Smith 
473d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
474d4bb536fSBarry Smith 
475ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation(), MatShellSetContext()
476d4bb536fSBarry Smith @*/
477c134de8dSSatish Balay int MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
478d4bb536fSBarry Smith {
479273d9f13SBarry Smith   int        ierr;
480273d9f13SBarry Smith   PetscTruth flg;
481273d9f13SBarry Smith 
4823a40ed3dSBarry Smith   PetscFunctionBegin;
483d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
484d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
485273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
486273d9f13SBarry Smith     if (flg) {
487d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
488c134de8dSSatish Balay       *f = (void(*)(void))shell->destroy;
489c7fcc2eaSBarry Smith     } else {
490c134de8dSSatish Balay       *f = (void(*)(void))mat->ops->destroy;
491d4bb536fSBarry Smith     }
492c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
493c134de8dSSatish Balay     *f = (void(*)(void))mat->ops->view;
494c7fcc2eaSBarry Smith   } else {
495c134de8dSSatish Balay     *f = (((void(**)(void))mat->ops)[op]);
496d4bb536fSBarry Smith   }
497d4bb536fSBarry Smith 
4983a40ed3dSBarry Smith   PetscFunctionReturn(0);
499d4bb536fSBarry Smith }
500d4bb536fSBarry Smith 
501