xref: /petsc/src/mat/impls/shell/shell.c (revision c6db04a5321582041def2b1e244c75985478b3ef)
1be1d678aSKris Buschelman 
2e51e0e81SBarry Smith /*
320563c6bSBarry Smith    This provides a simple shell for Fortran (and C programmers) to
420563c6bSBarry Smith   create a very simple matrix class for use with KSP without coding
5ed3cc1f0SBarry Smith   much of anything.
6e51e0e81SBarry Smith */
7e51e0e81SBarry Smith 
8*c6db04a5SJed Brown #include <private/matimpl.h>        /*I "petscmat.h" I*/
9*c6db04a5SJed Brown #include <private/vecimpl.h>
10e51e0e81SBarry Smith 
1120563c6bSBarry Smith typedef struct {
126849ba73SBarry Smith   PetscErrorCode (*destroy)(Mat);
136849ba73SBarry Smith   PetscErrorCode (*mult)(Mat,Vec,Vec);
1418be62a5SSatish Balay   PetscErrorCode (*multtranspose)(Mat,Vec,Vec);
1518be62a5SSatish Balay   PetscErrorCode (*getdiagonal)(Mat,Vec);
16ace3abfcSBarry Smith   PetscBool      scale,shift;
17ef66eb69SBarry Smith   PetscScalar    vscale,vshift;
1820563c6bSBarry Smith   void           *ctx;
1988cf3e7dSBarry Smith } Mat_Shell;
20e51e0e81SBarry Smith 
21711e205bSSatish Balay #undef __FUNCT__
22711e205bSSatish Balay #define __FUNCT__ "MatShellGetContext"
2335d520bfSBarry Smith /*@C
24a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
25b4fd4287SBarry Smith 
26c7fcc2eaSBarry Smith     Not Collective
27c7fcc2eaSBarry Smith 
28b4fd4287SBarry Smith     Input Parameter:
29b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
30b4fd4287SBarry Smith 
31b4fd4287SBarry Smith     Output Parameter:
32b4fd4287SBarry Smith .   ctx - the user provided context
33b4fd4287SBarry Smith 
3415091d37SBarry Smith     Level: advanced
3515091d37SBarry Smith 
36a62d957aSLois Curfman McInnes     Notes:
37a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
38a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
39a62d957aSLois Curfman McInnes 
40a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
41a62d957aSLois Curfman McInnes 
42ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellSetOperation(), MatShellSetContext()
430bc0a719SBarry Smith @*/
447087cfbeSBarry Smith PetscErrorCode  MatShellGetContext(Mat mat,void **ctx)
45b4fd4287SBarry Smith {
46dfbe8321SBarry Smith   PetscErrorCode ierr;
47ace3abfcSBarry Smith   PetscBool      flg;
48273d9f13SBarry Smith 
493a40ed3dSBarry Smith   PetscFunctionBegin;
500700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
514482741eSBarry Smith   PetscValidPointer(ctx,2);
52273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
53273d9f13SBarry Smith   if (!flg) *ctx = 0;
54b4fd4287SBarry Smith   else      *ctx = ((Mat_Shell*)(mat->data))->ctx;
553a40ed3dSBarry Smith   PetscFunctionReturn(0);
56b4fd4287SBarry Smith }
57b4fd4287SBarry Smith 
58711e205bSSatish Balay #undef __FUNCT__
59711e205bSSatish Balay #define __FUNCT__ "MatDestroy_Shell"
60dfbe8321SBarry Smith PetscErrorCode MatDestroy_Shell(Mat mat)
61e51e0e81SBarry Smith {
62dfbe8321SBarry Smith   PetscErrorCode ierr;
6388cf3e7dSBarry Smith   Mat_Shell      *shell;
64ed3cc1f0SBarry Smith 
653a40ed3dSBarry Smith   PetscFunctionBegin;
6688cf3e7dSBarry Smith   shell = (Mat_Shell*)mat->data;
673a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
68606d414cSSatish Balay   ierr = PetscFree(shell);CHKERRQ(ierr);
693a40ed3dSBarry Smith   PetscFunctionReturn(0);
70e51e0e81SBarry Smith }
71e51e0e81SBarry Smith 
72711e205bSSatish Balay #undef __FUNCT__
73ef66eb69SBarry Smith #define __FUNCT__ "MatMult_Shell"
74dfbe8321SBarry Smith PetscErrorCode MatMult_Shell(Mat A,Vec x,Vec y)
75ef66eb69SBarry Smith {
76ef66eb69SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)A->data;
77dfbe8321SBarry Smith   PetscErrorCode ierr;
78ef66eb69SBarry Smith 
79ef66eb69SBarry Smith   PetscFunctionBegin;
80ef66eb69SBarry Smith   ierr = (*shell->mult)(A,x,y);CHKERRQ(ierr);
81ef66eb69SBarry Smith   if (shell->shift && shell->scale) {
822dcb1b2aSMatthew Knepley     ierr = VecAXPBY(y,shell->vshift,shell->vscale,x);CHKERRQ(ierr);
83ef66eb69SBarry Smith   } else if (shell->scale) {
842dcb1b2aSMatthew Knepley     ierr = VecScale(y,shell->vscale);CHKERRQ(ierr);
85ef66eb69SBarry Smith   } else {
862dcb1b2aSMatthew Knepley     ierr = VecAXPY(y,shell->vshift,x);CHKERRQ(ierr);
87ef66eb69SBarry Smith   }
88ef66eb69SBarry Smith   PetscFunctionReturn(0);
89ef66eb69SBarry Smith }
90ef66eb69SBarry Smith 
91ef66eb69SBarry Smith #undef __FUNCT__
9218be62a5SSatish Balay #define __FUNCT__ "MatMultTranspose_Shell"
9318be62a5SSatish Balay PetscErrorCode MatMultTranspose_Shell(Mat A,Vec x,Vec y)
9418be62a5SSatish Balay {
9518be62a5SSatish Balay   Mat_Shell      *shell = (Mat_Shell*)A->data;
9618be62a5SSatish Balay   PetscErrorCode ierr;
9718be62a5SSatish Balay 
9818be62a5SSatish Balay   PetscFunctionBegin;
9918be62a5SSatish Balay   ierr = (*shell->multtranspose)(A,x,y);CHKERRQ(ierr);
10018be62a5SSatish Balay   if (shell->shift && shell->scale) {
10118be62a5SSatish Balay     ierr = VecAXPBY(y,shell->vshift,shell->vscale,x);CHKERRQ(ierr);
10218be62a5SSatish Balay   } else if (shell->scale) {
10318be62a5SSatish Balay     ierr = VecScale(y,shell->vscale);CHKERRQ(ierr);
10418be62a5SSatish Balay   } else {
10518be62a5SSatish Balay     ierr = VecAXPY(y,shell->vshift,x);CHKERRQ(ierr);
10618be62a5SSatish Balay   }
10718be62a5SSatish Balay   PetscFunctionReturn(0);
10818be62a5SSatish Balay }
10918be62a5SSatish Balay 
11018be62a5SSatish Balay #undef __FUNCT__
11118be62a5SSatish Balay #define __FUNCT__ "MatGetDiagonal_Shell"
11218be62a5SSatish Balay PetscErrorCode MatGetDiagonal_Shell(Mat A,Vec v)
11318be62a5SSatish Balay {
11418be62a5SSatish Balay   Mat_Shell      *shell = (Mat_Shell*)A->data;
11518be62a5SSatish Balay   PetscErrorCode ierr;
11618be62a5SSatish Balay 
11718be62a5SSatish Balay   PetscFunctionBegin;
11818be62a5SSatish Balay   ierr = (*shell->getdiagonal)(A,v);CHKERRQ(ierr);
11918be62a5SSatish Balay   if (shell->scale) {
12018be62a5SSatish Balay     ierr = VecScale(v,shell->vscale);CHKERRQ(ierr);
12118be62a5SSatish Balay   }
12218be62a5SSatish Balay   if (shell->shift) {
12318be62a5SSatish Balay     ierr = VecShift(v,shell->vshift);CHKERRQ(ierr);
12418be62a5SSatish Balay   }
12518be62a5SSatish Balay   PetscFunctionReturn(0);
12618be62a5SSatish Balay }
12718be62a5SSatish Balay 
12818be62a5SSatish Balay #undef __FUNCT__
129ef66eb69SBarry Smith #define __FUNCT__ "MatShift_Shell"
130f4df32b1SMatthew Knepley PetscErrorCode MatShift_Shell(Mat Y,PetscScalar a)
131ef66eb69SBarry Smith {
132ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
133b24ad042SBarry Smith 
134ef66eb69SBarry Smith   PetscFunctionBegin;
135ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
136f4df32b1SMatthew Knepley     shell->vshift += a;
137ef66eb69SBarry Smith   } else {
138ef66eb69SBarry Smith     shell->mult  = Y->ops->mult;
139ef66eb69SBarry Smith     Y->ops->mult = MatMult_Shell;
14018be62a5SSatish Balay     if (Y->ops->multtranspose) {
14118be62a5SSatish Balay       shell->multtranspose  = Y->ops->multtranspose;
14218be62a5SSatish Balay       Y->ops->multtranspose = MatMultTranspose_Shell;
14318be62a5SSatish Balay     }
14418be62a5SSatish Balay     if (Y->ops->getdiagonal) {
14518be62a5SSatish Balay       shell->getdiagonal  = Y->ops->getdiagonal;
14618be62a5SSatish Balay       Y->ops->getdiagonal = MatGetDiagonal_Shell;
14718be62a5SSatish Balay     }
148f4df32b1SMatthew Knepley     shell->vshift = a;
149ef66eb69SBarry Smith   }
150ef66eb69SBarry Smith   shell->shift  =  PETSC_TRUE;
151ef66eb69SBarry Smith   PetscFunctionReturn(0);
152ef66eb69SBarry Smith }
153ef66eb69SBarry Smith 
154ef66eb69SBarry Smith #undef __FUNCT__
155ef66eb69SBarry Smith #define __FUNCT__ "MatScale_Shell"
156f4df32b1SMatthew Knepley PetscErrorCode MatScale_Shell(Mat Y,PetscScalar a)
157ef66eb69SBarry Smith {
158ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
159b24ad042SBarry Smith 
160ef66eb69SBarry Smith   PetscFunctionBegin;
161ef66eb69SBarry Smith   if (shell->scale || shell->shift) {
162f4df32b1SMatthew Knepley     shell->vscale *= a;
163ef66eb69SBarry Smith   } else {
164ef66eb69SBarry Smith     shell->mult  = Y->ops->mult;
165ef66eb69SBarry Smith     Y->ops->mult = MatMult_Shell;
16618be62a5SSatish Balay     if (Y->ops->multtranspose) {
16718be62a5SSatish Balay       shell->multtranspose  = Y->ops->multtranspose;
16818be62a5SSatish Balay       Y->ops->multtranspose = MatMultTranspose_Shell;
16918be62a5SSatish Balay     }
17018be62a5SSatish Balay     if (Y->ops->getdiagonal) {
17118be62a5SSatish Balay       shell->getdiagonal  = Y->ops->getdiagonal;
17218be62a5SSatish Balay       Y->ops->getdiagonal = MatGetDiagonal_Shell;
17318be62a5SSatish Balay     }
174f4df32b1SMatthew Knepley     shell->vscale = a;
175ef66eb69SBarry Smith   }
176ef66eb69SBarry Smith   shell->scale  =  PETSC_TRUE;
177ef66eb69SBarry Smith   PetscFunctionReturn(0);
178ef66eb69SBarry Smith }
179ef66eb69SBarry Smith 
180ef66eb69SBarry Smith #undef __FUNCT__
181ef66eb69SBarry Smith #define __FUNCT__ "MatAssemblyEnd_Shell"
182dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_Shell(Mat Y,MatAssemblyType t)
183ef66eb69SBarry Smith {
184ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
185ef66eb69SBarry Smith 
186ef66eb69SBarry Smith   PetscFunctionBegin;
187ef66eb69SBarry Smith   if ((shell->shift || shell->scale) && t == MAT_FINAL_ASSEMBLY) {
188ef66eb69SBarry Smith     shell->scale  = PETSC_FALSE;
189ef66eb69SBarry Smith     shell->shift  = PETSC_FALSE;
190ef66eb69SBarry Smith     shell->vshift = 0.0;
191ef66eb69SBarry Smith     shell->vscale = 1.0;
192ef66eb69SBarry Smith     Y->ops->mult          = shell->mult;
19318be62a5SSatish Balay     Y->ops->multtranspose = shell->multtranspose;
19418be62a5SSatish Balay     Y->ops->getdiagonal   = shell->getdiagonal;
195ef66eb69SBarry Smith   }
196ef66eb69SBarry Smith   PetscFunctionReturn(0);
197ef66eb69SBarry Smith }
198ef66eb69SBarry Smith 
19909573ac7SBarry Smith extern PetscErrorCode MatConvert_Shell(Mat, const MatType,MatReuse,Mat*);
200b951964fSBarry Smith 
201521d7252SBarry Smith #undef __FUNCT__
202521d7252SBarry Smith #define __FUNCT__ "MatSetBlockSize_Shell"
203521d7252SBarry Smith PetscErrorCode MatSetBlockSize_Shell(Mat A,PetscInt bs)
204521d7252SBarry Smith {
20541c166b1SJed Brown   PetscErrorCode ierr;
20641c166b1SJed Brown 
207521d7252SBarry Smith   PetscFunctionBegin;
20841c166b1SJed Brown   ierr = PetscLayoutSetBlockSize(A->rmap,bs);CHKERRQ(ierr);
20941c166b1SJed Brown   ierr = PetscLayoutSetBlockSize(A->cmap,bs);CHKERRQ(ierr);
210521d7252SBarry Smith   PetscFunctionReturn(0);
211521d7252SBarry Smith }
212521d7252SBarry Smith 
21309dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
21420563c6bSBarry Smith        0,
21520563c6bSBarry Smith        0,
21620563c6bSBarry Smith        0,
21797304618SKris Buschelman /* 4*/ 0,
21820563c6bSBarry Smith        0,
219b951964fSBarry Smith        0,
220b951964fSBarry Smith        0,
221b951964fSBarry Smith        0,
222b951964fSBarry Smith        0,
22397304618SKris Buschelman /*10*/ 0,
224b951964fSBarry Smith        0,
225b951964fSBarry Smith        0,
226b951964fSBarry Smith        0,
227b951964fSBarry Smith        0,
22897304618SKris Buschelman /*15*/ 0,
229b951964fSBarry Smith        0,
230b951964fSBarry Smith        0,
231b951964fSBarry Smith        0,
232b951964fSBarry Smith        0,
23397304618SKris Buschelman /*20*/ 0,
234ef66eb69SBarry Smith        MatAssemblyEnd_Shell,
235b951964fSBarry Smith        0,
236b951964fSBarry Smith        0,
237d519adbfSMatthew Knepley /*24*/ 0,
238b951964fSBarry Smith        0,
239b951964fSBarry Smith        0,
240b951964fSBarry Smith        0,
241b951964fSBarry Smith        0,
242d519adbfSMatthew Knepley /*29*/ 0,
243b951964fSBarry Smith        0,
244273d9f13SBarry Smith        0,
245b951964fSBarry Smith        0,
246b951964fSBarry Smith        0,
247d519adbfSMatthew Knepley /*34*/ 0,
248b951964fSBarry Smith        0,
249b951964fSBarry Smith        0,
25009dc0095SBarry Smith        0,
25109dc0095SBarry Smith        0,
252d519adbfSMatthew Knepley /*39*/ 0,
25309dc0095SBarry Smith        0,
25409dc0095SBarry Smith        0,
25509dc0095SBarry Smith        0,
25609dc0095SBarry Smith        0,
257d519adbfSMatthew Knepley /*44*/ 0,
258ef66eb69SBarry Smith        MatScale_Shell,
259ef66eb69SBarry Smith        MatShift_Shell,
26009dc0095SBarry Smith        0,
26109dc0095SBarry Smith        0,
262d519adbfSMatthew Knepley /*49*/ MatSetBlockSize_Shell,
26309dc0095SBarry Smith        0,
26409dc0095SBarry Smith        0,
26509dc0095SBarry Smith        0,
26609dc0095SBarry Smith        0,
267d519adbfSMatthew Knepley /*54*/ 0,
26809dc0095SBarry Smith        0,
26909dc0095SBarry Smith        0,
27009dc0095SBarry Smith        0,
27109dc0095SBarry Smith        0,
272d519adbfSMatthew Knepley /*59*/ 0,
273b9b97703SBarry Smith        MatDestroy_Shell,
27409dc0095SBarry Smith        0,
275357abbc8SBarry Smith        0,
276273d9f13SBarry Smith        0,
277d519adbfSMatthew Knepley /*64*/ 0,
278273d9f13SBarry Smith        0,
279273d9f13SBarry Smith        0,
280273d9f13SBarry Smith        0,
281273d9f13SBarry Smith        0,
282d519adbfSMatthew Knepley /*69*/ 0,
283273d9f13SBarry Smith        0,
284c87e5d42SMatthew Knepley        MatConvert_Shell,
285273d9f13SBarry Smith        0,
28697304618SKris Buschelman        0,
287d519adbfSMatthew Knepley /*74*/ 0,
28897304618SKris Buschelman        0,
28997304618SKris Buschelman        0,
29097304618SKris Buschelman        0,
29197304618SKris Buschelman        0,
292d519adbfSMatthew Knepley /*79*/ 0,
29397304618SKris Buschelman        0,
29497304618SKris Buschelman        0,
29597304618SKris Buschelman        0,
296865e5f61SKris Buschelman        0,
297d519adbfSMatthew Knepley /*84*/ 0,
298865e5f61SKris Buschelman        0,
299865e5f61SKris Buschelman        0,
300865e5f61SKris Buschelman        0,
301865e5f61SKris Buschelman        0,
302d519adbfSMatthew Knepley /*89*/ 0,
303865e5f61SKris Buschelman        0,
304865e5f61SKris Buschelman        0,
305865e5f61SKris Buschelman        0,
306865e5f61SKris Buschelman        0,
307d519adbfSMatthew Knepley /*94*/ 0,
308865e5f61SKris Buschelman        0,
309865e5f61SKris Buschelman        0,
310865e5f61SKris Buschelman        0};
311273d9f13SBarry Smith 
3120bad9183SKris Buschelman /*MC
313fafad747SKris Buschelman    MATSHELL - MATSHELL = "shell" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
3140bad9183SKris Buschelman 
3150bad9183SKris Buschelman   Level: advanced
3160bad9183SKris Buschelman 
3170bad9183SKris Buschelman .seealso: MatCreateShell
3180bad9183SKris Buschelman M*/
3190bad9183SKris Buschelman 
320273d9f13SBarry Smith EXTERN_C_BEGIN
321711e205bSSatish Balay #undef __FUNCT__
322711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
3237087cfbeSBarry Smith PetscErrorCode  MatCreate_Shell(Mat A)
324273d9f13SBarry Smith {
325273d9f13SBarry Smith   Mat_Shell      *b;
326dfbe8321SBarry Smith   PetscErrorCode ierr;
327273d9f13SBarry Smith 
328273d9f13SBarry Smith   PetscFunctionBegin;
329273d9f13SBarry Smith   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
330273d9f13SBarry Smith 
33138f2d2fdSLisandro Dalcin   ierr = PetscNewLog(A,Mat_Shell,&b);CHKERRQ(ierr);
332273d9f13SBarry Smith   A->data = (void*)b;
333273d9f13SBarry Smith 
33426283091SBarry Smith   ierr = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr);
33526283091SBarry Smith   ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr);
33626283091SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
33726283091SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
338273d9f13SBarry Smith 
339273d9f13SBarry Smith   b->ctx           = 0;
340ef66eb69SBarry Smith   b->scale         = PETSC_FALSE;
341ef66eb69SBarry Smith   b->shift         = PETSC_FALSE;
342ef66eb69SBarry Smith   b->vshift        = 0.0;
343ef66eb69SBarry Smith   b->vscale        = 1.0;
344ef66eb69SBarry Smith   b->mult          = 0;
34518be62a5SSatish Balay   b->multtranspose = 0;
34618be62a5SSatish Balay   b->getdiagonal   = 0;
347273d9f13SBarry Smith   A->assembled     = PETSC_TRUE;
348210f0121SBarry Smith   A->preallocated  = PETSC_FALSE;
34917667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSHELL);CHKERRQ(ierr);
350273d9f13SBarry Smith   PetscFunctionReturn(0);
351273d9f13SBarry Smith }
352273d9f13SBarry Smith EXTERN_C_END
353e51e0e81SBarry Smith 
354711e205bSSatish Balay #undef __FUNCT__
355711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
3564b828684SBarry Smith /*@C
357052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
358ff756334SLois Curfman McInnes    private data storage format.
359e51e0e81SBarry Smith 
360c7fcc2eaSBarry Smith   Collective on MPI_Comm
361c7fcc2eaSBarry Smith 
362e51e0e81SBarry Smith    Input Parameters:
363c7fcc2eaSBarry Smith +  comm - MPI communicator
364c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
365c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
366c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
367c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
368c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
369e51e0e81SBarry Smith 
370ff756334SLois Curfman McInnes    Output Parameter:
37144cd7ae7SLois Curfman McInnes .  A - the matrix
372e51e0e81SBarry Smith 
373ff2fd236SBarry Smith    Level: advanced
374ff2fd236SBarry Smith 
375f39d1f56SLois Curfman McInnes   Usage:
3767b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
377f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
378c134de8dSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
379f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
380f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
381f39d1f56SLois Curfman McInnes 
382ff756334SLois Curfman McInnes    Notes:
383ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
384ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
385ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
386e51e0e81SBarry Smith 
387f38a8d56SBarry Smith    Fortran Notes: The context can only be an integer or a PetscObject
388f38a8d56SBarry Smith       unfortunately it cannot be a Fortran array or derived type.
389f38a8d56SBarry Smith 
390f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
391f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
392645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
393645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
394645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
395645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
396645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
397645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
398645985a0SLois Curfman McInnes    For example,
399f39d1f56SLois Curfman McInnes 
400f39d1f56SLois Curfman McInnes $
401f39d1f56SLois Curfman McInnes $     Vec x, y
4027b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
403645985a0SLois Curfman McInnes $     Mat A
404f39d1f56SLois Curfman McInnes $
405c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
406c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
407f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
408c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
409c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
410c134de8dSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
411645985a0SLois Curfman McInnes $     MatMult(A,x,y);
412645985a0SLois Curfman McInnes $     MatDestroy(A);
413f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
414645985a0SLois Curfman McInnes $
415e51e0e81SBarry Smith 
4160b627109SLois Curfman McInnes .keywords: matrix, shell, create
4170b627109SLois Curfman McInnes 
418ab50ec6bSBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext(), MatShellSetContext()
419e51e0e81SBarry Smith @*/
4207087cfbeSBarry Smith PetscErrorCode  MatCreateShell(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,void *ctx,Mat *A)
421e51e0e81SBarry Smith {
422dfbe8321SBarry Smith   PetscErrorCode ierr;
423ed3cc1f0SBarry Smith 
4243a40ed3dSBarry Smith   PetscFunctionBegin;
425f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
426f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
427899cda47SBarry Smith 
428273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
429273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
430273d9f13SBarry Smith   PetscFunctionReturn(0);
431c7fcc2eaSBarry Smith }
432c7fcc2eaSBarry Smith 
433711e205bSSatish Balay #undef __FUNCT__
434711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
435c6866cfdSSatish Balay /*@
436273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
437c7fcc2eaSBarry Smith 
4383f9fe445SBarry Smith    Logically Collective on Mat
439c7fcc2eaSBarry Smith 
440273d9f13SBarry Smith     Input Parameters:
441273d9f13SBarry Smith +   mat - the shell matrix
442273d9f13SBarry Smith -   ctx - the context
443273d9f13SBarry Smith 
444273d9f13SBarry Smith    Level: advanced
445273d9f13SBarry Smith 
446f38a8d56SBarry Smith    Fortran Notes: The context can only be an integer or a PetscObject
447f38a8d56SBarry Smith       unfortunately it cannot be a Fortran array or derived type.
448273d9f13SBarry Smith 
449273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
4500bc0a719SBarry Smith @*/
4517087cfbeSBarry Smith PetscErrorCode  MatShellSetContext(Mat mat,void *ctx)
452273d9f13SBarry Smith {
453273d9f13SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)mat->data;
454dfbe8321SBarry Smith   PetscErrorCode ierr;
455ace3abfcSBarry Smith   PetscBool      flg;
456273d9f13SBarry Smith 
457273d9f13SBarry Smith   PetscFunctionBegin;
4580700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
459273d9f13SBarry Smith   ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
460273d9f13SBarry Smith   if (flg) {
461273d9f13SBarry Smith     shell->ctx = ctx;
462273d9f13SBarry Smith   }
4633a40ed3dSBarry Smith   PetscFunctionReturn(0);
464e51e0e81SBarry Smith }
465e51e0e81SBarry Smith 
466711e205bSSatish Balay #undef __FUNCT__
467711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
468c16cb8f2SBarry Smith /*@C
4693a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
4703a3eedf2SBarry Smith                            a shell matrix.
471e51e0e81SBarry Smith 
4723f9fe445SBarry Smith    Logically Collective on Mat
473fee21e36SBarry Smith 
474c7fcc2eaSBarry Smith     Input Parameters:
475c7fcc2eaSBarry Smith +   mat - the shell matrix
476c7fcc2eaSBarry Smith .   op - the name of the operation
477c7fcc2eaSBarry Smith -   f - the function that provides the operation.
478c7fcc2eaSBarry Smith 
47915091d37SBarry Smith    Level: advanced
48015091d37SBarry Smith 
481fae171e0SBarry Smith     Usage:
482e93bc3c1Svictor $      extern PetscErrorCode usermult(Mat,Vec,Vec);
483f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
484c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
4850b627109SLois Curfman McInnes 
486a62d957aSLois Curfman McInnes     Notes:
487e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
4881c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
489a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
4901c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
491a62d957aSLois Curfman McInnes 
492a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
493deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
494deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
495deebb3c3SLois Curfman McInnes     routines, e.g.,
496a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
497a62d957aSLois Curfman McInnes 
4984aa34b0aSBarry Smith     In particular each function MUST return an error code of 0 on success and
4994aa34b0aSBarry Smith     nonzero on failure.
5004aa34b0aSBarry Smith 
501a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
502a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
503a62d957aSLois Curfman McInnes     set by MatCreateShell().
504a62d957aSLois Curfman McInnes 
505501d9185SBarry Smith     Fortran Notes: For MatGetVecs() the user code should check if the input left or right matrix is -1 and in that case not
506501d9185SBarry Smith        generate a matrix. See src/mat/examples/tests/ex120f.F
507501d9185SBarry Smith 
508a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
509a62d957aSLois Curfman McInnes 
510ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellSetContext()
511e51e0e81SBarry Smith @*/
5127087cfbeSBarry Smith PetscErrorCode  MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
513e51e0e81SBarry Smith {
514dfbe8321SBarry Smith   PetscErrorCode ierr;
515ace3abfcSBarry Smith   PetscBool      flg;
516273d9f13SBarry Smith 
5173a40ed3dSBarry Smith   PetscFunctionBegin;
5180700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5191c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
520273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
521273d9f13SBarry Smith     if (flg) {
522a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell*)mat->data;
5236849ba73SBarry Smith        shell->destroy                 = (PetscErrorCode (*)(Mat)) f;
5246849ba73SBarry Smith     } else mat->ops->destroy          = (PetscErrorCode (*)(Mat)) f;
525a62d957aSLois Curfman McInnes   }
5266849ba73SBarry Smith   else if (op == MATOP_VIEW) mat->ops->view  = (PetscErrorCode (*)(Mat,PetscViewer)) f;
527c134de8dSSatish Balay   else                       (((void(**)(void))mat->ops)[op]) = f;
528a62d957aSLois Curfman McInnes 
5293a40ed3dSBarry Smith   PetscFunctionReturn(0);
530e51e0e81SBarry Smith }
531f0479e8cSBarry Smith 
532711e205bSSatish Balay #undef __FUNCT__
533711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
534d4bb536fSBarry Smith /*@C
535d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
536d4bb536fSBarry Smith 
537c7fcc2eaSBarry Smith     Not Collective
538c7fcc2eaSBarry Smith 
539d4bb536fSBarry Smith     Input Parameters:
540c7fcc2eaSBarry Smith +   mat - the shell matrix
541c7fcc2eaSBarry Smith -   op - the name of the operation
542d4bb536fSBarry Smith 
543d4bb536fSBarry Smith     Output Parameter:
544d4bb536fSBarry Smith .   f - the function that provides the operation.
545d4bb536fSBarry Smith 
54615091d37SBarry Smith     Level: advanced
54715091d37SBarry Smith 
548d4bb536fSBarry Smith     Notes:
549e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
550d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
551d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
552d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
553d4bb536fSBarry Smith 
554d4bb536fSBarry Smith     All user-provided functions have the same calling
555d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
556d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
557d4bb536fSBarry Smith     routines, e.g.,
558d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
559d4bb536fSBarry Smith 
560d4bb536fSBarry Smith     Within each user-defined routine, the user should call
561d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
562d4bb536fSBarry Smith     set by MatCreateShell().
563d4bb536fSBarry Smith 
564d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
565d4bb536fSBarry Smith 
566ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation(), MatShellSetContext()
567d4bb536fSBarry Smith @*/
5687087cfbeSBarry Smith PetscErrorCode  MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
569d4bb536fSBarry Smith {
570dfbe8321SBarry Smith   PetscErrorCode ierr;
571ace3abfcSBarry Smith   PetscBool      flg;
572273d9f13SBarry Smith 
5733a40ed3dSBarry Smith   PetscFunctionBegin;
5740700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
575d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
576273d9f13SBarry Smith     ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
577273d9f13SBarry Smith     if (flg) {
578d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
579c134de8dSSatish Balay       *f = (void(*)(void))shell->destroy;
580c7fcc2eaSBarry Smith     } else {
581c134de8dSSatish Balay       *f = (void(*)(void))mat->ops->destroy;
582d4bb536fSBarry Smith     }
583c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
584c134de8dSSatish Balay     *f = (void(*)(void))mat->ops->view;
585c7fcc2eaSBarry Smith   } else {
586c134de8dSSatish Balay     *f = (((void(**)(void))mat->ops)[op]);
587d4bb536fSBarry Smith   }
588d4bb536fSBarry Smith 
5893a40ed3dSBarry Smith   PetscFunctionReturn(0);
590d4bb536fSBarry Smith }
591d4bb536fSBarry Smith 
592