xref: /petsc/src/mat/impls/shell/shell.c (revision 52e6d16ba989af9362d0fcebb12e73dd7c9666ed)
1e51e0e81SBarry Smith /*
220563c6bSBarry Smith    This provides a simple shell for Fortran (and C programmers) to
320563c6bSBarry Smith   create a very simple matrix class for use with KSP without coding
4ed3cc1f0SBarry Smith   much of anything.
5e51e0e81SBarry Smith */
6e51e0e81SBarry Smith 
7e090d566SSatish Balay #include "src/mat/matimpl.h"        /*I "petscmat.h" I*/
83c94ec11SBarry Smith #include "vecimpl.h"
9e51e0e81SBarry Smith 
1020563c6bSBarry Smith typedef struct {
116849ba73SBarry Smith   PetscErrorCode (*destroy)(Mat);
126849ba73SBarry Smith   PetscErrorCode (*mult)(Mat,Vec,Vec);
13ef66eb69SBarry Smith   PetscTruth     scale,shift;
14ef66eb69SBarry Smith   PetscScalar    vscale,vshift;
1520563c6bSBarry Smith   void           *ctx;
1688cf3e7dSBarry Smith } Mat_Shell;
17e51e0e81SBarry Smith 
18711e205bSSatish Balay #undef __FUNCT__
19711e205bSSatish Balay #define __FUNCT__ "MatShellGetContext"
20b4fd4287SBarry Smith /*@
21a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
22b4fd4287SBarry Smith 
23c7fcc2eaSBarry Smith     Not Collective
24c7fcc2eaSBarry Smith 
25b4fd4287SBarry Smith     Input Parameter:
26b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
27b4fd4287SBarry Smith 
28b4fd4287SBarry Smith     Output Parameter:
29b4fd4287SBarry Smith .   ctx - the user provided context
30b4fd4287SBarry Smith 
3115091d37SBarry Smith     Level: advanced
3215091d37SBarry Smith 
33a62d957aSLois Curfman McInnes     Notes:
34a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
35a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
36a62d957aSLois Curfman McInnes 
37a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
38a62d957aSLois Curfman McInnes 
39ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellSetOperation(), MatShellSetContext()
40b4fd4287SBarry Smith @*/
41dfbe8321SBarry Smith PetscErrorCode MatShellGetContext(Mat mat,void **ctx)
42b4fd4287SBarry Smith {
43dfbe8321SBarry Smith   PetscErrorCode ierr;
44273d9f13SBarry Smith   PetscTruth     flg;
45273d9f13SBarry Smith 
463a40ed3dSBarry Smith   PetscFunctionBegin;
474482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
484482741eSBarry Smith   PetscValidPointer(ctx,2);
49273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
50273d9f13SBarry Smith   if (!flg) *ctx = 0;
51b4fd4287SBarry Smith   else      *ctx = ((Mat_Shell*)(mat->data))->ctx;
523a40ed3dSBarry Smith   PetscFunctionReturn(0);
53b4fd4287SBarry Smith }
54b4fd4287SBarry Smith 
55711e205bSSatish Balay #undef __FUNCT__
56711e205bSSatish Balay #define __FUNCT__ "MatDestroy_Shell"
57dfbe8321SBarry Smith PetscErrorCode MatDestroy_Shell(Mat mat)
58e51e0e81SBarry Smith {
59dfbe8321SBarry Smith   PetscErrorCode ierr;
6088cf3e7dSBarry Smith   Mat_Shell      *shell;
61ed3cc1f0SBarry Smith 
623a40ed3dSBarry Smith   PetscFunctionBegin;
6388cf3e7dSBarry Smith   shell = (Mat_Shell*)mat->data;
643a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
65606d414cSSatish Balay   ierr = PetscFree(shell);CHKERRQ(ierr);
663a40ed3dSBarry Smith   PetscFunctionReturn(0);
67e51e0e81SBarry Smith }
68e51e0e81SBarry Smith 
69711e205bSSatish Balay #undef __FUNCT__
70ef66eb69SBarry Smith #define __FUNCT__ "MatMult_Shell"
71dfbe8321SBarry Smith PetscErrorCode MatMult_Shell(Mat A,Vec x,Vec y)
72ef66eb69SBarry Smith {
73ef66eb69SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)A->data;
74dfbe8321SBarry Smith   PetscErrorCode ierr;
75ef66eb69SBarry Smith 
76ef66eb69SBarry Smith   PetscFunctionBegin;
77ef66eb69SBarry Smith   ierr = (*shell->mult)(A,x,y);CHKERRQ(ierr);
78ef66eb69SBarry Smith   if (shell->shift && shell->scale) {
79ef66eb69SBarry Smith     ierr = VecAXPBY(&shell->vshift,&shell->vscale,x,y);CHKERRQ(ierr);
80ef66eb69SBarry Smith   } else if (shell->scale) {
81ef66eb69SBarry Smith     ierr = VecScale(&shell->vscale,y);CHKERRQ(ierr);
82ef66eb69SBarry Smith   } else {
83ef66eb69SBarry Smith     ierr = VecAXPY(&shell->vshift,x,y);CHKERRQ(ierr);
84ef66eb69SBarry Smith   }
85ef66eb69SBarry Smith   PetscFunctionReturn(0);
86ef66eb69SBarry Smith }
87ef66eb69SBarry Smith 
88ef66eb69SBarry Smith #undef __FUNCT__
89ef66eb69SBarry Smith #define __FUNCT__ "MatShift_Shell"
90dfbe8321SBarry Smith PetscErrorCode MatShift_Shell(const PetscScalar *a,Mat Y)
91ef66eb69SBarry Smith {
92ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
93b24ad042SBarry Smith 
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"
108dfbe8321SBarry Smith PetscErrorCode MatScale_Shell(const PetscScalar *a,Mat Y)
109ef66eb69SBarry Smith {
110ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
111b24ad042SBarry Smith 
112ef66eb69SBarry Smith   PetscFunctionBegin;
113ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
114ef66eb69SBarry Smith     shell->vscale *= *a;
115ef66eb69SBarry Smith   } else {
116ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
117ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
118ef66eb69SBarry Smith     shell->vscale = *a;
119ef66eb69SBarry Smith   }
120ef66eb69SBarry Smith   shell->scale  =  PETSC_TRUE;
121ef66eb69SBarry Smith   PetscFunctionReturn(0);
122ef66eb69SBarry Smith }
123ef66eb69SBarry Smith 
124ef66eb69SBarry Smith #undef __FUNCT__
125ef66eb69SBarry Smith #define __FUNCT__ "MatAssemblyEnd_Shell"
126dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_Shell(Mat Y,MatAssemblyType t)
127ef66eb69SBarry Smith {
128ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
129ef66eb69SBarry Smith 
130ef66eb69SBarry Smith   PetscFunctionBegin;
131ef66eb69SBarry Smith   if ((shell->shift || shell->scale) && t == MAT_FINAL_ASSEMBLY) {
132ef66eb69SBarry Smith     shell->scale  = PETSC_FALSE;
133ef66eb69SBarry Smith     shell->shift  = PETSC_FALSE;
134ef66eb69SBarry Smith     shell->vshift = 0.0;
135ef66eb69SBarry Smith     shell->vscale = 1.0;
136ef66eb69SBarry Smith     Y->ops->mult  = shell->mult;
137ef66eb69SBarry Smith   }
138ef66eb69SBarry Smith   PetscFunctionReturn(0);
139ef66eb69SBarry Smith }
140ef66eb69SBarry Smith 
141dfbe8321SBarry Smith EXTERN PetscErrorCode MatConvert_Shell(Mat,const MatType,Mat*);
142b951964fSBarry Smith 
143521d7252SBarry Smith #undef __FUNCT__
144521d7252SBarry Smith #define __FUNCT__ "MatSetBlockSize_Shell"
145521d7252SBarry Smith PetscErrorCode MatSetBlockSize_Shell(Mat A,PetscInt bs)
146521d7252SBarry Smith {
147521d7252SBarry Smith   PetscFunctionBegin;
148521d7252SBarry Smith   PetscFunctionReturn(0);
149521d7252SBarry Smith }
150521d7252SBarry Smith 
15109dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
15220563c6bSBarry Smith        0,
15320563c6bSBarry Smith        0,
15420563c6bSBarry Smith        0,
15597304618SKris Buschelman /* 4*/ 0,
15620563c6bSBarry Smith        0,
157b951964fSBarry Smith        0,
158b951964fSBarry Smith        0,
159b951964fSBarry Smith        0,
160b951964fSBarry Smith        0,
16197304618SKris Buschelman /*10*/ 0,
162b951964fSBarry Smith        0,
163b951964fSBarry Smith        0,
164b951964fSBarry Smith        0,
165b951964fSBarry Smith        0,
16697304618SKris Buschelman /*15*/ 0,
167b951964fSBarry Smith        0,
168b951964fSBarry Smith        0,
169b951964fSBarry Smith        0,
170b951964fSBarry Smith        0,
17197304618SKris Buschelman /*20*/ 0,
172ef66eb69SBarry Smith        MatAssemblyEnd_Shell,
173b951964fSBarry Smith        0,
174b951964fSBarry Smith        0,
175b951964fSBarry Smith        0,
17697304618SKris Buschelman /*25*/ 0,
177b951964fSBarry Smith        0,
178b951964fSBarry Smith        0,
179b951964fSBarry Smith        0,
180b951964fSBarry Smith        0,
18197304618SKris Buschelman /*30*/ 0,
182b951964fSBarry Smith        0,
183273d9f13SBarry Smith        0,
184b951964fSBarry Smith        0,
185b951964fSBarry Smith        0,
18697304618SKris Buschelman /*35*/ 0,
187b951964fSBarry Smith        0,
188b951964fSBarry Smith        0,
18909dc0095SBarry Smith        0,
19009dc0095SBarry Smith        0,
19197304618SKris Buschelman /*40*/ 0,
19209dc0095SBarry Smith        0,
19309dc0095SBarry Smith        0,
19409dc0095SBarry Smith        0,
19509dc0095SBarry Smith        0,
19697304618SKris Buschelman /*45*/ 0,
197ef66eb69SBarry Smith        MatScale_Shell,
198ef66eb69SBarry Smith        MatShift_Shell,
19909dc0095SBarry Smith        0,
20009dc0095SBarry Smith        0,
201521d7252SBarry Smith /*50*/ MatSetBlockSize_Shell,
20209dc0095SBarry Smith        0,
20309dc0095SBarry Smith        0,
20409dc0095SBarry Smith        0,
20509dc0095SBarry Smith        0,
20697304618SKris Buschelman /*55*/ 0,
20709dc0095SBarry Smith        0,
20809dc0095SBarry Smith        0,
20909dc0095SBarry Smith        0,
21009dc0095SBarry Smith        0,
21197304618SKris Buschelman /*60*/ 0,
212b9b97703SBarry Smith        MatDestroy_Shell,
21309dc0095SBarry Smith        0,
2148a124369SBarry Smith        MatGetPetscMaps_Petsc,
215273d9f13SBarry Smith        0,
21697304618SKris Buschelman /*65*/ 0,
217273d9f13SBarry Smith        0,
218273d9f13SBarry Smith        0,
219273d9f13SBarry Smith        0,
220273d9f13SBarry Smith        0,
22197304618SKris Buschelman /*70*/ 0,
22297304618SKris Buschelman        MatConvert_Shell,
223273d9f13SBarry Smith        0,
224273d9f13SBarry Smith        0,
22597304618SKris Buschelman        0,
22697304618SKris Buschelman /*75*/ 0,
22797304618SKris Buschelman        0,
22897304618SKris Buschelman        0,
22997304618SKris Buschelman        0,
23097304618SKris Buschelman        0,
23197304618SKris Buschelman /*80*/ 0,
23297304618SKris Buschelman        0,
23397304618SKris Buschelman        0,
23497304618SKris Buschelman        0,
235865e5f61SKris Buschelman        0,
236865e5f61SKris Buschelman /*85*/ 0,
237865e5f61SKris Buschelman        0,
238865e5f61SKris Buschelman        0,
239865e5f61SKris Buschelman        0,
240865e5f61SKris Buschelman        0,
241865e5f61SKris Buschelman /*90*/ 0,
242865e5f61SKris Buschelman        0,
243865e5f61SKris Buschelman        0,
244865e5f61SKris Buschelman        0,
245865e5f61SKris Buschelman        0,
246865e5f61SKris Buschelman /*95*/ 0,
247865e5f61SKris Buschelman        0,
248865e5f61SKris Buschelman        0,
249865e5f61SKris Buschelman        0};
250273d9f13SBarry Smith 
2510bad9183SKris Buschelman /*MC
252fafad747SKris Buschelman    MATSHELL - MATSHELL = "shell" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
2530bad9183SKris Buschelman 
2540bad9183SKris Buschelman   Level: advanced
2550bad9183SKris Buschelman 
2560bad9183SKris Buschelman .seealso: MatCreateShell
2570bad9183SKris Buschelman M*/
2580bad9183SKris Buschelman 
259273d9f13SBarry Smith EXTERN_C_BEGIN
260711e205bSSatish Balay #undef __FUNCT__
261711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
262dfbe8321SBarry Smith PetscErrorCode MatCreate_Shell(Mat A)
263273d9f13SBarry Smith {
264273d9f13SBarry Smith   Mat_Shell      *b;
265dfbe8321SBarry Smith   PetscErrorCode ierr;
266273d9f13SBarry Smith 
267273d9f13SBarry Smith   PetscFunctionBegin;
268273d9f13SBarry Smith   ierr            = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
269273d9f13SBarry Smith 
270b0a32e0cSBarry Smith   ierr = PetscNew(Mat_Shell,&b);CHKERRQ(ierr);
271*52e6d16bSBarry Smith   ierr = PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell));CHKERRQ(ierr);
272273d9f13SBarry Smith   A->data = (void*)b;
273273d9f13SBarry Smith 
274273d9f13SBarry Smith   if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) {
275e005ede5SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Must give local row and column count for matrix");
276273d9f13SBarry Smith   }
277273d9f13SBarry Smith 
278273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->m,&A->M);CHKERRQ(ierr);
279273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->n,&A->N);CHKERRQ(ierr);
280273d9f13SBarry Smith 
2818a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->m,A->M,&A->rmap);CHKERRQ(ierr);
2828a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->n,A->N,&A->cmap);CHKERRQ(ierr);
283273d9f13SBarry Smith 
284273d9f13SBarry Smith   b->ctx          = 0;
285ef66eb69SBarry Smith   b->scale        = PETSC_FALSE;
286ef66eb69SBarry Smith   b->shift        = PETSC_FALSE;
287ef66eb69SBarry Smith   b->vshift       = 0.0;
288ef66eb69SBarry Smith   b->vscale       = 1.0;
289ef66eb69SBarry Smith   b->mult         = 0;
290273d9f13SBarry Smith   A->assembled    = PETSC_TRUE;
291273d9f13SBarry Smith   A->preallocated = PETSC_TRUE;
292273d9f13SBarry Smith   PetscFunctionReturn(0);
293273d9f13SBarry Smith }
294273d9f13SBarry Smith EXTERN_C_END
295e51e0e81SBarry Smith 
296711e205bSSatish Balay #undef __FUNCT__
297711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
2984b828684SBarry Smith /*@C
299052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
300ff756334SLois Curfman McInnes    private data storage format.
301e51e0e81SBarry Smith 
302c7fcc2eaSBarry Smith   Collective on MPI_Comm
303c7fcc2eaSBarry Smith 
304e51e0e81SBarry Smith    Input Parameters:
305c7fcc2eaSBarry Smith +  comm - MPI communicator
306c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
307c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
308c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
309c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
310c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
311e51e0e81SBarry Smith 
312ff756334SLois Curfman McInnes    Output Parameter:
31344cd7ae7SLois Curfman McInnes .  A - the matrix
314e51e0e81SBarry Smith 
315ff2fd236SBarry Smith    Level: advanced
316ff2fd236SBarry Smith 
317f39d1f56SLois Curfman McInnes   Usage:
3187b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
319f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
320c134de8dSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
321f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
322f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
323f39d1f56SLois Curfman McInnes 
324ff756334SLois Curfman McInnes    Notes:
325ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
326ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
327ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
328e51e0e81SBarry Smith 
329f38a8d56SBarry Smith    Fortran Notes: The context can only be an integer or a PetscObject
330f38a8d56SBarry Smith       unfortunately it cannot be a Fortran array or derived type.
331f38a8d56SBarry Smith 
332f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
333f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
334645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
335645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
336645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
337645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
338645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
339645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
340645985a0SLois Curfman McInnes    For example,
341f39d1f56SLois Curfman McInnes 
342f39d1f56SLois Curfman McInnes $
343f39d1f56SLois Curfman McInnes $     Vec x, y
3447b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
345645985a0SLois Curfman McInnes $     Mat A
346f39d1f56SLois Curfman McInnes $
347c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
348c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
349f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
350c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
351c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
352c134de8dSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
353645985a0SLois Curfman McInnes $     MatMult(A,x,y);
354645985a0SLois Curfman McInnes $     MatDestroy(A);
355f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
356645985a0SLois Curfman McInnes $
357e51e0e81SBarry Smith 
3580b627109SLois Curfman McInnes .keywords: matrix, shell, create
3590b627109SLois Curfman McInnes 
360ab50ec6bSBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext(), MatShellSetContext()
361e51e0e81SBarry Smith @*/
362b24ad042SBarry Smith PetscErrorCode MatCreateShell(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,void *ctx,Mat *A)
363e51e0e81SBarry Smith {
364dfbe8321SBarry Smith   PetscErrorCode ierr;
365ed3cc1f0SBarry Smith 
3663a40ed3dSBarry Smith   PetscFunctionBegin;
367273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,M,N,A);CHKERRQ(ierr);
368273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
369273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
370273d9f13SBarry Smith   PetscFunctionReturn(0);
371c7fcc2eaSBarry Smith }
372c7fcc2eaSBarry Smith 
373711e205bSSatish Balay #undef __FUNCT__
374711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
375273d9f13SBarry Smith /*@C
376273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
377c7fcc2eaSBarry Smith 
378273d9f13SBarry Smith    Collective on Mat
379c7fcc2eaSBarry Smith 
380273d9f13SBarry Smith     Input Parameters:
381273d9f13SBarry Smith +   mat - the shell matrix
382273d9f13SBarry Smith -   ctx - the context
383273d9f13SBarry Smith 
384273d9f13SBarry Smith    Level: advanced
385273d9f13SBarry Smith 
386f38a8d56SBarry Smith    Fortran Notes: The context can only be an integer or a PetscObject
387f38a8d56SBarry Smith       unfortunately it cannot be a Fortran array or derived type.
388273d9f13SBarry Smith 
389273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
390273d9f13SBarry Smith @*/
391dfbe8321SBarry Smith PetscErrorCode MatShellSetContext(Mat mat,void *ctx)
392273d9f13SBarry Smith {
393273d9f13SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)mat->data;
394dfbe8321SBarry Smith   PetscErrorCode ierr;
395273d9f13SBarry Smith   PetscTruth     flg;
396273d9f13SBarry Smith 
397273d9f13SBarry Smith   PetscFunctionBegin;
3984482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
399273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
400273d9f13SBarry Smith   if (flg) {
401273d9f13SBarry Smith     shell->ctx = ctx;
402273d9f13SBarry Smith   }
4033a40ed3dSBarry Smith   PetscFunctionReturn(0);
404e51e0e81SBarry Smith }
405e51e0e81SBarry Smith 
406711e205bSSatish Balay #undef __FUNCT__
407711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
408c16cb8f2SBarry Smith /*@C
4093a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
4103a3eedf2SBarry Smith                            a shell matrix.
411e51e0e81SBarry Smith 
412fee21e36SBarry Smith    Collective on Mat
413fee21e36SBarry Smith 
414c7fcc2eaSBarry Smith     Input Parameters:
415c7fcc2eaSBarry Smith +   mat - the shell matrix
416c7fcc2eaSBarry Smith .   op - the name of the operation
417c7fcc2eaSBarry Smith -   f - the function that provides the operation.
418c7fcc2eaSBarry Smith 
41915091d37SBarry Smith    Level: advanced
42015091d37SBarry Smith 
421fae171e0SBarry Smith     Usage:
422a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
423f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
424c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
4250b627109SLois Curfman McInnes 
426a62d957aSLois Curfman McInnes     Notes:
427e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
4281c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
429a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
4301c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
431a62d957aSLois Curfman McInnes 
432a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
433deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
434deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
435deebb3c3SLois Curfman McInnes     routines, e.g.,
436a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
437a62d957aSLois Curfman McInnes 
438a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
439a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
440a62d957aSLois Curfman McInnes     set by MatCreateShell().
441a62d957aSLois Curfman McInnes 
442a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
443a62d957aSLois Curfman McInnes 
444ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellSetContext()
445e51e0e81SBarry Smith @*/
446dfbe8321SBarry Smith PetscErrorCode MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
447e51e0e81SBarry Smith {
448dfbe8321SBarry Smith   PetscErrorCode ierr;
449273d9f13SBarry Smith   PetscTruth     flg;
450273d9f13SBarry Smith 
4513a40ed3dSBarry Smith   PetscFunctionBegin;
4524482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
4531c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
454273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
455273d9f13SBarry Smith     if (flg) {
456a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
4576849ba73SBarry Smith        shell->destroy                 = (PetscErrorCode (*)(Mat)) f;
4586849ba73SBarry Smith     } else mat->ops->destroy          = (PetscErrorCode (*)(Mat)) f;
459a62d957aSLois Curfman McInnes   }
4606849ba73SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (PetscErrorCode (*)(Mat,PetscViewer)) f;
461c134de8dSSatish Balay   else                       (((void(**)(void))mat->ops)[op]) = f;
462a62d957aSLois Curfman McInnes 
4633a40ed3dSBarry Smith   PetscFunctionReturn(0);
464e51e0e81SBarry Smith }
465f0479e8cSBarry Smith 
466711e205bSSatish Balay #undef __FUNCT__
467711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
468d4bb536fSBarry Smith /*@C
469d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
470d4bb536fSBarry Smith 
471c7fcc2eaSBarry Smith     Not Collective
472c7fcc2eaSBarry Smith 
473d4bb536fSBarry Smith     Input Parameters:
474c7fcc2eaSBarry Smith +   mat - the shell matrix
475c7fcc2eaSBarry Smith -   op - the name of the operation
476d4bb536fSBarry Smith 
477d4bb536fSBarry Smith     Output Parameter:
478d4bb536fSBarry Smith .   f - the function that provides the operation.
479d4bb536fSBarry Smith 
48015091d37SBarry Smith     Level: advanced
48115091d37SBarry Smith 
482d4bb536fSBarry Smith     Notes:
483e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
484d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
485d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
486d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
487d4bb536fSBarry Smith 
488d4bb536fSBarry Smith     All user-provided functions have the same calling
489d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
490d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
491d4bb536fSBarry Smith     routines, e.g.,
492d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
493d4bb536fSBarry Smith 
494d4bb536fSBarry Smith     Within each user-defined routine, the user should call
495d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
496d4bb536fSBarry Smith     set by MatCreateShell().
497d4bb536fSBarry Smith 
498d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
499d4bb536fSBarry Smith 
500ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation(), MatShellSetContext()
501d4bb536fSBarry Smith @*/
502dfbe8321SBarry Smith PetscErrorCode MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
503d4bb536fSBarry Smith {
504dfbe8321SBarry Smith   PetscErrorCode ierr;
505273d9f13SBarry Smith   PetscTruth     flg;
506273d9f13SBarry Smith 
5073a40ed3dSBarry Smith   PetscFunctionBegin;
5084482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
509d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
510273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
511273d9f13SBarry Smith     if (flg) {
512d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
513c134de8dSSatish Balay       *f = (void(*)(void))shell->destroy;
514c7fcc2eaSBarry Smith     } else {
515c134de8dSSatish Balay       *f = (void(*)(void))mat->ops->destroy;
516d4bb536fSBarry Smith     }
517c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
518c134de8dSSatish Balay     *f = (void(*)(void))mat->ops->view;
519c7fcc2eaSBarry Smith   } else {
520c134de8dSSatish Balay     *f = (((void(**)(void))mat->ops)[op]);
521d4bb536fSBarry Smith   }
522d4bb536fSBarry Smith 
5233a40ed3dSBarry Smith   PetscFunctionReturn(0);
524d4bb536fSBarry Smith }
525d4bb536fSBarry Smith 
526