xref: /petsc/src/mat/impls/shell/shell.c (revision b24ad0428a60bb3d8d9be05f5b432634d28bad96)
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;
93*b24ad042SBarry 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;
111*b24ad042SBarry 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 
14309dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
14420563c6bSBarry Smith        0,
14520563c6bSBarry Smith        0,
14620563c6bSBarry Smith        0,
14797304618SKris Buschelman /* 4*/ 0,
14820563c6bSBarry Smith        0,
149b951964fSBarry Smith        0,
150b951964fSBarry Smith        0,
151b951964fSBarry Smith        0,
152b951964fSBarry Smith        0,
15397304618SKris Buschelman /*10*/ 0,
154b951964fSBarry Smith        0,
155b951964fSBarry Smith        0,
156b951964fSBarry Smith        0,
157b951964fSBarry Smith        0,
15897304618SKris Buschelman /*15*/ 0,
159b951964fSBarry Smith        0,
160b951964fSBarry Smith        0,
161b951964fSBarry Smith        0,
162b951964fSBarry Smith        0,
16397304618SKris Buschelman /*20*/ 0,
164ef66eb69SBarry Smith        MatAssemblyEnd_Shell,
165b951964fSBarry Smith        0,
166b951964fSBarry Smith        0,
167b951964fSBarry Smith        0,
16897304618SKris Buschelman /*25*/ 0,
169b951964fSBarry Smith        0,
170b951964fSBarry Smith        0,
171b951964fSBarry Smith        0,
172b951964fSBarry Smith        0,
17397304618SKris Buschelman /*30*/ 0,
174b951964fSBarry Smith        0,
175273d9f13SBarry Smith        0,
176b951964fSBarry Smith        0,
177b951964fSBarry Smith        0,
17897304618SKris Buschelman /*35*/ 0,
179b951964fSBarry Smith        0,
180b951964fSBarry Smith        0,
18109dc0095SBarry Smith        0,
18209dc0095SBarry Smith        0,
18397304618SKris Buschelman /*40*/ 0,
18409dc0095SBarry Smith        0,
18509dc0095SBarry Smith        0,
18609dc0095SBarry Smith        0,
18709dc0095SBarry Smith        0,
18897304618SKris Buschelman /*45*/ 0,
189ef66eb69SBarry Smith        MatScale_Shell,
190ef66eb69SBarry Smith        MatShift_Shell,
19109dc0095SBarry Smith        0,
19209dc0095SBarry Smith        0,
19397304618SKris Buschelman /*50*/ 0,
19409dc0095SBarry Smith        0,
19509dc0095SBarry Smith        0,
19609dc0095SBarry Smith        0,
19709dc0095SBarry Smith        0,
19897304618SKris Buschelman /*55*/ 0,
19909dc0095SBarry Smith        0,
20009dc0095SBarry Smith        0,
20109dc0095SBarry Smith        0,
20209dc0095SBarry Smith        0,
20397304618SKris Buschelman /*60*/ 0,
204b9b97703SBarry Smith        MatDestroy_Shell,
20509dc0095SBarry Smith        0,
2068a124369SBarry Smith        MatGetPetscMaps_Petsc,
207273d9f13SBarry Smith        0,
20897304618SKris Buschelman /*65*/ 0,
209273d9f13SBarry Smith        0,
210273d9f13SBarry Smith        0,
211273d9f13SBarry Smith        0,
212273d9f13SBarry Smith        0,
21397304618SKris Buschelman /*70*/ 0,
21497304618SKris Buschelman        MatConvert_Shell,
215273d9f13SBarry Smith        0,
216273d9f13SBarry Smith        0,
21797304618SKris Buschelman        0,
21897304618SKris Buschelman /*75*/ 0,
21997304618SKris Buschelman        0,
22097304618SKris Buschelman        0,
22197304618SKris Buschelman        0,
22297304618SKris Buschelman        0,
22397304618SKris Buschelman /*80*/ 0,
22497304618SKris Buschelman        0,
22597304618SKris Buschelman        0,
22697304618SKris Buschelman        0,
227865e5f61SKris Buschelman        0,
228865e5f61SKris Buschelman /*85*/ 0,
229865e5f61SKris Buschelman        0,
230865e5f61SKris Buschelman        0,
231865e5f61SKris Buschelman        0,
232865e5f61SKris Buschelman        0,
233865e5f61SKris Buschelman /*90*/ 0,
234865e5f61SKris Buschelman        0,
235865e5f61SKris Buschelman        0,
236865e5f61SKris Buschelman        0,
237865e5f61SKris Buschelman        0,
238865e5f61SKris Buschelman /*95*/ 0,
239865e5f61SKris Buschelman        0,
240865e5f61SKris Buschelman        0,
241865e5f61SKris Buschelman        0};
242273d9f13SBarry Smith 
2430bad9183SKris Buschelman /*MC
244fafad747SKris Buschelman    MATSHELL - MATSHELL = "shell" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
2450bad9183SKris Buschelman 
2460bad9183SKris Buschelman   Level: advanced
2470bad9183SKris Buschelman 
2480bad9183SKris Buschelman .seealso: MatCreateShell
2490bad9183SKris Buschelman M*/
2500bad9183SKris Buschelman 
251273d9f13SBarry Smith EXTERN_C_BEGIN
252711e205bSSatish Balay #undef __FUNCT__
253711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
254dfbe8321SBarry Smith PetscErrorCode MatCreate_Shell(Mat A)
255273d9f13SBarry Smith {
256273d9f13SBarry Smith   Mat_Shell      *b;
257dfbe8321SBarry Smith   PetscErrorCode ierr;
258273d9f13SBarry Smith 
259273d9f13SBarry Smith   PetscFunctionBegin;
260273d9f13SBarry Smith   ierr            = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
261273d9f13SBarry Smith 
262b0a32e0cSBarry Smith   ierr = PetscNew(Mat_Shell,&b);CHKERRQ(ierr);
263b0a32e0cSBarry Smith   PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
264273d9f13SBarry Smith   ierr    = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr);
265273d9f13SBarry Smith   A->data = (void*)b;
266273d9f13SBarry Smith 
267273d9f13SBarry Smith   if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) {
268e005ede5SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Must give local row and column count for matrix");
269273d9f13SBarry Smith   }
270273d9f13SBarry Smith 
271273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->m,&A->M);CHKERRQ(ierr);
272273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->n,&A->N);CHKERRQ(ierr);
273273d9f13SBarry Smith 
2748a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->m,A->M,&A->rmap);CHKERRQ(ierr);
2758a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->n,A->N,&A->cmap);CHKERRQ(ierr);
276273d9f13SBarry Smith 
277273d9f13SBarry Smith   b->ctx          = 0;
278ef66eb69SBarry Smith   b->scale        = PETSC_FALSE;
279ef66eb69SBarry Smith   b->shift        = PETSC_FALSE;
280ef66eb69SBarry Smith   b->vshift       = 0.0;
281ef66eb69SBarry Smith   b->vscale       = 1.0;
282ef66eb69SBarry Smith   b->mult         = 0;
283273d9f13SBarry Smith   A->assembled    = PETSC_TRUE;
284273d9f13SBarry Smith   A->preallocated = PETSC_TRUE;
285273d9f13SBarry Smith   PetscFunctionReturn(0);
286273d9f13SBarry Smith }
287273d9f13SBarry Smith EXTERN_C_END
288e51e0e81SBarry Smith 
289711e205bSSatish Balay #undef __FUNCT__
290711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
2914b828684SBarry Smith /*@C
292052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
293ff756334SLois Curfman McInnes    private data storage format.
294e51e0e81SBarry Smith 
295c7fcc2eaSBarry Smith   Collective on MPI_Comm
296c7fcc2eaSBarry Smith 
297e51e0e81SBarry Smith    Input Parameters:
298c7fcc2eaSBarry Smith +  comm - MPI communicator
299c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
300c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
301c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
302c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
303c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
304e51e0e81SBarry Smith 
305ff756334SLois Curfman McInnes    Output Parameter:
30644cd7ae7SLois Curfman McInnes .  A - the matrix
307e51e0e81SBarry Smith 
308ff2fd236SBarry Smith    Level: advanced
309ff2fd236SBarry Smith 
310f39d1f56SLois Curfman McInnes   Usage:
3117b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
312f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
313c134de8dSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
314f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
315f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
316f39d1f56SLois Curfman McInnes 
317ff756334SLois Curfman McInnes    Notes:
318ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
319ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
320ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
321e51e0e81SBarry Smith 
322f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
323f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
324645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
325645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
326645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
327645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
328645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
329645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
330645985a0SLois Curfman McInnes    For example,
331f39d1f56SLois Curfman McInnes 
332f39d1f56SLois Curfman McInnes $
333f39d1f56SLois Curfman McInnes $     Vec x, y
3347b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
335645985a0SLois Curfman McInnes $     Mat A
336f39d1f56SLois Curfman McInnes $
337c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
338c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
339f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
340c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
341c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
342c134de8dSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
343645985a0SLois Curfman McInnes $     MatMult(A,x,y);
344645985a0SLois Curfman McInnes $     MatDestroy(A);
345f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
346645985a0SLois Curfman McInnes $
347e51e0e81SBarry Smith 
3480b627109SLois Curfman McInnes .keywords: matrix, shell, create
3490b627109SLois Curfman McInnes 
350ab50ec6bSBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext(), MatShellSetContext()
351e51e0e81SBarry Smith @*/
352*b24ad042SBarry Smith PetscErrorCode MatCreateShell(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,void *ctx,Mat *A)
353e51e0e81SBarry Smith {
354dfbe8321SBarry Smith   PetscErrorCode ierr;
355ed3cc1f0SBarry Smith 
3563a40ed3dSBarry Smith   PetscFunctionBegin;
357273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,M,N,A);CHKERRQ(ierr);
358273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
359273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
360273d9f13SBarry Smith   PetscFunctionReturn(0);
361c7fcc2eaSBarry Smith }
362c7fcc2eaSBarry Smith 
363711e205bSSatish Balay #undef __FUNCT__
364711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
365273d9f13SBarry Smith /*@C
366273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
367c7fcc2eaSBarry Smith 
368273d9f13SBarry Smith    Collective on Mat
369c7fcc2eaSBarry Smith 
370273d9f13SBarry Smith     Input Parameters:
371273d9f13SBarry Smith +   mat - the shell matrix
372273d9f13SBarry Smith -   ctx - the context
373273d9f13SBarry Smith 
374273d9f13SBarry Smith    Level: advanced
375273d9f13SBarry Smith 
376273d9f13SBarry Smith 
377273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
378273d9f13SBarry Smith @*/
379dfbe8321SBarry Smith PetscErrorCode MatShellSetContext(Mat mat,void *ctx)
380273d9f13SBarry Smith {
381273d9f13SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)mat->data;
382dfbe8321SBarry Smith   PetscErrorCode ierr;
383273d9f13SBarry Smith   PetscTruth     flg;
384273d9f13SBarry Smith 
385273d9f13SBarry Smith   PetscFunctionBegin;
3864482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
387273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
388273d9f13SBarry Smith   if (flg) {
389273d9f13SBarry Smith     shell->ctx = ctx;
390273d9f13SBarry Smith   }
3913a40ed3dSBarry Smith   PetscFunctionReturn(0);
392e51e0e81SBarry Smith }
393e51e0e81SBarry Smith 
394711e205bSSatish Balay #undef __FUNCT__
395711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
396c16cb8f2SBarry Smith /*@C
3973a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
3983a3eedf2SBarry Smith                            a shell matrix.
399e51e0e81SBarry Smith 
400fee21e36SBarry Smith    Collective on Mat
401fee21e36SBarry Smith 
402c7fcc2eaSBarry Smith     Input Parameters:
403c7fcc2eaSBarry Smith +   mat - the shell matrix
404c7fcc2eaSBarry Smith .   op - the name of the operation
405c7fcc2eaSBarry Smith -   f - the function that provides the operation.
406c7fcc2eaSBarry Smith 
40715091d37SBarry Smith    Level: advanced
40815091d37SBarry Smith 
409fae171e0SBarry Smith     Usage:
410a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
411f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
412c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
4130b627109SLois Curfman McInnes 
414a62d957aSLois Curfman McInnes     Notes:
415e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
4161c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
417a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
4181c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
419a62d957aSLois Curfman McInnes 
420a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
421deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
422deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
423deebb3c3SLois Curfman McInnes     routines, e.g.,
424a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
425a62d957aSLois Curfman McInnes 
426a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
427a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
428a62d957aSLois Curfman McInnes     set by MatCreateShell().
429a62d957aSLois Curfman McInnes 
430a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
431a62d957aSLois Curfman McInnes 
432ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellSetContext()
433e51e0e81SBarry Smith @*/
434dfbe8321SBarry Smith PetscErrorCode MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
435e51e0e81SBarry Smith {
436dfbe8321SBarry Smith   PetscErrorCode ierr;
437273d9f13SBarry Smith   PetscTruth     flg;
438273d9f13SBarry Smith 
4393a40ed3dSBarry Smith   PetscFunctionBegin;
4404482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
4411c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
442273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
443273d9f13SBarry Smith     if (flg) {
444a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
4456849ba73SBarry Smith        shell->destroy                 = (PetscErrorCode (*)(Mat)) f;
4466849ba73SBarry Smith     } else mat->ops->destroy          = (PetscErrorCode (*)(Mat)) f;
447a62d957aSLois Curfman McInnes   }
4486849ba73SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (PetscErrorCode (*)(Mat,PetscViewer)) f;
449c134de8dSSatish Balay   else                       (((void(**)(void))mat->ops)[op]) = f;
450a62d957aSLois Curfman McInnes 
4513a40ed3dSBarry Smith   PetscFunctionReturn(0);
452e51e0e81SBarry Smith }
453f0479e8cSBarry Smith 
454711e205bSSatish Balay #undef __FUNCT__
455711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
456d4bb536fSBarry Smith /*@C
457d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
458d4bb536fSBarry Smith 
459c7fcc2eaSBarry Smith     Not Collective
460c7fcc2eaSBarry Smith 
461d4bb536fSBarry Smith     Input Parameters:
462c7fcc2eaSBarry Smith +   mat - the shell matrix
463c7fcc2eaSBarry Smith -   op - the name of the operation
464d4bb536fSBarry Smith 
465d4bb536fSBarry Smith     Output Parameter:
466d4bb536fSBarry Smith .   f - the function that provides the operation.
467d4bb536fSBarry Smith 
46815091d37SBarry Smith     Level: advanced
46915091d37SBarry Smith 
470d4bb536fSBarry Smith     Notes:
471e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
472d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
473d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
474d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
475d4bb536fSBarry Smith 
476d4bb536fSBarry Smith     All user-provided functions have the same calling
477d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
478d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
479d4bb536fSBarry Smith     routines, e.g.,
480d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
481d4bb536fSBarry Smith 
482d4bb536fSBarry Smith     Within each user-defined routine, the user should call
483d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
484d4bb536fSBarry Smith     set by MatCreateShell().
485d4bb536fSBarry Smith 
486d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
487d4bb536fSBarry Smith 
488ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation(), MatShellSetContext()
489d4bb536fSBarry Smith @*/
490dfbe8321SBarry Smith PetscErrorCode MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
491d4bb536fSBarry Smith {
492dfbe8321SBarry Smith   PetscErrorCode ierr;
493273d9f13SBarry Smith   PetscTruth     flg;
494273d9f13SBarry Smith 
4953a40ed3dSBarry Smith   PetscFunctionBegin;
4964482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
497d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
498273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
499273d9f13SBarry Smith     if (flg) {
500d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
501c134de8dSSatish Balay       *f = (void(*)(void))shell->destroy;
502c7fcc2eaSBarry Smith     } else {
503c134de8dSSatish Balay       *f = (void(*)(void))mat->ops->destroy;
504d4bb536fSBarry Smith     }
505c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
506c134de8dSSatish Balay     *f = (void(*)(void))mat->ops->view;
507c7fcc2eaSBarry Smith   } else {
508c134de8dSSatish Balay     *f = (((void(**)(void))mat->ops)[op]);
509d4bb536fSBarry Smith   }
510d4bb536fSBarry Smith 
5113a40ed3dSBarry Smith   PetscFunctionReturn(0);
512d4bb536fSBarry Smith }
513d4bb536fSBarry Smith 
514