xref: /petsc/src/mat/impls/shell/shell.c (revision ef66eb6987ddfdf4e414d6b820cbc8d8d7d17bc2)
1*ef66eb69SBarry Smith /*$Id: shell.c,v 1.87 2001/07/20 21:20:12 bsmith Exp bsmith $*/
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);
14*ef66eb69SBarry Smith   int         (*mult)(Mat,Vec,Vec);
15*ef66eb69SBarry Smith   PetscTruth  scale,shift;
16*ef66eb69SBarry Smith   PetscScalar vscale,vshift;
1720563c6bSBarry Smith   void        *ctx;
1888cf3e7dSBarry Smith } Mat_Shell;
19e51e0e81SBarry Smith 
20711e205bSSatish Balay #undef __FUNCT__
21711e205bSSatish Balay #define __FUNCT__ "MatShellGetContext"
22b4fd4287SBarry Smith /*@
23a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
24b4fd4287SBarry Smith 
25c7fcc2eaSBarry Smith     Not Collective
26c7fcc2eaSBarry Smith 
27b4fd4287SBarry Smith     Input Parameter:
28b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
29b4fd4287SBarry Smith 
30b4fd4287SBarry Smith     Output Parameter:
31b4fd4287SBarry Smith .   ctx - the user provided context
32b4fd4287SBarry Smith 
3315091d37SBarry Smith     Level: advanced
3415091d37SBarry Smith 
35a62d957aSLois Curfman McInnes     Notes:
36a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
37a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
38a62d957aSLois Curfman McInnes 
39a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
40a62d957aSLois Curfman McInnes 
41a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation()
42b4fd4287SBarry Smith @*/
43b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx)
44b4fd4287SBarry Smith {
45273d9f13SBarry Smith   int        ierr;
46273d9f13SBarry Smith   PetscTruth flg;
47273d9f13SBarry Smith 
483a40ed3dSBarry Smith   PetscFunctionBegin;
4977c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
50273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
51273d9f13SBarry Smith   if (!flg) *ctx = 0;
52b4fd4287SBarry Smith   else      *ctx = ((Mat_Shell*)(mat->data))->ctx;
533a40ed3dSBarry Smith   PetscFunctionReturn(0);
54b4fd4287SBarry Smith }
55b4fd4287SBarry Smith 
56711e205bSSatish Balay #undef __FUNCT__
57711e205bSSatish Balay #define __FUNCT__ "MatDestroy_Shell"
58e1311b90SBarry Smith int MatDestroy_Shell(Mat mat)
59e51e0e81SBarry Smith {
60b9fa9cd0SBarry Smith   int       ierr;
6188cf3e7dSBarry Smith   Mat_Shell *shell;
62ed3cc1f0SBarry Smith 
633a40ed3dSBarry Smith   PetscFunctionBegin;
6488cf3e7dSBarry Smith   shell = (Mat_Shell*)mat->data;
653a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
66606d414cSSatish Balay   ierr = PetscFree(shell);CHKERRQ(ierr);
673a40ed3dSBarry Smith   PetscFunctionReturn(0);
68e51e0e81SBarry Smith }
69e51e0e81SBarry Smith 
70711e205bSSatish Balay #undef __FUNCT__
71711e205bSSatish Balay #define __FUNCT__ "MatGetOwnershipRange_Shell"
728f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat,int *rstart,int *rend)
73b951964fSBarry Smith {
744c49b128SBarry Smith   int ierr,tmp;
75ca161407SBarry Smith 
76ca161407SBarry Smith   PetscFunctionBegin;
774c49b128SBarry Smith   ierr = MPI_Scan(&mat->m,&tmp,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr);
784c49b128SBarry Smith   if (rstart) *rstart = tmp - mat->m;
794c49b128SBarry Smith   if (rend)   *rend   = tmp;
803a40ed3dSBarry Smith   PetscFunctionReturn(0);
81b951964fSBarry Smith }
82*ef66eb69SBarry Smith 
83*ef66eb69SBarry Smith #undef __FUNCT__
84*ef66eb69SBarry Smith #define __FUNCT__ "MatMult_Shell"
85*ef66eb69SBarry Smith int MatMult_Shell(Mat A,Vec x,Vec y)
86*ef66eb69SBarry Smith {
87*ef66eb69SBarry Smith   Mat_Shell   *shell = (Mat_Shell*)A->data;
88*ef66eb69SBarry Smith   int         ierr;
89*ef66eb69SBarry Smith 
90*ef66eb69SBarry Smith   PetscFunctionBegin;
91*ef66eb69SBarry Smith   ierr = (*shell->mult)(A,x,y);CHKERRQ(ierr);
92*ef66eb69SBarry Smith   if (shell->shift && shell->scale) {
93*ef66eb69SBarry Smith     ierr = VecAXPBY(&shell->vshift,&shell->vscale,x,y);CHKERRQ(ierr);
94*ef66eb69SBarry Smith   } else if (shell->scale) {
95*ef66eb69SBarry Smith     ierr = VecScale(&shell->vscale,y);CHKERRQ(ierr);
96*ef66eb69SBarry Smith   } else {
97*ef66eb69SBarry Smith     ierr = VecAXPY(&shell->vshift,x,y);CHKERRQ(ierr);
98*ef66eb69SBarry Smith   }
99*ef66eb69SBarry Smith   PetscFunctionReturn(0);
100*ef66eb69SBarry Smith }
101*ef66eb69SBarry Smith 
102*ef66eb69SBarry Smith #undef __FUNCT__
103*ef66eb69SBarry Smith #define __FUNCT__ "MatShift_Shell"
104*ef66eb69SBarry Smith int MatShift_Shell(PetscScalar *a,Mat Y)
105*ef66eb69SBarry Smith {
106*ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
107*ef66eb69SBarry Smith   PetscFunctionBegin;
108*ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
109*ef66eb69SBarry Smith     shell->vshift += *a;
110*ef66eb69SBarry Smith   } else {
111*ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
112*ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
113*ef66eb69SBarry Smith     shell->vshift = *a;
114*ef66eb69SBarry Smith   }
115*ef66eb69SBarry Smith   shell->shift  =  PETSC_TRUE;
116*ef66eb69SBarry Smith   PetscFunctionReturn(0);
117*ef66eb69SBarry Smith }
118*ef66eb69SBarry Smith 
119*ef66eb69SBarry Smith #undef __FUNCT__
120*ef66eb69SBarry Smith #define __FUNCT__ "MatScale_Shell"
121*ef66eb69SBarry Smith int MatScale_Shell(PetscScalar *a,Mat Y)
122*ef66eb69SBarry Smith {
123*ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
124*ef66eb69SBarry Smith   PetscFunctionBegin;
125*ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
126*ef66eb69SBarry Smith     shell->vscale *= *a;
127*ef66eb69SBarry Smith   } else {
128*ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
129*ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
130*ef66eb69SBarry Smith     shell->vscale = *a;
131*ef66eb69SBarry Smith   }
132*ef66eb69SBarry Smith   shell->scale  =  PETSC_TRUE;
133*ef66eb69SBarry Smith   PetscFunctionReturn(0);
134*ef66eb69SBarry Smith }
135*ef66eb69SBarry Smith 
136*ef66eb69SBarry Smith #undef __FUNCT__
137*ef66eb69SBarry Smith #define __FUNCT__ "MatAssemblyEnd_Shell"
138*ef66eb69SBarry Smith int MatAssemblyEnd_Shell(Mat Y,MatAssemblyType t)
139*ef66eb69SBarry Smith {
140*ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
141*ef66eb69SBarry Smith 
142*ef66eb69SBarry Smith   PetscFunctionBegin;
143*ef66eb69SBarry Smith   if ((shell->shift || shell->scale) && t == MAT_FINAL_ASSEMBLY) {
144*ef66eb69SBarry Smith     shell->scale  = PETSC_FALSE;
145*ef66eb69SBarry Smith     shell->shift  = PETSC_FALSE;
146*ef66eb69SBarry Smith     shell->vshift = 0.0;
147*ef66eb69SBarry Smith     shell->vscale = 1.0;
148*ef66eb69SBarry Smith     Y->ops->mult  = shell->mult;
149*ef66eb69SBarry Smith   }
150*ef66eb69SBarry Smith   PetscFunctionReturn(0);
151*ef66eb69SBarry Smith }
152*ef66eb69SBarry Smith 
153273d9f13SBarry Smith extern int MatConvert_Shell(Mat,MatType,Mat*);
154b951964fSBarry Smith 
15509dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
15620563c6bSBarry Smith        0,
15720563c6bSBarry Smith        0,
15820563c6bSBarry Smith        0,
15920563c6bSBarry Smith        0,
160b951964fSBarry Smith        0,
161b951964fSBarry Smith        0,
162b951964fSBarry Smith        0,
163b951964fSBarry Smith        0,
164b951964fSBarry Smith        0,
165b951964fSBarry Smith        0,
166b951964fSBarry Smith        0,
167b951964fSBarry Smith        0,
168b951964fSBarry Smith        0,
169b951964fSBarry Smith        0,
170b951964fSBarry Smith        0,
171b951964fSBarry Smith        0,
172b951964fSBarry Smith        0,
173b951964fSBarry Smith        0,
174b951964fSBarry Smith        0,
175b951964fSBarry Smith        0,
176*ef66eb69SBarry Smith        MatAssemblyEnd_Shell,
177b951964fSBarry Smith        0,
178b951964fSBarry Smith        0,
179b951964fSBarry Smith        0,
180b951964fSBarry Smith        0,
181b951964fSBarry Smith        0,
182b951964fSBarry Smith        0,
183b951964fSBarry Smith        0,
184b951964fSBarry Smith        0,
185273d9f13SBarry Smith        0,
186b951964fSBarry Smith        MatGetOwnershipRange_Shell,
187b951964fSBarry Smith        0,
188b951964fSBarry Smith        0,
189b951964fSBarry Smith        0,
190b951964fSBarry Smith        0,
19109dc0095SBarry Smith        0,
19209dc0095SBarry Smith        0,
19309dc0095SBarry Smith        0,
19409dc0095SBarry Smith        0,
19509dc0095SBarry Smith        0,
19609dc0095SBarry Smith        0,
19709dc0095SBarry Smith        0,
19809dc0095SBarry Smith        0,
19909dc0095SBarry Smith        0,
20009dc0095SBarry Smith        0,
20109dc0095SBarry Smith        0,
20209dc0095SBarry Smith        0,
203*ef66eb69SBarry Smith        MatScale_Shell,
204*ef66eb69SBarry Smith        MatShift_Shell,
20509dc0095SBarry Smith        0,
20609dc0095SBarry Smith        0,
20709dc0095SBarry Smith        0,
20809dc0095SBarry Smith        0,
20909dc0095SBarry Smith        0,
21009dc0095SBarry Smith        0,
21109dc0095SBarry Smith        0,
21209dc0095SBarry Smith        0,
21309dc0095SBarry Smith        0,
21409dc0095SBarry Smith        0,
21509dc0095SBarry Smith        0,
21609dc0095SBarry Smith        0,
217273d9f13SBarry Smith        0,
218b9b97703SBarry Smith        MatDestroy_Shell,
21909dc0095SBarry Smith        0,
2208a124369SBarry Smith        MatGetPetscMaps_Petsc,
221273d9f13SBarry Smith        0,
222273d9f13SBarry Smith        0,
223273d9f13SBarry Smith        0,
224273d9f13SBarry Smith        0,
225273d9f13SBarry Smith        0,
226273d9f13SBarry Smith        0,
227273d9f13SBarry Smith        0,
228273d9f13SBarry Smith        MatConvert_Shell};
229273d9f13SBarry Smith 
230273d9f13SBarry Smith EXTERN_C_BEGIN
231711e205bSSatish Balay #undef __FUNCT__
232711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
233273d9f13SBarry Smith int MatCreate_Shell(Mat A)
234273d9f13SBarry Smith {
235273d9f13SBarry Smith   Mat_Shell *b;
236273d9f13SBarry Smith   int       ierr;
237273d9f13SBarry Smith 
238273d9f13SBarry Smith   PetscFunctionBegin;
239273d9f13SBarry Smith   ierr            = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
240273d9f13SBarry Smith 
241b0a32e0cSBarry Smith   ierr = PetscNew(Mat_Shell,&b);CHKERRQ(ierr);
242b0a32e0cSBarry Smith   PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
243273d9f13SBarry Smith   ierr    = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr);
244273d9f13SBarry Smith   A->data = (void*)b;
245273d9f13SBarry Smith 
246273d9f13SBarry Smith   if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) {
247273d9f13SBarry Smith     SETERRQ(1,"Must give local row and column count for matrix");
248273d9f13SBarry Smith   }
249273d9f13SBarry Smith 
250273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->m,&A->M);CHKERRQ(ierr);
251273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->n,&A->N);CHKERRQ(ierr);
252273d9f13SBarry Smith 
2538a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->m,A->M,&A->rmap);CHKERRQ(ierr);
2548a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->n,A->N,&A->cmap);CHKERRQ(ierr);
255273d9f13SBarry Smith 
256273d9f13SBarry Smith   b->ctx          = 0;
257*ef66eb69SBarry Smith   b->scale        = PETSC_FALSE;
258*ef66eb69SBarry Smith   b->shift        = PETSC_FALSE;
259*ef66eb69SBarry Smith   b->vshift       = 0.0;
260*ef66eb69SBarry Smith   b->vscale       = 1.0;
261*ef66eb69SBarry Smith   b->mult         = 0;
262273d9f13SBarry Smith   A->assembled    = PETSC_TRUE;
263273d9f13SBarry Smith   A->preallocated = PETSC_TRUE;
264273d9f13SBarry Smith   PetscFunctionReturn(0);
265273d9f13SBarry Smith }
266273d9f13SBarry Smith EXTERN_C_END
267e51e0e81SBarry Smith 
268711e205bSSatish Balay #undef __FUNCT__
269711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
2704b828684SBarry Smith /*@C
271052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
272ff756334SLois Curfman McInnes    private data storage format.
273e51e0e81SBarry Smith 
274c7fcc2eaSBarry Smith   Collective on MPI_Comm
275c7fcc2eaSBarry Smith 
276e51e0e81SBarry Smith    Input Parameters:
277c7fcc2eaSBarry Smith +  comm - MPI communicator
278c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
279c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
280c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
281c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
282c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
283e51e0e81SBarry Smith 
284ff756334SLois Curfman McInnes    Output Parameter:
28544cd7ae7SLois Curfman McInnes .  A - the matrix
286e51e0e81SBarry Smith 
287ff2fd236SBarry Smith    Level: advanced
288ff2fd236SBarry Smith 
289f39d1f56SLois Curfman McInnes   Usage:
2907b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
291f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
29237bd1cefSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)())mult);
293f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
294f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
295f39d1f56SLois Curfman McInnes 
296ff756334SLois Curfman McInnes    Notes:
297ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
298ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
299ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
300e51e0e81SBarry Smith 
301f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
302f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
303645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
304645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
305645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
306645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
307645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
308645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
309645985a0SLois Curfman McInnes    For example,
310f39d1f56SLois Curfman McInnes 
311f39d1f56SLois Curfman McInnes $
312f39d1f56SLois Curfman McInnes $     Vec x, y
3137b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
314645985a0SLois Curfman McInnes $     Mat A
315f39d1f56SLois Curfman McInnes $
316c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
317c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
318f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
319c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
320c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
32137bd1cefSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)())mult);
322645985a0SLois Curfman McInnes $     MatMult(A,x,y);
323645985a0SLois Curfman McInnes $     MatDestroy(A);
324f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
325645985a0SLois Curfman McInnes $
326e51e0e81SBarry Smith 
3270b627109SLois Curfman McInnes .keywords: matrix, shell, create
3280b627109SLois Curfman McInnes 
3293a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
330e51e0e81SBarry Smith @*/
331f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
332e51e0e81SBarry Smith {
333c7fcc2eaSBarry Smith   int       ierr;
334ed3cc1f0SBarry Smith 
3353a40ed3dSBarry Smith   PetscFunctionBegin;
336273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,M,N,A);CHKERRQ(ierr);
337273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
338273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
339273d9f13SBarry Smith   PetscFunctionReturn(0);
340c7fcc2eaSBarry Smith }
341c7fcc2eaSBarry Smith 
342711e205bSSatish Balay #undef __FUNCT__
343711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
344273d9f13SBarry Smith /*@C
345273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
346c7fcc2eaSBarry Smith 
347273d9f13SBarry Smith    Collective on Mat
348c7fcc2eaSBarry Smith 
349273d9f13SBarry Smith     Input Parameters:
350273d9f13SBarry Smith +   mat - the shell matrix
351273d9f13SBarry Smith -   ctx - the context
352273d9f13SBarry Smith 
353273d9f13SBarry Smith    Level: advanced
354273d9f13SBarry Smith 
355273d9f13SBarry Smith 
356273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
357273d9f13SBarry Smith @*/
358273d9f13SBarry Smith int MatShellSetContext(Mat mat,void *ctx)
359273d9f13SBarry Smith {
360273d9f13SBarry Smith   Mat_Shell  *shell = (Mat_Shell*)mat->data;
361273d9f13SBarry Smith   int        ierr;
362273d9f13SBarry Smith   PetscTruth flg;
363273d9f13SBarry Smith 
364273d9f13SBarry Smith   PetscFunctionBegin;
365273d9f13SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
366273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
367273d9f13SBarry Smith   if (flg) {
368273d9f13SBarry Smith     shell->ctx = ctx;
369273d9f13SBarry Smith   }
3703a40ed3dSBarry Smith   PetscFunctionReturn(0);
371e51e0e81SBarry Smith }
372e51e0e81SBarry Smith 
373711e205bSSatish Balay #undef __FUNCT__
374711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
375c16cb8f2SBarry Smith /*@C
3763a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
3773a3eedf2SBarry Smith                            a shell matrix.
378e51e0e81SBarry Smith 
379fee21e36SBarry Smith    Collective on Mat
380fee21e36SBarry Smith 
381c7fcc2eaSBarry Smith     Input Parameters:
382c7fcc2eaSBarry Smith +   mat - the shell matrix
383c7fcc2eaSBarry Smith .   op - the name of the operation
384c7fcc2eaSBarry Smith -   f - the function that provides the operation.
385c7fcc2eaSBarry Smith 
38615091d37SBarry Smith    Level: advanced
38715091d37SBarry Smith 
388fae171e0SBarry Smith     Usage:
389a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
390f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
39137bd1cefSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)())usermult);
3920b627109SLois Curfman McInnes 
393a62d957aSLois Curfman McInnes     Notes:
394e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
3951c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
396a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
3971c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
398a62d957aSLois Curfman McInnes 
399a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
400deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
401deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
402deebb3c3SLois Curfman McInnes     routines, e.g.,
403a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
404a62d957aSLois Curfman McInnes 
405a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
406a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
407a62d957aSLois Curfman McInnes     set by MatCreateShell().
408a62d957aSLois Curfman McInnes 
409a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
410a62d957aSLois Curfman McInnes 
411d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
412e51e0e81SBarry Smith @*/
41337bd1cefSSatish Balay int MatShellSetOperation(Mat mat,MatOperation op,void (*f)())
414e51e0e81SBarry Smith {
415273d9f13SBarry Smith   int        ierr;
416273d9f13SBarry Smith   PetscTruth flg;
417273d9f13SBarry Smith 
4183a40ed3dSBarry Smith   PetscFunctionBegin;
41977c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
4201c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
421273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
422273d9f13SBarry Smith     if (flg) {
423a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
4243a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
4250c0c84c0SBarry Smith     } else mat->ops->destroy            = (int (*)(Mat)) f;
426a62d957aSLois Curfman McInnes   }
427b0a32e0cSBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (int (*)(Mat,PetscViewer)) f;
42837bd1cefSSatish Balay   else                       (((void(**)())mat->ops)[op]) = f;
429a62d957aSLois Curfman McInnes 
4303a40ed3dSBarry Smith   PetscFunctionReturn(0);
431e51e0e81SBarry Smith }
432f0479e8cSBarry Smith 
433711e205bSSatish Balay #undef __FUNCT__
434711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
435d4bb536fSBarry Smith /*@C
436d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
437d4bb536fSBarry Smith 
438c7fcc2eaSBarry Smith     Not Collective
439c7fcc2eaSBarry Smith 
440d4bb536fSBarry Smith     Input Parameters:
441c7fcc2eaSBarry Smith +   mat - the shell matrix
442c7fcc2eaSBarry Smith -   op - the name of the operation
443d4bb536fSBarry Smith 
444d4bb536fSBarry Smith     Output Parameter:
445d4bb536fSBarry Smith .   f - the function that provides the operation.
446d4bb536fSBarry Smith 
44715091d37SBarry Smith     Level: advanced
44815091d37SBarry Smith 
449d4bb536fSBarry Smith     Notes:
450e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
451d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
452d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
453d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
454d4bb536fSBarry Smith 
455d4bb536fSBarry Smith     All user-provided functions have the same calling
456d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
457d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
458d4bb536fSBarry Smith     routines, e.g.,
459d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
460d4bb536fSBarry Smith 
461d4bb536fSBarry Smith     Within each user-defined routine, the user should call
462d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
463d4bb536fSBarry Smith     set by MatCreateShell().
464d4bb536fSBarry Smith 
465d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
466d4bb536fSBarry Smith 
467d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
468d4bb536fSBarry Smith @*/
46937bd1cefSSatish Balay int MatShellGetOperation(Mat mat,MatOperation op,void(**f)())
470d4bb536fSBarry Smith {
471273d9f13SBarry Smith   int        ierr;
472273d9f13SBarry Smith   PetscTruth flg;
473273d9f13SBarry Smith 
4743a40ed3dSBarry Smith   PetscFunctionBegin;
475d4bb536fSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
476d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
477273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
478273d9f13SBarry Smith     if (flg) {
479d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
48037bd1cefSSatish Balay       *f = (void(*)())shell->destroy;
481c7fcc2eaSBarry Smith     } else {
48237bd1cefSSatish Balay       *f = (void(*)())mat->ops->destroy;
483d4bb536fSBarry Smith     }
484c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
48537bd1cefSSatish Balay     *f = (void(*)())mat->ops->view;
486c7fcc2eaSBarry Smith   } else {
48737bd1cefSSatish Balay     *f = (((void(**)())mat->ops)[op]);
488d4bb536fSBarry Smith   }
489d4bb536fSBarry Smith 
4903a40ed3dSBarry Smith   PetscFunctionReturn(0);
491d4bb536fSBarry Smith }
492d4bb536fSBarry Smith 
493