xref: /petsc/src/mat/impls/shell/shell.c (revision d519adbfaddd20300d0b94bbdb1ee93b9df0dacd)
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 
97c4f633dSBarry Smith #include "private/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);
1518be62a5SSatish Balay   PetscErrorCode (*multtranspose)(Mat,Vec,Vec);
1618be62a5SSatish Balay   PetscErrorCode (*getdiagonal)(Mat,Vec);
17ef66eb69SBarry Smith   PetscTruth     scale,shift;
18ef66eb69SBarry Smith   PetscScalar    vscale,vshift;
1920563c6bSBarry Smith   void           *ctx;
2088cf3e7dSBarry Smith } Mat_Shell;
21e51e0e81SBarry Smith 
22711e205bSSatish Balay #undef __FUNCT__
23711e205bSSatish Balay #define __FUNCT__ "MatShellGetContext"
2435d520bfSBarry Smith /*@C
25a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
26b4fd4287SBarry Smith 
27c7fcc2eaSBarry Smith     Not Collective
28c7fcc2eaSBarry Smith 
29b4fd4287SBarry Smith     Input Parameter:
30b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
31b4fd4287SBarry Smith 
32b4fd4287SBarry Smith     Output Parameter:
33b4fd4287SBarry Smith .   ctx - the user provided context
34b4fd4287SBarry Smith 
3515091d37SBarry Smith     Level: advanced
3615091d37SBarry Smith 
37a62d957aSLois Curfman McInnes     Notes:
38a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
39a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
40a62d957aSLois Curfman McInnes 
41a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
42a62d957aSLois Curfman McInnes 
43ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellSetOperation(), MatShellSetContext()
440bc0a719SBarry Smith @*/
45be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellGetContext(Mat mat,void **ctx)
46b4fd4287SBarry Smith {
47dfbe8321SBarry Smith   PetscErrorCode ierr;
48273d9f13SBarry Smith   PetscTruth     flg;
49273d9f13SBarry Smith 
503a40ed3dSBarry Smith   PetscFunctionBegin;
514482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
524482741eSBarry Smith   PetscValidPointer(ctx,2);
53273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
54273d9f13SBarry Smith   if (!flg) *ctx = 0;
55b4fd4287SBarry Smith   else      *ctx = ((Mat_Shell*)(mat->data))->ctx;
563a40ed3dSBarry Smith   PetscFunctionReturn(0);
57b4fd4287SBarry Smith }
58b4fd4287SBarry Smith 
59711e205bSSatish Balay #undef __FUNCT__
60711e205bSSatish Balay #define __FUNCT__ "MatDestroy_Shell"
61dfbe8321SBarry Smith PetscErrorCode MatDestroy_Shell(Mat mat)
62e51e0e81SBarry Smith {
63dfbe8321SBarry Smith   PetscErrorCode ierr;
6488cf3e7dSBarry Smith   Mat_Shell      *shell;
65ed3cc1f0SBarry Smith 
663a40ed3dSBarry Smith   PetscFunctionBegin;
6788cf3e7dSBarry Smith   shell = (Mat_Shell*)mat->data;
683a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
69606d414cSSatish Balay   ierr = PetscFree(shell);CHKERRQ(ierr);
703a40ed3dSBarry Smith   PetscFunctionReturn(0);
71e51e0e81SBarry Smith }
72e51e0e81SBarry Smith 
73711e205bSSatish Balay #undef __FUNCT__
74ef66eb69SBarry Smith #define __FUNCT__ "MatMult_Shell"
75dfbe8321SBarry Smith PetscErrorCode MatMult_Shell(Mat A,Vec x,Vec y)
76ef66eb69SBarry Smith {
77ef66eb69SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)A->data;
78dfbe8321SBarry Smith   PetscErrorCode ierr;
79ef66eb69SBarry Smith 
80ef66eb69SBarry Smith   PetscFunctionBegin;
81ef66eb69SBarry Smith   ierr = (*shell->mult)(A,x,y);CHKERRQ(ierr);
82ef66eb69SBarry Smith   if (shell->shift && shell->scale) {
832dcb1b2aSMatthew Knepley     ierr = VecAXPBY(y,shell->vshift,shell->vscale,x);CHKERRQ(ierr);
84ef66eb69SBarry Smith   } else if (shell->scale) {
852dcb1b2aSMatthew Knepley     ierr = VecScale(y,shell->vscale);CHKERRQ(ierr);
86ef66eb69SBarry Smith   } else {
872dcb1b2aSMatthew Knepley     ierr = VecAXPY(y,shell->vshift,x);CHKERRQ(ierr);
88ef66eb69SBarry Smith   }
89ef66eb69SBarry Smith   PetscFunctionReturn(0);
90ef66eb69SBarry Smith }
91ef66eb69SBarry Smith 
92ef66eb69SBarry Smith #undef __FUNCT__
9318be62a5SSatish Balay #define __FUNCT__ "MatMultTranspose_Shell"
9418be62a5SSatish Balay PetscErrorCode MatMultTranspose_Shell(Mat A,Vec x,Vec y)
9518be62a5SSatish Balay {
9618be62a5SSatish Balay   Mat_Shell      *shell = (Mat_Shell*)A->data;
9718be62a5SSatish Balay   PetscErrorCode ierr;
9818be62a5SSatish Balay 
9918be62a5SSatish Balay   PetscFunctionBegin;
10018be62a5SSatish Balay   ierr = (*shell->multtranspose)(A,x,y);CHKERRQ(ierr);
10118be62a5SSatish Balay   if (shell->shift && shell->scale) {
10218be62a5SSatish Balay     ierr = VecAXPBY(y,shell->vshift,shell->vscale,x);CHKERRQ(ierr);
10318be62a5SSatish Balay   } else if (shell->scale) {
10418be62a5SSatish Balay     ierr = VecScale(y,shell->vscale);CHKERRQ(ierr);
10518be62a5SSatish Balay   } else {
10618be62a5SSatish Balay     ierr = VecAXPY(y,shell->vshift,x);CHKERRQ(ierr);
10718be62a5SSatish Balay   }
10818be62a5SSatish Balay   PetscFunctionReturn(0);
10918be62a5SSatish Balay }
11018be62a5SSatish Balay 
11118be62a5SSatish Balay #undef __FUNCT__
11218be62a5SSatish Balay #define __FUNCT__ "MatGetDiagonal_Shell"
11318be62a5SSatish Balay PetscErrorCode MatGetDiagonal_Shell(Mat A,Vec v)
11418be62a5SSatish Balay {
11518be62a5SSatish Balay   Mat_Shell      *shell = (Mat_Shell*)A->data;
11618be62a5SSatish Balay   PetscErrorCode ierr;
11718be62a5SSatish Balay 
11818be62a5SSatish Balay   PetscFunctionBegin;
11918be62a5SSatish Balay   ierr = (*shell->getdiagonal)(A,v);CHKERRQ(ierr);
12018be62a5SSatish Balay   if (shell->scale) {
12118be62a5SSatish Balay     ierr = VecScale(v,shell->vscale);CHKERRQ(ierr);
12218be62a5SSatish Balay   }
12318be62a5SSatish Balay   if (shell->shift) {
12418be62a5SSatish Balay     ierr = VecShift(v,shell->vshift);CHKERRQ(ierr);
12518be62a5SSatish Balay   }
12618be62a5SSatish Balay   PetscFunctionReturn(0);
12718be62a5SSatish Balay }
12818be62a5SSatish Balay 
12918be62a5SSatish Balay #undef __FUNCT__
130ef66eb69SBarry Smith #define __FUNCT__ "MatShift_Shell"
131f4df32b1SMatthew Knepley PetscErrorCode MatShift_Shell(Mat Y,PetscScalar a)
132ef66eb69SBarry Smith {
133ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
134b24ad042SBarry Smith 
135ef66eb69SBarry Smith   PetscFunctionBegin;
136ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
137f4df32b1SMatthew Knepley     shell->vshift += a;
138ef66eb69SBarry Smith   } else {
139ef66eb69SBarry Smith     shell->mult  = Y->ops->mult;
140ef66eb69SBarry Smith     Y->ops->mult = MatMult_Shell;
14118be62a5SSatish Balay     if (Y->ops->multtranspose) {
14218be62a5SSatish Balay       shell->multtranspose  = Y->ops->multtranspose;
14318be62a5SSatish Balay       Y->ops->multtranspose = MatMultTranspose_Shell;
14418be62a5SSatish Balay     }
14518be62a5SSatish Balay     if (Y->ops->getdiagonal) {
14618be62a5SSatish Balay       shell->getdiagonal  = Y->ops->getdiagonal;
14718be62a5SSatish Balay       Y->ops->getdiagonal = MatGetDiagonal_Shell;
14818be62a5SSatish Balay     }
149f4df32b1SMatthew Knepley     shell->vshift = a;
150ef66eb69SBarry Smith   }
151ef66eb69SBarry Smith   shell->shift  =  PETSC_TRUE;
152ef66eb69SBarry Smith   PetscFunctionReturn(0);
153ef66eb69SBarry Smith }
154ef66eb69SBarry Smith 
155ef66eb69SBarry Smith #undef __FUNCT__
156ef66eb69SBarry Smith #define __FUNCT__ "MatScale_Shell"
157f4df32b1SMatthew Knepley PetscErrorCode MatScale_Shell(Mat Y,PetscScalar a)
158ef66eb69SBarry Smith {
159ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
160b24ad042SBarry Smith 
161ef66eb69SBarry Smith   PetscFunctionBegin;
162ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
163f4df32b1SMatthew Knepley     shell->vscale *= a;
164ef66eb69SBarry Smith   } else {
165ef66eb69SBarry Smith     shell->mult  = Y->ops->mult;
166ef66eb69SBarry Smith     Y->ops->mult = MatMult_Shell;
16718be62a5SSatish Balay     if (Y->ops->multtranspose) {
16818be62a5SSatish Balay       shell->multtranspose  = Y->ops->multtranspose;
16918be62a5SSatish Balay       Y->ops->multtranspose = MatMultTranspose_Shell;
17018be62a5SSatish Balay     }
17118be62a5SSatish Balay     if (Y->ops->getdiagonal) {
17218be62a5SSatish Balay       shell->getdiagonal  = Y->ops->getdiagonal;
17318be62a5SSatish Balay       Y->ops->getdiagonal = MatGetDiagonal_Shell;
17418be62a5SSatish Balay     }
175f4df32b1SMatthew Knepley     shell->vscale = a;
176ef66eb69SBarry Smith   }
177ef66eb69SBarry Smith   shell->scale  =  PETSC_TRUE;
178ef66eb69SBarry Smith   PetscFunctionReturn(0);
179ef66eb69SBarry Smith }
180ef66eb69SBarry Smith 
181ef66eb69SBarry Smith #undef __FUNCT__
182ef66eb69SBarry Smith #define __FUNCT__ "MatAssemblyEnd_Shell"
183dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_Shell(Mat Y,MatAssemblyType t)
184ef66eb69SBarry Smith {
185ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
186ef66eb69SBarry Smith 
187ef66eb69SBarry Smith   PetscFunctionBegin;
188ef66eb69SBarry Smith   if ((shell->shift || shell->scale) && t == MAT_FINAL_ASSEMBLY) {
189ef66eb69SBarry Smith     shell->scale  = PETSC_FALSE;
190ef66eb69SBarry Smith     shell->shift  = PETSC_FALSE;
191ef66eb69SBarry Smith     shell->vshift = 0.0;
192ef66eb69SBarry Smith     shell->vscale = 1.0;
193ef66eb69SBarry Smith     Y->ops->mult          = shell->mult;
19418be62a5SSatish Balay     Y->ops->multtranspose = shell->multtranspose;
19518be62a5SSatish Balay     Y->ops->getdiagonal   = shell->getdiagonal;
196ef66eb69SBarry Smith   }
197ef66eb69SBarry Smith   PetscFunctionReturn(0);
198ef66eb69SBarry Smith }
199ef66eb69SBarry Smith 
200a313700dSBarry Smith EXTERN PetscErrorCode MatConvert_Shell(Mat, const MatType,MatReuse,Mat*);
201b951964fSBarry Smith 
202521d7252SBarry Smith #undef __FUNCT__
203521d7252SBarry Smith #define __FUNCT__ "MatSetBlockSize_Shell"
204521d7252SBarry Smith PetscErrorCode MatSetBlockSize_Shell(Mat A,PetscInt bs)
205521d7252SBarry Smith {
206521d7252SBarry Smith   PetscFunctionBegin;
207521d7252SBarry Smith   PetscFunctionReturn(0);
208521d7252SBarry Smith }
209521d7252SBarry Smith 
21009dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
21120563c6bSBarry Smith        0,
21220563c6bSBarry Smith        0,
21320563c6bSBarry Smith        0,
21497304618SKris Buschelman /* 4*/ 0,
21520563c6bSBarry Smith        0,
216b951964fSBarry Smith        0,
217b951964fSBarry Smith        0,
218b951964fSBarry Smith        0,
219b951964fSBarry Smith        0,
22097304618SKris Buschelman /*10*/ 0,
221b951964fSBarry Smith        0,
222b951964fSBarry Smith        0,
223b951964fSBarry Smith        0,
224b951964fSBarry Smith        0,
22597304618SKris Buschelman /*15*/ 0,
226b951964fSBarry Smith        0,
227b951964fSBarry Smith        0,
228b951964fSBarry Smith        0,
229b951964fSBarry Smith        0,
23097304618SKris Buschelman /*20*/ 0,
231ef66eb69SBarry Smith        MatAssemblyEnd_Shell,
232b951964fSBarry Smith        0,
233b951964fSBarry Smith        0,
234*d519adbfSMatthew Knepley /*24*/ 0,
235b951964fSBarry Smith        0,
236b951964fSBarry Smith        0,
237b951964fSBarry Smith        0,
238b951964fSBarry Smith        0,
239*d519adbfSMatthew Knepley /*29*/ 0,
240b951964fSBarry Smith        0,
241273d9f13SBarry Smith        0,
242b951964fSBarry Smith        0,
243b951964fSBarry Smith        0,
244*d519adbfSMatthew Knepley /*34*/ 0,
245b951964fSBarry Smith        0,
246b951964fSBarry Smith        0,
24709dc0095SBarry Smith        0,
24809dc0095SBarry Smith        0,
249*d519adbfSMatthew Knepley /*39*/ 0,
25009dc0095SBarry Smith        0,
25109dc0095SBarry Smith        0,
25209dc0095SBarry Smith        0,
25309dc0095SBarry Smith        0,
254*d519adbfSMatthew Knepley /*44*/ 0,
255ef66eb69SBarry Smith        MatScale_Shell,
256ef66eb69SBarry Smith        MatShift_Shell,
25709dc0095SBarry Smith        0,
25809dc0095SBarry Smith        0,
259*d519adbfSMatthew Knepley /*49*/ MatSetBlockSize_Shell,
26009dc0095SBarry Smith        0,
26109dc0095SBarry Smith        0,
26209dc0095SBarry Smith        0,
26309dc0095SBarry Smith        0,
264*d519adbfSMatthew Knepley /*54*/ 0,
26509dc0095SBarry Smith        0,
26609dc0095SBarry Smith        0,
26709dc0095SBarry Smith        0,
26809dc0095SBarry Smith        0,
269*d519adbfSMatthew Knepley /*59*/ 0,
270b9b97703SBarry Smith        MatDestroy_Shell,
27109dc0095SBarry Smith        0,
272357abbc8SBarry Smith        0,
273273d9f13SBarry Smith        0,
274*d519adbfSMatthew Knepley /*64*/ 0,
275273d9f13SBarry Smith        0,
276273d9f13SBarry Smith        0,
277273d9f13SBarry Smith        0,
278273d9f13SBarry Smith        0,
279*d519adbfSMatthew Knepley /*69*/ 0,
280273d9f13SBarry Smith        0,
281c87e5d42SMatthew Knepley        MatConvert_Shell,
282273d9f13SBarry Smith        0,
28397304618SKris Buschelman        0,
284*d519adbfSMatthew Knepley /*74*/ 0,
28597304618SKris Buschelman        0,
28697304618SKris Buschelman        0,
28797304618SKris Buschelman        0,
28897304618SKris Buschelman        0,
289*d519adbfSMatthew Knepley /*79*/ 0,
29097304618SKris Buschelman        0,
29197304618SKris Buschelman        0,
29297304618SKris Buschelman        0,
293865e5f61SKris Buschelman        0,
294*d519adbfSMatthew Knepley /*84*/ 0,
295865e5f61SKris Buschelman        0,
296865e5f61SKris Buschelman        0,
297865e5f61SKris Buschelman        0,
298865e5f61SKris Buschelman        0,
299*d519adbfSMatthew Knepley /*89*/ 0,
300865e5f61SKris Buschelman        0,
301865e5f61SKris Buschelman        0,
302865e5f61SKris Buschelman        0,
303865e5f61SKris Buschelman        0,
304*d519adbfSMatthew Knepley /*94*/ 0,
305865e5f61SKris Buschelman        0,
306865e5f61SKris Buschelman        0,
307865e5f61SKris Buschelman        0};
308273d9f13SBarry Smith 
3090bad9183SKris Buschelman /*MC
310fafad747SKris Buschelman    MATSHELL - MATSHELL = "shell" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
3110bad9183SKris Buschelman 
3120bad9183SKris Buschelman   Level: advanced
3130bad9183SKris Buschelman 
3140bad9183SKris Buschelman .seealso: MatCreateShell
3150bad9183SKris Buschelman M*/
3160bad9183SKris Buschelman 
317273d9f13SBarry Smith EXTERN_C_BEGIN
318711e205bSSatish Balay #undef __FUNCT__
319711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
320be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_Shell(Mat A)
321273d9f13SBarry Smith {
322273d9f13SBarry Smith   Mat_Shell      *b;
323dfbe8321SBarry Smith   PetscErrorCode ierr;
324273d9f13SBarry Smith 
325273d9f13SBarry Smith   PetscFunctionBegin;
326273d9f13SBarry Smith   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
327273d9f13SBarry Smith 
32838f2d2fdSLisandro Dalcin   ierr = PetscNewLog(A,Mat_Shell,&b);CHKERRQ(ierr);
329273d9f13SBarry Smith   A->data = (void*)b;
330273d9f13SBarry Smith 
331d0f46423SBarry Smith   if (A->rmap->n == PETSC_DECIDE || A->cmap->n == PETSC_DECIDE) {
332e005ede5SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONG,"Must give local row and column count for matrix");
333273d9f13SBarry Smith   }
334273d9f13SBarry Smith 
335d0f46423SBarry Smith   ierr = PetscMapSetBlockSize(A->rmap,1);CHKERRQ(ierr);
336d0f46423SBarry Smith   ierr = PetscMapSetBlockSize(A->cmap,1);CHKERRQ(ierr);
337d0f46423SBarry Smith   ierr = PetscMapSetUp(A->rmap);CHKERRQ(ierr);
338d0f46423SBarry Smith   ierr = PetscMapSetUp(A->cmap);CHKERRQ(ierr);
339273d9f13SBarry Smith 
340273d9f13SBarry Smith   b->ctx           = 0;
341ef66eb69SBarry Smith   b->scale         = PETSC_FALSE;
342ef66eb69SBarry Smith   b->shift         = PETSC_FALSE;
343ef66eb69SBarry Smith   b->vshift        = 0.0;
344ef66eb69SBarry Smith   b->vscale        = 1.0;
345ef66eb69SBarry Smith   b->mult          = 0;
34618be62a5SSatish Balay   b->multtranspose = 0;
34718be62a5SSatish Balay   b->getdiagonal   = 0;
348273d9f13SBarry Smith   A->assembled     = PETSC_TRUE;
349210f0121SBarry Smith   A->preallocated  = PETSC_FALSE;
35017667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSHELL);CHKERRQ(ierr);
351273d9f13SBarry Smith   PetscFunctionReturn(0);
352273d9f13SBarry Smith }
353273d9f13SBarry Smith EXTERN_C_END
354e51e0e81SBarry Smith 
355711e205bSSatish Balay #undef __FUNCT__
356711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
3574b828684SBarry Smith /*@C
358052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
359ff756334SLois Curfman McInnes    private data storage format.
360e51e0e81SBarry Smith 
361c7fcc2eaSBarry Smith   Collective on MPI_Comm
362c7fcc2eaSBarry Smith 
363e51e0e81SBarry Smith    Input Parameters:
364c7fcc2eaSBarry Smith +  comm - MPI communicator
365c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
366c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
367c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
368c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
369c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
370e51e0e81SBarry Smith 
371ff756334SLois Curfman McInnes    Output Parameter:
37244cd7ae7SLois Curfman McInnes .  A - the matrix
373e51e0e81SBarry Smith 
374ff2fd236SBarry Smith    Level: advanced
375ff2fd236SBarry Smith 
376f39d1f56SLois Curfman McInnes   Usage:
3777b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
378f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
379c134de8dSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
380f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
381f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
382f39d1f56SLois Curfman McInnes 
383ff756334SLois Curfman McInnes    Notes:
384ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
385ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
386ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
387e51e0e81SBarry 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.
390f38a8d56SBarry Smith 
391f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
392f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
393645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
394645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
395645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
396645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
397645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
398645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
399645985a0SLois Curfman McInnes    For example,
400f39d1f56SLois Curfman McInnes 
401f39d1f56SLois Curfman McInnes $
402f39d1f56SLois Curfman McInnes $     Vec x, y
4037b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
404645985a0SLois Curfman McInnes $     Mat A
405f39d1f56SLois Curfman McInnes $
406c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
407c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
408f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
409c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
410c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
411c134de8dSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
412645985a0SLois Curfman McInnes $     MatMult(A,x,y);
413645985a0SLois Curfman McInnes $     MatDestroy(A);
414f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
415645985a0SLois Curfman McInnes $
416e51e0e81SBarry Smith 
4170b627109SLois Curfman McInnes .keywords: matrix, shell, create
4180b627109SLois Curfman McInnes 
419ab50ec6bSBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext(), MatShellSetContext()
420e51e0e81SBarry Smith @*/
421be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreateShell(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,void *ctx,Mat *A)
422e51e0e81SBarry Smith {
423dfbe8321SBarry Smith   PetscErrorCode ierr;
424ed3cc1f0SBarry Smith 
4253a40ed3dSBarry Smith   PetscFunctionBegin;
426f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
427f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
428899cda47SBarry Smith 
429273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
430273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
431273d9f13SBarry Smith   PetscFunctionReturn(0);
432c7fcc2eaSBarry Smith }
433c7fcc2eaSBarry Smith 
434711e205bSSatish Balay #undef __FUNCT__
435711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
436c6866cfdSSatish Balay /*@
437273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
438c7fcc2eaSBarry Smith 
439273d9f13SBarry Smith    Collective on Mat
440c7fcc2eaSBarry Smith 
441273d9f13SBarry Smith     Input Parameters:
442273d9f13SBarry Smith +   mat - the shell matrix
443273d9f13SBarry Smith -   ctx - the context
444273d9f13SBarry Smith 
445273d9f13SBarry Smith    Level: advanced
446273d9f13SBarry Smith 
447f38a8d56SBarry Smith    Fortran Notes: The context can only be an integer or a PetscObject
448f38a8d56SBarry Smith       unfortunately it cannot be a Fortran array or derived type.
449273d9f13SBarry Smith 
450273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
4510bc0a719SBarry Smith @*/
452be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellSetContext(Mat mat,void *ctx)
453273d9f13SBarry Smith {
454273d9f13SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)mat->data;
455dfbe8321SBarry Smith   PetscErrorCode ierr;
456273d9f13SBarry Smith   PetscTruth     flg;
457273d9f13SBarry Smith 
458273d9f13SBarry Smith   PetscFunctionBegin;
4594482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
460273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
461273d9f13SBarry Smith   if (flg) {
462273d9f13SBarry Smith     shell->ctx = ctx;
463273d9f13SBarry Smith   }
4643a40ed3dSBarry Smith   PetscFunctionReturn(0);
465e51e0e81SBarry Smith }
466e51e0e81SBarry Smith 
467711e205bSSatish Balay #undef __FUNCT__
468711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
469c16cb8f2SBarry Smith /*@C
4703a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
4713a3eedf2SBarry Smith                            a shell matrix.
472e51e0e81SBarry Smith 
473fee21e36SBarry Smith    Collective on Mat
474fee21e36SBarry Smith 
475c7fcc2eaSBarry Smith     Input Parameters:
476c7fcc2eaSBarry Smith +   mat - the shell matrix
477c7fcc2eaSBarry Smith .   op - the name of the operation
478c7fcc2eaSBarry Smith -   f - the function that provides the operation.
479c7fcc2eaSBarry Smith 
48015091d37SBarry Smith    Level: advanced
48115091d37SBarry Smith 
482fae171e0SBarry Smith     Usage:
483e93bc3c1Svictor $      extern PetscErrorCode usermult(Mat,Vec,Vec);
484f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
485c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
4860b627109SLois Curfman McInnes 
487a62d957aSLois Curfman McInnes     Notes:
488e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
4891c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
490a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
4911c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
492a62d957aSLois Curfman McInnes 
493a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
494deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
495deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
496deebb3c3SLois Curfman McInnes     routines, e.g.,
497a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
498a62d957aSLois Curfman McInnes 
4994aa34b0aSBarry Smith     In particular each function MUST return an error code of 0 on success and
5004aa34b0aSBarry Smith     nonzero on failure.
5014aa34b0aSBarry Smith 
502a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
503a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
504a62d957aSLois Curfman McInnes     set by MatCreateShell().
505a62d957aSLois Curfman McInnes 
506a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
507a62d957aSLois Curfman McInnes 
508ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellSetContext()
509e51e0e81SBarry Smith @*/
510be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
511e51e0e81SBarry Smith {
512dfbe8321SBarry Smith   PetscErrorCode ierr;
513273d9f13SBarry Smith   PetscTruth     flg;
514273d9f13SBarry Smith 
5153a40ed3dSBarry Smith   PetscFunctionBegin;
5164482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
5171c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
518273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
519273d9f13SBarry Smith     if (flg) {
520a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
5216849ba73SBarry Smith        shell->destroy                 = (PetscErrorCode (*)(Mat)) f;
5226849ba73SBarry Smith     } else mat->ops->destroy          = (PetscErrorCode (*)(Mat)) f;
523a62d957aSLois Curfman McInnes   }
5246849ba73SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (PetscErrorCode (*)(Mat,PetscViewer)) f;
525c134de8dSSatish Balay   else                       (((void(**)(void))mat->ops)[op]) = f;
526a62d957aSLois Curfman McInnes 
5273a40ed3dSBarry Smith   PetscFunctionReturn(0);
528e51e0e81SBarry Smith }
529f0479e8cSBarry Smith 
530711e205bSSatish Balay #undef __FUNCT__
531711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
532d4bb536fSBarry Smith /*@C
533d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
534d4bb536fSBarry Smith 
535c7fcc2eaSBarry Smith     Not Collective
536c7fcc2eaSBarry Smith 
537d4bb536fSBarry Smith     Input Parameters:
538c7fcc2eaSBarry Smith +   mat - the shell matrix
539c7fcc2eaSBarry Smith -   op - the name of the operation
540d4bb536fSBarry Smith 
541d4bb536fSBarry Smith     Output Parameter:
542d4bb536fSBarry Smith .   f - the function that provides the operation.
543d4bb536fSBarry Smith 
54415091d37SBarry Smith     Level: advanced
54515091d37SBarry Smith 
546d4bb536fSBarry Smith     Notes:
547e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
548d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
549d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
550d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
551d4bb536fSBarry Smith 
552d4bb536fSBarry Smith     All user-provided functions have the same calling
553d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
554d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
555d4bb536fSBarry Smith     routines, e.g.,
556d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
557d4bb536fSBarry Smith 
558d4bb536fSBarry Smith     Within each user-defined routine, the user should call
559d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
560d4bb536fSBarry Smith     set by MatCreateShell().
561d4bb536fSBarry Smith 
562d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
563d4bb536fSBarry Smith 
564ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation(), MatShellSetContext()
565d4bb536fSBarry Smith @*/
566be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
567d4bb536fSBarry Smith {
568dfbe8321SBarry Smith   PetscErrorCode ierr;
569273d9f13SBarry Smith   PetscTruth     flg;
570273d9f13SBarry Smith 
5713a40ed3dSBarry Smith   PetscFunctionBegin;
5724482741eSBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
573d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
574273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
575273d9f13SBarry Smith     if (flg) {
576d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
577c134de8dSSatish Balay       *f = (void(*)(void))shell->destroy;
578c7fcc2eaSBarry Smith     } else {
579c134de8dSSatish Balay       *f = (void(*)(void))mat->ops->destroy;
580d4bb536fSBarry Smith     }
581c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
582c134de8dSSatish Balay     *f = (void(*)(void))mat->ops->view;
583c7fcc2eaSBarry Smith   } else {
584c134de8dSSatish Balay     *f = (((void(**)(void))mat->ops)[op]);
585d4bb536fSBarry Smith   }
586d4bb536fSBarry Smith 
5873a40ed3dSBarry Smith   PetscFunctionReturn(0);
588d4bb536fSBarry Smith }
589d4bb536fSBarry Smith 
590