xref: /petsc/src/mat/impls/shell/shell.c (revision be1d678a52e6eff2808b2fa31ae986cdbf03c9fe)
1*be1d678aSKris Buschelman #define PETSCMAT_DLL
2*be1d678aSKris Buschelman 
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*/
103c94ec11SBarry Smith #include "vecimpl.h"
11e51e0e81SBarry Smith 
1220563c6bSBarry Smith typedef struct {
136849ba73SBarry Smith   PetscErrorCode (*destroy)(Mat);
146849ba73SBarry Smith   PetscErrorCode (*mult)(Mat,Vec,Vec);
15ef66eb69SBarry Smith   PetscTruth     scale,shift;
16ef66eb69SBarry Smith   PetscScalar    vscale,vshift;
1720563c6bSBarry Smith   void           *ctx;
1888cf3e7dSBarry Smith } Mat_Shell;
19e51e0e81SBarry Smith 
20711e205bSSatish Balay #undef __FUNCT__
21711e205bSSatish Balay #define __FUNCT__ "MatShellGetContext"
22b4fd4287SBarry Smith /*@
23a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
24b4fd4287SBarry Smith 
25c7fcc2eaSBarry Smith     Not Collective
26c7fcc2eaSBarry Smith 
27b4fd4287SBarry Smith     Input Parameter:
28b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
29b4fd4287SBarry Smith 
30b4fd4287SBarry Smith     Output Parameter:
31b4fd4287SBarry Smith .   ctx - the user provided context
32b4fd4287SBarry Smith 
3315091d37SBarry Smith     Level: advanced
3415091d37SBarry Smith 
35a62d957aSLois Curfman McInnes     Notes:
36a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
37a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
38a62d957aSLois Curfman McInnes 
39a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
40a62d957aSLois Curfman McInnes 
41ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellSetOperation(), MatShellSetContext()
42b4fd4287SBarry Smith @*/
43*be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellGetContext(Mat mat,void **ctx)
44b4fd4287SBarry Smith {
45dfbe8321SBarry Smith   PetscErrorCode ierr;
46273d9f13SBarry Smith   PetscTruth     flg;
47273d9f13SBarry Smith 
483a40ed3dSBarry Smith   PetscFunctionBegin;
494482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
504482741eSBarry Smith   PetscValidPointer(ctx,2);
51273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
52273d9f13SBarry Smith   if (!flg) *ctx = 0;
53b4fd4287SBarry Smith   else      *ctx = ((Mat_Shell*)(mat->data))->ctx;
543a40ed3dSBarry Smith   PetscFunctionReturn(0);
55b4fd4287SBarry Smith }
56b4fd4287SBarry Smith 
57711e205bSSatish Balay #undef __FUNCT__
58711e205bSSatish Balay #define __FUNCT__ "MatDestroy_Shell"
59dfbe8321SBarry Smith PetscErrorCode MatDestroy_Shell(Mat mat)
60e51e0e81SBarry Smith {
61dfbe8321SBarry Smith   PetscErrorCode ierr;
6288cf3e7dSBarry Smith   Mat_Shell      *shell;
63ed3cc1f0SBarry Smith 
643a40ed3dSBarry Smith   PetscFunctionBegin;
6588cf3e7dSBarry Smith   shell = (Mat_Shell*)mat->data;
663a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
67606d414cSSatish Balay   ierr = PetscFree(shell);CHKERRQ(ierr);
683a40ed3dSBarry Smith   PetscFunctionReturn(0);
69e51e0e81SBarry Smith }
70e51e0e81SBarry Smith 
71711e205bSSatish Balay #undef __FUNCT__
72ef66eb69SBarry Smith #define __FUNCT__ "MatMult_Shell"
73dfbe8321SBarry Smith PetscErrorCode MatMult_Shell(Mat A,Vec x,Vec y)
74ef66eb69SBarry Smith {
75ef66eb69SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)A->data;
76dfbe8321SBarry Smith   PetscErrorCode ierr;
77ef66eb69SBarry Smith 
78ef66eb69SBarry Smith   PetscFunctionBegin;
79ef66eb69SBarry Smith   ierr = (*shell->mult)(A,x,y);CHKERRQ(ierr);
80ef66eb69SBarry Smith   if (shell->shift && shell->scale) {
81ef66eb69SBarry Smith     ierr = VecAXPBY(&shell->vshift,&shell->vscale,x,y);CHKERRQ(ierr);
82ef66eb69SBarry Smith   } else if (shell->scale) {
83ef66eb69SBarry Smith     ierr = VecScale(&shell->vscale,y);CHKERRQ(ierr);
84ef66eb69SBarry Smith   } else {
85ef66eb69SBarry Smith     ierr = VecAXPY(&shell->vshift,x,y);CHKERRQ(ierr);
86ef66eb69SBarry Smith   }
87ef66eb69SBarry Smith   PetscFunctionReturn(0);
88ef66eb69SBarry Smith }
89ef66eb69SBarry Smith 
90ef66eb69SBarry Smith #undef __FUNCT__
91ef66eb69SBarry Smith #define __FUNCT__ "MatShift_Shell"
92dfbe8321SBarry Smith PetscErrorCode MatShift_Shell(const PetscScalar *a,Mat Y)
93ef66eb69SBarry Smith {
94ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
95b24ad042SBarry Smith 
96ef66eb69SBarry Smith   PetscFunctionBegin;
97ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
98ef66eb69SBarry Smith     shell->vshift += *a;
99ef66eb69SBarry Smith   } else {
100ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
101ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
102ef66eb69SBarry Smith     shell->vshift = *a;
103ef66eb69SBarry Smith   }
104ef66eb69SBarry Smith   shell->shift  =  PETSC_TRUE;
105ef66eb69SBarry Smith   PetscFunctionReturn(0);
106ef66eb69SBarry Smith }
107ef66eb69SBarry Smith 
108ef66eb69SBarry Smith #undef __FUNCT__
109ef66eb69SBarry Smith #define __FUNCT__ "MatScale_Shell"
110dfbe8321SBarry Smith PetscErrorCode MatScale_Shell(const PetscScalar *a,Mat Y)
111ef66eb69SBarry Smith {
112ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
113b24ad042SBarry Smith 
114ef66eb69SBarry Smith   PetscFunctionBegin;
115ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
116ef66eb69SBarry Smith     shell->vscale *= *a;
117ef66eb69SBarry Smith   } else {
118ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
119ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
120ef66eb69SBarry Smith     shell->vscale = *a;
121ef66eb69SBarry Smith   }
122ef66eb69SBarry Smith   shell->scale  =  PETSC_TRUE;
123ef66eb69SBarry Smith   PetscFunctionReturn(0);
124ef66eb69SBarry Smith }
125ef66eb69SBarry Smith 
126ef66eb69SBarry Smith #undef __FUNCT__
127ef66eb69SBarry Smith #define __FUNCT__ "MatAssemblyEnd_Shell"
128dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_Shell(Mat Y,MatAssemblyType t)
129ef66eb69SBarry Smith {
130ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
131ef66eb69SBarry Smith 
132ef66eb69SBarry Smith   PetscFunctionBegin;
133ef66eb69SBarry Smith   if ((shell->shift || shell->scale) && t == MAT_FINAL_ASSEMBLY) {
134ef66eb69SBarry Smith     shell->scale  = PETSC_FALSE;
135ef66eb69SBarry Smith     shell->shift  = PETSC_FALSE;
136ef66eb69SBarry Smith     shell->vshift = 0.0;
137ef66eb69SBarry Smith     shell->vscale = 1.0;
138ef66eb69SBarry Smith     Y->ops->mult  = shell->mult;
139ef66eb69SBarry Smith   }
140ef66eb69SBarry Smith   PetscFunctionReturn(0);
141ef66eb69SBarry Smith }
142ef66eb69SBarry Smith 
143ceb03754SKris Buschelman EXTERN PetscErrorCode MatConvert_Shell(Mat,const MatType,MatReuse,Mat*);
144b951964fSBarry Smith 
145521d7252SBarry Smith #undef __FUNCT__
146521d7252SBarry Smith #define __FUNCT__ "MatSetBlockSize_Shell"
147521d7252SBarry Smith PetscErrorCode MatSetBlockSize_Shell(Mat A,PetscInt bs)
148521d7252SBarry Smith {
149521d7252SBarry Smith   PetscFunctionBegin;
150521d7252SBarry Smith   PetscFunctionReturn(0);
151521d7252SBarry Smith }
152521d7252SBarry Smith 
15309dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
15420563c6bSBarry Smith        0,
15520563c6bSBarry Smith        0,
15620563c6bSBarry Smith        0,
15797304618SKris Buschelman /* 4*/ 0,
15820563c6bSBarry Smith        0,
159b951964fSBarry Smith        0,
160b951964fSBarry Smith        0,
161b951964fSBarry Smith        0,
162b951964fSBarry Smith        0,
16397304618SKris Buschelman /*10*/ 0,
164b951964fSBarry Smith        0,
165b951964fSBarry Smith        0,
166b951964fSBarry Smith        0,
167b951964fSBarry Smith        0,
16897304618SKris Buschelman /*15*/ 0,
169b951964fSBarry Smith        0,
170b951964fSBarry Smith        0,
171b951964fSBarry Smith        0,
172b951964fSBarry Smith        0,
17397304618SKris Buschelman /*20*/ 0,
174ef66eb69SBarry Smith        MatAssemblyEnd_Shell,
175b951964fSBarry Smith        0,
176b951964fSBarry Smith        0,
177b951964fSBarry Smith        0,
17897304618SKris Buschelman /*25*/ 0,
179b951964fSBarry Smith        0,
180b951964fSBarry Smith        0,
181b951964fSBarry Smith        0,
182b951964fSBarry Smith        0,
18397304618SKris Buschelman /*30*/ 0,
184b951964fSBarry Smith        0,
185273d9f13SBarry Smith        0,
186b951964fSBarry Smith        0,
187b951964fSBarry Smith        0,
18897304618SKris Buschelman /*35*/ 0,
189b951964fSBarry Smith        0,
190b951964fSBarry Smith        0,
19109dc0095SBarry Smith        0,
19209dc0095SBarry Smith        0,
19397304618SKris Buschelman /*40*/ 0,
19409dc0095SBarry Smith        0,
19509dc0095SBarry Smith        0,
19609dc0095SBarry Smith        0,
19709dc0095SBarry Smith        0,
19897304618SKris Buschelman /*45*/ 0,
199ef66eb69SBarry Smith        MatScale_Shell,
200ef66eb69SBarry Smith        MatShift_Shell,
20109dc0095SBarry Smith        0,
20209dc0095SBarry Smith        0,
203521d7252SBarry Smith /*50*/ MatSetBlockSize_Shell,
20409dc0095SBarry Smith        0,
20509dc0095SBarry Smith        0,
20609dc0095SBarry Smith        0,
20709dc0095SBarry Smith        0,
20897304618SKris Buschelman /*55*/ 0,
20909dc0095SBarry Smith        0,
21009dc0095SBarry Smith        0,
21109dc0095SBarry Smith        0,
21209dc0095SBarry Smith        0,
21397304618SKris Buschelman /*60*/ 0,
214b9b97703SBarry Smith        MatDestroy_Shell,
21509dc0095SBarry Smith        0,
2168a124369SBarry Smith        MatGetPetscMaps_Petsc,
217273d9f13SBarry Smith        0,
21897304618SKris Buschelman /*65*/ 0,
219273d9f13SBarry Smith        0,
220273d9f13SBarry Smith        0,
221273d9f13SBarry Smith        0,
222273d9f13SBarry Smith        0,
22397304618SKris Buschelman /*70*/ 0,
22497304618SKris Buschelman        MatConvert_Shell,
225273d9f13SBarry Smith        0,
226273d9f13SBarry Smith        0,
22797304618SKris Buschelman        0,
22897304618SKris Buschelman /*75*/ 0,
22997304618SKris Buschelman        0,
23097304618SKris Buschelman        0,
23197304618SKris Buschelman        0,
23297304618SKris Buschelman        0,
23397304618SKris Buschelman /*80*/ 0,
23497304618SKris Buschelman        0,
23597304618SKris Buschelman        0,
23697304618SKris Buschelman        0,
237865e5f61SKris Buschelman        0,
238865e5f61SKris Buschelman /*85*/ 0,
239865e5f61SKris Buschelman        0,
240865e5f61SKris Buschelman        0,
241865e5f61SKris Buschelman        0,
242865e5f61SKris Buschelman        0,
243865e5f61SKris Buschelman /*90*/ 0,
244865e5f61SKris Buschelman        0,
245865e5f61SKris Buschelman        0,
246865e5f61SKris Buschelman        0,
247865e5f61SKris Buschelman        0,
248865e5f61SKris Buschelman /*95*/ 0,
249865e5f61SKris Buschelman        0,
250865e5f61SKris Buschelman        0,
251865e5f61SKris Buschelman        0};
252273d9f13SBarry Smith 
2530bad9183SKris Buschelman /*MC
254fafad747SKris Buschelman    MATSHELL - MATSHELL = "shell" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
2550bad9183SKris Buschelman 
2560bad9183SKris Buschelman   Level: advanced
2570bad9183SKris Buschelman 
2580bad9183SKris Buschelman .seealso: MatCreateShell
2590bad9183SKris Buschelman M*/
2600bad9183SKris Buschelman 
261273d9f13SBarry Smith EXTERN_C_BEGIN
262711e205bSSatish Balay #undef __FUNCT__
263711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
264*be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_Shell(Mat A)
265273d9f13SBarry Smith {
266273d9f13SBarry Smith   Mat_Shell      *b;
267dfbe8321SBarry Smith   PetscErrorCode ierr;
268273d9f13SBarry Smith 
269273d9f13SBarry Smith   PetscFunctionBegin;
270273d9f13SBarry Smith   ierr            = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
271273d9f13SBarry Smith 
272b0a32e0cSBarry Smith   ierr = PetscNew(Mat_Shell,&b);CHKERRQ(ierr);
27352e6d16bSBarry Smith   ierr = PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell));CHKERRQ(ierr);
274273d9f13SBarry Smith   A->data = (void*)b;
275273d9f13SBarry Smith 
276273d9f13SBarry Smith   if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) {
277e005ede5SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Must give local row and column count for matrix");
278273d9f13SBarry Smith   }
279273d9f13SBarry Smith 
280273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->m,&A->M);CHKERRQ(ierr);
281273d9f13SBarry Smith   ierr = PetscSplitOwnership(A->comm,&A->n,&A->N);CHKERRQ(ierr);
282273d9f13SBarry Smith 
2838a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->m,A->M,&A->rmap);CHKERRQ(ierr);
2848a124369SBarry Smith   ierr = PetscMapCreateMPI(A->comm,A->n,A->N,&A->cmap);CHKERRQ(ierr);
285273d9f13SBarry Smith 
286273d9f13SBarry Smith   b->ctx          = 0;
287ef66eb69SBarry Smith   b->scale        = PETSC_FALSE;
288ef66eb69SBarry Smith   b->shift        = PETSC_FALSE;
289ef66eb69SBarry Smith   b->vshift       = 0.0;
290ef66eb69SBarry Smith   b->vscale       = 1.0;
291ef66eb69SBarry Smith   b->mult         = 0;
292273d9f13SBarry Smith   A->assembled    = PETSC_TRUE;
293273d9f13SBarry Smith   A->preallocated = PETSC_TRUE;
294273d9f13SBarry Smith   PetscFunctionReturn(0);
295273d9f13SBarry Smith }
296273d9f13SBarry Smith EXTERN_C_END
297e51e0e81SBarry Smith 
298711e205bSSatish Balay #undef __FUNCT__
299711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
3004b828684SBarry Smith /*@C
301052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
302ff756334SLois Curfman McInnes    private data storage format.
303e51e0e81SBarry Smith 
304c7fcc2eaSBarry Smith   Collective on MPI_Comm
305c7fcc2eaSBarry Smith 
306e51e0e81SBarry Smith    Input Parameters:
307c7fcc2eaSBarry Smith +  comm - MPI communicator
308c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
309c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
310c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
311c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
312c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
313e51e0e81SBarry Smith 
314ff756334SLois Curfman McInnes    Output Parameter:
31544cd7ae7SLois Curfman McInnes .  A - the matrix
316e51e0e81SBarry Smith 
317ff2fd236SBarry Smith    Level: advanced
318ff2fd236SBarry Smith 
319f39d1f56SLois Curfman McInnes   Usage:
3207b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
321f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
322c134de8dSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
323f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
324f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
325f39d1f56SLois Curfman McInnes 
326ff756334SLois Curfman McInnes    Notes:
327ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
328ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
329ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
330e51e0e81SBarry Smith 
331f38a8d56SBarry Smith    Fortran Notes: The context can only be an integer or a PetscObject
332f38a8d56SBarry Smith       unfortunately it cannot be a Fortran array or derived type.
333f38a8d56SBarry Smith 
334f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
335f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
336645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
337645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
338645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
339645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
340645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
341645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
342645985a0SLois Curfman McInnes    For example,
343f39d1f56SLois Curfman McInnes 
344f39d1f56SLois Curfman McInnes $
345f39d1f56SLois Curfman McInnes $     Vec x, y
3467b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
347645985a0SLois Curfman McInnes $     Mat A
348f39d1f56SLois Curfman McInnes $
349c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
350c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
351f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
352c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
353c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
354c134de8dSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
355645985a0SLois Curfman McInnes $     MatMult(A,x,y);
356645985a0SLois Curfman McInnes $     MatDestroy(A);
357f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
358645985a0SLois Curfman McInnes $
359e51e0e81SBarry Smith 
3600b627109SLois Curfman McInnes .keywords: matrix, shell, create
3610b627109SLois Curfman McInnes 
362ab50ec6bSBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext(), MatShellSetContext()
363e51e0e81SBarry Smith @*/
364*be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreateShell(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,void *ctx,Mat *A)
365e51e0e81SBarry Smith {
366dfbe8321SBarry Smith   PetscErrorCode ierr;
367ed3cc1f0SBarry Smith 
3683a40ed3dSBarry Smith   PetscFunctionBegin;
369273d9f13SBarry Smith   ierr = MatCreate(comm,m,n,M,N,A);CHKERRQ(ierr);
370273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
371273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
372273d9f13SBarry Smith   PetscFunctionReturn(0);
373c7fcc2eaSBarry Smith }
374c7fcc2eaSBarry Smith 
375711e205bSSatish Balay #undef __FUNCT__
376711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
377273d9f13SBarry Smith /*@C
378273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
379c7fcc2eaSBarry Smith 
380273d9f13SBarry Smith    Collective on Mat
381c7fcc2eaSBarry Smith 
382273d9f13SBarry Smith     Input Parameters:
383273d9f13SBarry Smith +   mat - the shell matrix
384273d9f13SBarry Smith -   ctx - the context
385273d9f13SBarry Smith 
386273d9f13SBarry Smith    Level: advanced
387273d9f13SBarry Smith 
388f38a8d56SBarry Smith    Fortran Notes: The context can only be an integer or a PetscObject
389f38a8d56SBarry Smith       unfortunately it cannot be a Fortran array or derived type.
390273d9f13SBarry Smith 
391273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
392273d9f13SBarry Smith @*/
393*be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellSetContext(Mat mat,void *ctx)
394273d9f13SBarry Smith {
395273d9f13SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)mat->data;
396dfbe8321SBarry Smith   PetscErrorCode ierr;
397273d9f13SBarry Smith   PetscTruth     flg;
398273d9f13SBarry Smith 
399273d9f13SBarry Smith   PetscFunctionBegin;
4004482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
401273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
402273d9f13SBarry Smith   if (flg) {
403273d9f13SBarry Smith     shell->ctx = ctx;
404273d9f13SBarry Smith   }
4053a40ed3dSBarry Smith   PetscFunctionReturn(0);
406e51e0e81SBarry Smith }
407e51e0e81SBarry Smith 
408711e205bSSatish Balay #undef __FUNCT__
409711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
410c16cb8f2SBarry Smith /*@C
4113a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
4123a3eedf2SBarry Smith                            a shell matrix.
413e51e0e81SBarry Smith 
414fee21e36SBarry Smith    Collective on Mat
415fee21e36SBarry Smith 
416c7fcc2eaSBarry Smith     Input Parameters:
417c7fcc2eaSBarry Smith +   mat - the shell matrix
418c7fcc2eaSBarry Smith .   op - the name of the operation
419c7fcc2eaSBarry Smith -   f - the function that provides the operation.
420c7fcc2eaSBarry Smith 
42115091d37SBarry Smith    Level: advanced
42215091d37SBarry Smith 
423fae171e0SBarry Smith     Usage:
424a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
425f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
426c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
4270b627109SLois Curfman McInnes 
428a62d957aSLois Curfman McInnes     Notes:
429e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
4301c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
431a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
4321c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
433a62d957aSLois Curfman McInnes 
434a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
435deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
436deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
437deebb3c3SLois Curfman McInnes     routines, e.g.,
438a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
439a62d957aSLois Curfman McInnes 
440a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
441a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
442a62d957aSLois Curfman McInnes     set by MatCreateShell().
443a62d957aSLois Curfman McInnes 
444a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
445a62d957aSLois Curfman McInnes 
446ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellSetContext()
447e51e0e81SBarry Smith @*/
448*be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
449e51e0e81SBarry Smith {
450dfbe8321SBarry Smith   PetscErrorCode ierr;
451273d9f13SBarry Smith   PetscTruth     flg;
452273d9f13SBarry Smith 
4533a40ed3dSBarry Smith   PetscFunctionBegin;
4544482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
4551c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
456273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
457273d9f13SBarry Smith     if (flg) {
458a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
4596849ba73SBarry Smith        shell->destroy                 = (PetscErrorCode (*)(Mat)) f;
4606849ba73SBarry Smith     } else mat->ops->destroy          = (PetscErrorCode (*)(Mat)) f;
461a62d957aSLois Curfman McInnes   }
4626849ba73SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (PetscErrorCode (*)(Mat,PetscViewer)) f;
463c134de8dSSatish Balay   else                       (((void(**)(void))mat->ops)[op]) = f;
464a62d957aSLois Curfman McInnes 
4653a40ed3dSBarry Smith   PetscFunctionReturn(0);
466e51e0e81SBarry Smith }
467f0479e8cSBarry Smith 
468711e205bSSatish Balay #undef __FUNCT__
469711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
470d4bb536fSBarry Smith /*@C
471d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
472d4bb536fSBarry Smith 
473c7fcc2eaSBarry Smith     Not Collective
474c7fcc2eaSBarry Smith 
475d4bb536fSBarry Smith     Input Parameters:
476c7fcc2eaSBarry Smith +   mat - the shell matrix
477c7fcc2eaSBarry Smith -   op - the name of the operation
478d4bb536fSBarry Smith 
479d4bb536fSBarry Smith     Output Parameter:
480d4bb536fSBarry Smith .   f - the function that provides the operation.
481d4bb536fSBarry Smith 
48215091d37SBarry Smith     Level: advanced
48315091d37SBarry Smith 
484d4bb536fSBarry Smith     Notes:
485e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
486d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
487d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
488d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
489d4bb536fSBarry Smith 
490d4bb536fSBarry Smith     All user-provided functions have the same calling
491d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
492d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
493d4bb536fSBarry Smith     routines, e.g.,
494d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
495d4bb536fSBarry Smith 
496d4bb536fSBarry Smith     Within each user-defined routine, the user should call
497d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
498d4bb536fSBarry Smith     set by MatCreateShell().
499d4bb536fSBarry Smith 
500d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
501d4bb536fSBarry Smith 
502ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation(), MatShellSetContext()
503d4bb536fSBarry Smith @*/
504*be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
505d4bb536fSBarry Smith {
506dfbe8321SBarry Smith   PetscErrorCode ierr;
507273d9f13SBarry Smith   PetscTruth     flg;
508273d9f13SBarry Smith 
5093a40ed3dSBarry Smith   PetscFunctionBegin;
5104482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
511d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
512273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
513273d9f13SBarry Smith     if (flg) {
514d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
515c134de8dSSatish Balay       *f = (void(*)(void))shell->destroy;
516c7fcc2eaSBarry Smith     } else {
517c134de8dSSatish Balay       *f = (void(*)(void))mat->ops->destroy;
518d4bb536fSBarry Smith     }
519c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
520c134de8dSSatish Balay     *f = (void(*)(void))mat->ops->view;
521c7fcc2eaSBarry Smith   } else {
522c134de8dSSatish Balay     *f = (((void(**)(void))mat->ops)[op]);
523d4bb536fSBarry Smith   }
524d4bb536fSBarry Smith 
5253a40ed3dSBarry Smith   PetscFunctionReturn(0);
526d4bb536fSBarry Smith }
527d4bb536fSBarry Smith 
528