xref: /petsc/src/mat/impls/shell/shell.c (revision e93bc3c11e430217b93e6c0883a78d39bef6c101)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
2be1d678aSKris 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*/
101d8d5f9aSSatish Balay #include "private/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 @*/
43be1d678aSKris 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) {
812dcb1b2aSMatthew Knepley     ierr = VecAXPBY(y,shell->vshift,shell->vscale,x);CHKERRQ(ierr);
82ef66eb69SBarry Smith   } else if (shell->scale) {
832dcb1b2aSMatthew Knepley     ierr = VecScale(y,shell->vscale);CHKERRQ(ierr);
84ef66eb69SBarry Smith   } else {
852dcb1b2aSMatthew Knepley     ierr = VecAXPY(y,shell->vshift,x);CHKERRQ(ierr);
86ef66eb69SBarry Smith   }
87ef66eb69SBarry Smith   PetscFunctionReturn(0);
88ef66eb69SBarry Smith }
89ef66eb69SBarry Smith 
90ef66eb69SBarry Smith #undef __FUNCT__
91ef66eb69SBarry Smith #define __FUNCT__ "MatShift_Shell"
92f4df32b1SMatthew Knepley PetscErrorCode MatShift_Shell(Mat Y,PetscScalar a)
93ef66eb69SBarry Smith {
94ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
95b24ad042SBarry Smith 
96ef66eb69SBarry Smith   PetscFunctionBegin;
97ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
98f4df32b1SMatthew Knepley     shell->vshift += a;
99ef66eb69SBarry Smith   } else {
100ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
101ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
102f4df32b1SMatthew Knepley     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"
110f4df32b1SMatthew Knepley PetscErrorCode MatScale_Shell(Mat Y,PetscScalar a)
111ef66eb69SBarry Smith {
112ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
113b24ad042SBarry Smith 
114ef66eb69SBarry Smith   PetscFunctionBegin;
115ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
116f4df32b1SMatthew Knepley     shell->vscale *= a;
117ef66eb69SBarry Smith   } else {
118ef66eb69SBarry Smith     shell->mult   = Y->ops->mult;
119ef66eb69SBarry Smith     Y->ops->mult  = MatMult_Shell;
120f4df32b1SMatthew Knepley     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 
143f69a0ea3SMatthew Knepley EXTERN PetscErrorCode MatConvert_Shell(Mat, 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"
264be1d678aSKris 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 @*/
364be1d678aSKris 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;
369f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
370f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
371273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
372273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
373273d9f13SBarry Smith   PetscFunctionReturn(0);
374c7fcc2eaSBarry Smith }
375c7fcc2eaSBarry Smith 
376711e205bSSatish Balay #undef __FUNCT__
377711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
37805869f15SSatish Balay /*@
379273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
380c7fcc2eaSBarry Smith 
381273d9f13SBarry Smith    Collective on Mat
382c7fcc2eaSBarry Smith 
383273d9f13SBarry Smith     Input Parameters:
384273d9f13SBarry Smith +   mat - the shell matrix
385273d9f13SBarry Smith -   ctx - the context
386273d9f13SBarry Smith 
387273d9f13SBarry Smith    Level: advanced
388273d9f13SBarry Smith 
389f38a8d56SBarry Smith    Fortran Notes: The context can only be an integer or a PetscObject
390f38a8d56SBarry Smith       unfortunately it cannot be a Fortran array or derived type.
391273d9f13SBarry Smith 
392273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
393273d9f13SBarry Smith @*/
394be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellSetContext(Mat mat,void *ctx)
395273d9f13SBarry Smith {
396273d9f13SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)mat->data;
397dfbe8321SBarry Smith   PetscErrorCode ierr;
398273d9f13SBarry Smith   PetscTruth     flg;
399273d9f13SBarry Smith 
400273d9f13SBarry Smith   PetscFunctionBegin;
4014482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
402273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
403273d9f13SBarry Smith   if (flg) {
404273d9f13SBarry Smith     shell->ctx = ctx;
405273d9f13SBarry Smith   }
4063a40ed3dSBarry Smith   PetscFunctionReturn(0);
407e51e0e81SBarry Smith }
408e51e0e81SBarry Smith 
409711e205bSSatish Balay #undef __FUNCT__
410711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
411c16cb8f2SBarry Smith /*@C
4123a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
4133a3eedf2SBarry Smith                            a shell matrix.
414e51e0e81SBarry Smith 
415fee21e36SBarry Smith    Collective on Mat
416fee21e36SBarry Smith 
417c7fcc2eaSBarry Smith     Input Parameters:
418c7fcc2eaSBarry Smith +   mat - the shell matrix
419c7fcc2eaSBarry Smith .   op - the name of the operation
420c7fcc2eaSBarry Smith -   f - the function that provides the operation.
421c7fcc2eaSBarry Smith 
42215091d37SBarry Smith    Level: advanced
42315091d37SBarry Smith 
424fae171e0SBarry Smith     Usage:
425*e93bc3c1Svictor $      extern PetscErrorCode usermult(Mat,Vec,Vec);
426f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
427c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
4280b627109SLois Curfman McInnes 
429a62d957aSLois Curfman McInnes     Notes:
430e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
4311c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
432a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
4331c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
434a62d957aSLois Curfman McInnes 
435a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
436deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
437deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
438deebb3c3SLois Curfman McInnes     routines, e.g.,
439a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
440a62d957aSLois Curfman McInnes 
441a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
442a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
443a62d957aSLois Curfman McInnes     set by MatCreateShell().
444a62d957aSLois Curfman McInnes 
445a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
446a62d957aSLois Curfman McInnes 
447ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellSetContext()
448e51e0e81SBarry Smith @*/
449be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
450e51e0e81SBarry Smith {
451dfbe8321SBarry Smith   PetscErrorCode ierr;
452273d9f13SBarry Smith   PetscTruth     flg;
453273d9f13SBarry Smith 
4543a40ed3dSBarry Smith   PetscFunctionBegin;
4554482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
4561c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
457273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
458273d9f13SBarry Smith     if (flg) {
459a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
4606849ba73SBarry Smith        shell->destroy                 = (PetscErrorCode (*)(Mat)) f;
4616849ba73SBarry Smith     } else mat->ops->destroy          = (PetscErrorCode (*)(Mat)) f;
462a62d957aSLois Curfman McInnes   }
4636849ba73SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (PetscErrorCode (*)(Mat,PetscViewer)) f;
464c134de8dSSatish Balay   else                       (((void(**)(void))mat->ops)[op]) = f;
465a62d957aSLois Curfman McInnes 
4663a40ed3dSBarry Smith   PetscFunctionReturn(0);
467e51e0e81SBarry Smith }
468f0479e8cSBarry Smith 
469711e205bSSatish Balay #undef __FUNCT__
470711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
471d4bb536fSBarry Smith /*@C
472d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
473d4bb536fSBarry Smith 
474c7fcc2eaSBarry Smith     Not Collective
475c7fcc2eaSBarry Smith 
476d4bb536fSBarry Smith     Input Parameters:
477c7fcc2eaSBarry Smith +   mat - the shell matrix
478c7fcc2eaSBarry Smith -   op - the name of the operation
479d4bb536fSBarry Smith 
480d4bb536fSBarry Smith     Output Parameter:
481d4bb536fSBarry Smith .   f - the function that provides the operation.
482d4bb536fSBarry Smith 
48315091d37SBarry Smith     Level: advanced
48415091d37SBarry Smith 
485d4bb536fSBarry Smith     Notes:
486e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
487d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
488d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
489d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
490d4bb536fSBarry Smith 
491d4bb536fSBarry Smith     All user-provided functions have the same calling
492d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
493d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
494d4bb536fSBarry Smith     routines, e.g.,
495d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
496d4bb536fSBarry Smith 
497d4bb536fSBarry Smith     Within each user-defined routine, the user should call
498d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
499d4bb536fSBarry Smith     set by MatCreateShell().
500d4bb536fSBarry Smith 
501d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
502d4bb536fSBarry Smith 
503ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation(), MatShellSetContext()
504d4bb536fSBarry Smith @*/
505be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
506d4bb536fSBarry Smith {
507dfbe8321SBarry Smith   PetscErrorCode ierr;
508273d9f13SBarry Smith   PetscTruth     flg;
509273d9f13SBarry Smith 
5103a40ed3dSBarry Smith   PetscFunctionBegin;
5114482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
512d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
513273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
514273d9f13SBarry Smith     if (flg) {
515d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
516c134de8dSSatish Balay       *f = (void(*)(void))shell->destroy;
517c7fcc2eaSBarry Smith     } else {
518c134de8dSSatish Balay       *f = (void(*)(void))mat->ops->destroy;
519d4bb536fSBarry Smith     }
520c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
521c134de8dSSatish Balay     *f = (void(*)(void))mat->ops->view;
522c7fcc2eaSBarry Smith   } else {
523c134de8dSSatish Balay     *f = (((void(**)(void))mat->ops)[op]);
524d4bb536fSBarry Smith   }
525d4bb536fSBarry Smith 
5263a40ed3dSBarry Smith   PetscFunctionReturn(0);
527d4bb536fSBarry Smith }
528d4bb536fSBarry Smith 
529