xref: /petsc/src/mat/impls/shell/shell.c (revision e005ede52eafe2fed2813abb7a7eb3df04d5f886)
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;
93ef66eb69SBarry Smith   PetscFunctionBegin;
94ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
95ef66eb69SBarry Smith     shell->vshift += *a;
96ef66eb69SBarry Smith   } else {
97ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
98ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
99ef66eb69SBarry Smith     shell->vshift = *a;
100ef66eb69SBarry Smith   }
101ef66eb69SBarry Smith   shell->shift  =  PETSC_TRUE;
102ef66eb69SBarry Smith   PetscFunctionReturn(0);
103ef66eb69SBarry Smith }
104ef66eb69SBarry Smith 
105ef66eb69SBarry Smith #undef __FUNCT__
106ef66eb69SBarry Smith #define __FUNCT__ "MatScale_Shell"
107dfbe8321SBarry Smith PetscErrorCode MatScale_Shell(const PetscScalar *a,Mat Y)
108ef66eb69SBarry Smith {
109ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
110ef66eb69SBarry Smith   PetscFunctionBegin;
111ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
112ef66eb69SBarry Smith     shell->vscale *= *a;
113ef66eb69SBarry Smith   } else {
114ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
115ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
116ef66eb69SBarry Smith     shell->vscale = *a;
117ef66eb69SBarry Smith   }
118ef66eb69SBarry Smith   shell->scale  =  PETSC_TRUE;
119ef66eb69SBarry Smith   PetscFunctionReturn(0);
120ef66eb69SBarry Smith }
121ef66eb69SBarry Smith 
122ef66eb69SBarry Smith #undef __FUNCT__
123ef66eb69SBarry Smith #define __FUNCT__ "MatAssemblyEnd_Shell"
124dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_Shell(Mat Y,MatAssemblyType t)
125ef66eb69SBarry Smith {
126ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
127ef66eb69SBarry Smith 
128ef66eb69SBarry Smith   PetscFunctionBegin;
129ef66eb69SBarry Smith   if ((shell->shift || shell->scale) && t == MAT_FINAL_ASSEMBLY) {
130ef66eb69SBarry Smith     shell->scale  = PETSC_FALSE;
131ef66eb69SBarry Smith     shell->shift  = PETSC_FALSE;
132ef66eb69SBarry Smith     shell->vshift = 0.0;
133ef66eb69SBarry Smith     shell->vscale = 1.0;
134ef66eb69SBarry Smith     Y->ops->mult  = shell->mult;
135ef66eb69SBarry Smith   }
136ef66eb69SBarry Smith   PetscFunctionReturn(0);
137ef66eb69SBarry Smith }
138ef66eb69SBarry Smith 
139dfbe8321SBarry Smith EXTERN PetscErrorCode MatConvert_Shell(Mat,const MatType,Mat*);
140b951964fSBarry Smith 
14109dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
14220563c6bSBarry Smith        0,
14320563c6bSBarry Smith        0,
14420563c6bSBarry Smith        0,
14597304618SKris Buschelman /* 4*/ 0,
14620563c6bSBarry Smith        0,
147b951964fSBarry Smith        0,
148b951964fSBarry Smith        0,
149b951964fSBarry Smith        0,
150b951964fSBarry Smith        0,
15197304618SKris Buschelman /*10*/ 0,
152b951964fSBarry Smith        0,
153b951964fSBarry Smith        0,
154b951964fSBarry Smith        0,
155b951964fSBarry Smith        0,
15697304618SKris Buschelman /*15*/ 0,
157b951964fSBarry Smith        0,
158b951964fSBarry Smith        0,
159b951964fSBarry Smith        0,
160b951964fSBarry Smith        0,
16197304618SKris Buschelman /*20*/ 0,
162ef66eb69SBarry Smith        MatAssemblyEnd_Shell,
163b951964fSBarry Smith        0,
164b951964fSBarry Smith        0,
165b951964fSBarry Smith        0,
16697304618SKris Buschelman /*25*/ 0,
167b951964fSBarry Smith        0,
168b951964fSBarry Smith        0,
169b951964fSBarry Smith        0,
170b951964fSBarry Smith        0,
17197304618SKris Buschelman /*30*/ 0,
172b951964fSBarry Smith        0,
173273d9f13SBarry Smith        0,
174b951964fSBarry Smith        0,
175b951964fSBarry Smith        0,
17697304618SKris Buschelman /*35*/ 0,
177b951964fSBarry Smith        0,
178b951964fSBarry Smith        0,
17909dc0095SBarry Smith        0,
18009dc0095SBarry Smith        0,
18197304618SKris Buschelman /*40*/ 0,
18209dc0095SBarry Smith        0,
18309dc0095SBarry Smith        0,
18409dc0095SBarry Smith        0,
18509dc0095SBarry Smith        0,
18697304618SKris Buschelman /*45*/ 0,
187ef66eb69SBarry Smith        MatScale_Shell,
188ef66eb69SBarry Smith        MatShift_Shell,
18909dc0095SBarry Smith        0,
19009dc0095SBarry Smith        0,
19197304618SKris Buschelman /*50*/ 0,
19209dc0095SBarry Smith        0,
19309dc0095SBarry Smith        0,
19409dc0095SBarry Smith        0,
19509dc0095SBarry Smith        0,
19697304618SKris Buschelman /*55*/ 0,
19709dc0095SBarry Smith        0,
19809dc0095SBarry Smith        0,
19909dc0095SBarry Smith        0,
20009dc0095SBarry Smith        0,
20197304618SKris Buschelman /*60*/ 0,
202b9b97703SBarry Smith        MatDestroy_Shell,
20309dc0095SBarry Smith        0,
2048a124369SBarry Smith        MatGetPetscMaps_Petsc,
205273d9f13SBarry Smith        0,
20697304618SKris Buschelman /*65*/ 0,
207273d9f13SBarry Smith        0,
208273d9f13SBarry Smith        0,
209273d9f13SBarry Smith        0,
210273d9f13SBarry Smith        0,
21197304618SKris Buschelman /*70*/ 0,
21297304618SKris Buschelman        MatConvert_Shell,
213273d9f13SBarry Smith        0,
214273d9f13SBarry Smith        0,
21597304618SKris Buschelman        0,
21697304618SKris Buschelman /*75*/ 0,
21797304618SKris Buschelman        0,
21897304618SKris Buschelman        0,
21997304618SKris Buschelman        0,
22097304618SKris Buschelman        0,
22197304618SKris Buschelman /*80*/ 0,
22297304618SKris Buschelman        0,
22397304618SKris Buschelman        0,
22497304618SKris Buschelman        0,
225865e5f61SKris Buschelman        0,
226865e5f61SKris Buschelman /*85*/ 0,
227865e5f61SKris Buschelman        0,
228865e5f61SKris Buschelman        0,
229865e5f61SKris Buschelman        0,
230865e5f61SKris Buschelman        0,
231865e5f61SKris Buschelman /*90*/ 0,
232865e5f61SKris Buschelman        0,
233865e5f61SKris Buschelman        0,
234865e5f61SKris Buschelman        0,
235865e5f61SKris Buschelman        0,
236865e5f61SKris Buschelman /*95*/ 0,
237865e5f61SKris Buschelman        0,
238865e5f61SKris Buschelman        0,
239865e5f61SKris Buschelman        0};
240273d9f13SBarry Smith 
2410bad9183SKris Buschelman /*MC
242fafad747SKris Buschelman    MATSHELL - MATSHELL = "shell" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
2430bad9183SKris Buschelman 
2440bad9183SKris Buschelman   Level: advanced
2450bad9183SKris Buschelman 
2460bad9183SKris Buschelman .seealso: MatCreateShell
2470bad9183SKris Buschelman M*/
2480bad9183SKris Buschelman 
249273d9f13SBarry Smith EXTERN_C_BEGIN
250711e205bSSatish Balay #undef __FUNCT__
251711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
252dfbe8321SBarry Smith PetscErrorCode MatCreate_Shell(Mat A)
253273d9f13SBarry Smith {
254273d9f13SBarry Smith   Mat_Shell *b;
255dfbe8321SBarry Smith   PetscErrorCode ierr;
256273d9f13SBarry Smith 
257273d9f13SBarry Smith   PetscFunctionBegin;
258273d9f13SBarry Smith   ierr            = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
259273d9f13SBarry Smith 
260b0a32e0cSBarry Smith   ierr = PetscNew(Mat_Shell,&b);CHKERRQ(ierr);
261b0a32e0cSBarry Smith   PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
262273d9f13SBarry Smith   ierr    = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr);
263273d9f13SBarry Smith   A->data = (void*)b;
264273d9f13SBarry Smith 
265273d9f13SBarry Smith   if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) {
266*e005ede5SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Must give local row and column count for matrix");
267273d9f13SBarry Smith   }
268273d9f13SBarry Smith 
269273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->m,&A->M);CHKERRQ(ierr);
270273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->n,&A->N);CHKERRQ(ierr);
271273d9f13SBarry Smith 
2728a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->m,A->M,&A->rmap);CHKERRQ(ierr);
2738a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->n,A->N,&A->cmap);CHKERRQ(ierr);
274273d9f13SBarry Smith 
275273d9f13SBarry Smith   b->ctx          = 0;
276ef66eb69SBarry Smith   b->scale        = PETSC_FALSE;
277ef66eb69SBarry Smith   b->shift        = PETSC_FALSE;
278ef66eb69SBarry Smith   b->vshift       = 0.0;
279ef66eb69SBarry Smith   b->vscale       = 1.0;
280ef66eb69SBarry Smith   b->mult         = 0;
281273d9f13SBarry Smith   A->assembled    = PETSC_TRUE;
282273d9f13SBarry Smith   A->preallocated = PETSC_TRUE;
283273d9f13SBarry Smith   PetscFunctionReturn(0);
284273d9f13SBarry Smith }
285273d9f13SBarry Smith EXTERN_C_END
286e51e0e81SBarry Smith 
287711e205bSSatish Balay #undef __FUNCT__
288711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
2894b828684SBarry Smith /*@C
290052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
291ff756334SLois Curfman McInnes    private data storage format.
292e51e0e81SBarry Smith 
293c7fcc2eaSBarry Smith   Collective on MPI_Comm
294c7fcc2eaSBarry Smith 
295e51e0e81SBarry Smith    Input Parameters:
296c7fcc2eaSBarry Smith +  comm - MPI communicator
297c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
298c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
299c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
300c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
301c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
302e51e0e81SBarry Smith 
303ff756334SLois Curfman McInnes    Output Parameter:
30444cd7ae7SLois Curfman McInnes .  A - the matrix
305e51e0e81SBarry Smith 
306ff2fd236SBarry Smith    Level: advanced
307ff2fd236SBarry Smith 
308f39d1f56SLois Curfman McInnes   Usage:
3097b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
310f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
311c134de8dSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
312f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
313f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
314f39d1f56SLois Curfman McInnes 
315ff756334SLois Curfman McInnes    Notes:
316ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
317ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
318ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
319e51e0e81SBarry Smith 
320f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
321f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
322645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
323645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
324645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
325645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
326645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
327645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
328645985a0SLois Curfman McInnes    For example,
329f39d1f56SLois Curfman McInnes 
330f39d1f56SLois Curfman McInnes $
331f39d1f56SLois Curfman McInnes $     Vec x, y
3327b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
333645985a0SLois Curfman McInnes $     Mat A
334f39d1f56SLois Curfman McInnes $
335c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
336c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
337f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
338c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
339c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
340c134de8dSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
341645985a0SLois Curfman McInnes $     MatMult(A,x,y);
342645985a0SLois Curfman McInnes $     MatDestroy(A);
343f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
344645985a0SLois Curfman McInnes $
345e51e0e81SBarry Smith 
3460b627109SLois Curfman McInnes .keywords: matrix, shell, create
3470b627109SLois Curfman McInnes 
348ab50ec6bSBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext(), MatShellSetContext()
349e51e0e81SBarry Smith @*/
350dfbe8321SBarry Smith PetscErrorCode MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
351e51e0e81SBarry Smith {
352dfbe8321SBarry Smith   PetscErrorCode ierr;
353ed3cc1f0SBarry Smith 
3543a40ed3dSBarry Smith   PetscFunctionBegin;
355273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,M,N,A);CHKERRQ(ierr);
356273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
357273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
358273d9f13SBarry Smith   PetscFunctionReturn(0);
359c7fcc2eaSBarry Smith }
360c7fcc2eaSBarry Smith 
361711e205bSSatish Balay #undef __FUNCT__
362711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
363273d9f13SBarry Smith /*@C
364273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
365c7fcc2eaSBarry Smith 
366273d9f13SBarry Smith    Collective on Mat
367c7fcc2eaSBarry Smith 
368273d9f13SBarry Smith     Input Parameters:
369273d9f13SBarry Smith +   mat - the shell matrix
370273d9f13SBarry Smith -   ctx - the context
371273d9f13SBarry Smith 
372273d9f13SBarry Smith    Level: advanced
373273d9f13SBarry Smith 
374273d9f13SBarry Smith 
375273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
376273d9f13SBarry Smith @*/
377dfbe8321SBarry Smith PetscErrorCode MatShellSetContext(Mat mat,void *ctx)
378273d9f13SBarry Smith {
379273d9f13SBarry Smith   Mat_Shell  *shell = (Mat_Shell*)mat->data;
380dfbe8321SBarry Smith   PetscErrorCode ierr;
381273d9f13SBarry Smith   PetscTruth flg;
382273d9f13SBarry Smith 
383273d9f13SBarry Smith   PetscFunctionBegin;
3844482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
385273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
386273d9f13SBarry Smith   if (flg) {
387273d9f13SBarry Smith     shell->ctx = ctx;
388273d9f13SBarry Smith   }
3893a40ed3dSBarry Smith   PetscFunctionReturn(0);
390e51e0e81SBarry Smith }
391e51e0e81SBarry Smith 
392711e205bSSatish Balay #undef __FUNCT__
393711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
394c16cb8f2SBarry Smith /*@C
3953a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
3963a3eedf2SBarry Smith                            a shell matrix.
397e51e0e81SBarry Smith 
398fee21e36SBarry Smith    Collective on Mat
399fee21e36SBarry Smith 
400c7fcc2eaSBarry Smith     Input Parameters:
401c7fcc2eaSBarry Smith +   mat - the shell matrix
402c7fcc2eaSBarry Smith .   op - the name of the operation
403c7fcc2eaSBarry Smith -   f - the function that provides the operation.
404c7fcc2eaSBarry Smith 
40515091d37SBarry Smith    Level: advanced
40615091d37SBarry Smith 
407fae171e0SBarry Smith     Usage:
408a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
409f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
410c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
4110b627109SLois Curfman McInnes 
412a62d957aSLois Curfman McInnes     Notes:
413e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
4141c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
415a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
4161c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
417a62d957aSLois Curfman McInnes 
418a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
419deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
420deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
421deebb3c3SLois Curfman McInnes     routines, e.g.,
422a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
423a62d957aSLois Curfman McInnes 
424a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
425a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
426a62d957aSLois Curfman McInnes     set by MatCreateShell().
427a62d957aSLois Curfman McInnes 
428a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
429a62d957aSLois Curfman McInnes 
430ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellSetContext()
431e51e0e81SBarry Smith @*/
432dfbe8321SBarry Smith PetscErrorCode MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
433e51e0e81SBarry Smith {
434dfbe8321SBarry Smith   PetscErrorCode ierr;
435273d9f13SBarry Smith   PetscTruth flg;
436273d9f13SBarry Smith 
4373a40ed3dSBarry Smith   PetscFunctionBegin;
4384482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
4391c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
440273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
441273d9f13SBarry Smith     if (flg) {
442a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
4436849ba73SBarry Smith        shell->destroy                 = (PetscErrorCode (*)(Mat)) f;
4446849ba73SBarry Smith     } else mat->ops->destroy            = (PetscErrorCode (*)(Mat)) f;
445a62d957aSLois Curfman McInnes   }
4466849ba73SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (PetscErrorCode (*)(Mat,PetscViewer)) f;
447c134de8dSSatish Balay   else                       (((void(**)(void))mat->ops)[op]) = f;
448a62d957aSLois Curfman McInnes 
4493a40ed3dSBarry Smith   PetscFunctionReturn(0);
450e51e0e81SBarry Smith }
451f0479e8cSBarry Smith 
452711e205bSSatish Balay #undef __FUNCT__
453711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
454d4bb536fSBarry Smith /*@C
455d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
456d4bb536fSBarry Smith 
457c7fcc2eaSBarry Smith     Not Collective
458c7fcc2eaSBarry Smith 
459d4bb536fSBarry Smith     Input Parameters:
460c7fcc2eaSBarry Smith +   mat - the shell matrix
461c7fcc2eaSBarry Smith -   op - the name of the operation
462d4bb536fSBarry Smith 
463d4bb536fSBarry Smith     Output Parameter:
464d4bb536fSBarry Smith .   f - the function that provides the operation.
465d4bb536fSBarry Smith 
46615091d37SBarry Smith     Level: advanced
46715091d37SBarry Smith 
468d4bb536fSBarry Smith     Notes:
469e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
470d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
471d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
472d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
473d4bb536fSBarry Smith 
474d4bb536fSBarry Smith     All user-provided functions have the same calling
475d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
476d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
477d4bb536fSBarry Smith     routines, e.g.,
478d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
479d4bb536fSBarry Smith 
480d4bb536fSBarry Smith     Within each user-defined routine, the user should call
481d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
482d4bb536fSBarry Smith     set by MatCreateShell().
483d4bb536fSBarry Smith 
484d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
485d4bb536fSBarry Smith 
486ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation(), MatShellSetContext()
487d4bb536fSBarry Smith @*/
488dfbe8321SBarry Smith PetscErrorCode MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
489d4bb536fSBarry Smith {
490dfbe8321SBarry Smith   PetscErrorCode ierr;
491273d9f13SBarry Smith   PetscTruth flg;
492273d9f13SBarry Smith 
4933a40ed3dSBarry Smith   PetscFunctionBegin;
4944482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
495d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
496273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
497273d9f13SBarry Smith     if (flg) {
498d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
499c134de8dSSatish Balay       *f = (void(*)(void))shell->destroy;
500c7fcc2eaSBarry Smith     } else {
501c134de8dSSatish Balay       *f = (void(*)(void))mat->ops->destroy;
502d4bb536fSBarry Smith     }
503c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
504c134de8dSSatish Balay     *f = (void(*)(void))mat->ops->view;
505c7fcc2eaSBarry Smith   } else {
506c134de8dSSatish Balay     *f = (((void(**)(void))mat->ops)[op]);
507d4bb536fSBarry Smith   }
508d4bb536fSBarry Smith 
5093a40ed3dSBarry Smith   PetscFunctionReturn(0);
510d4bb536fSBarry Smith }
511d4bb536fSBarry Smith 
512