xref: /petsc/src/mat/impls/shell/shell.c (revision daf670e6b6806aa4641b59813b183d0635e60101)
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 
8af0996ceSBarry Smith #include <petsc/private/matimpl.h>        /*I "petscmat.h" I*/
9af0996ceSBarry Smith #include <petsc/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);
162205254eSKarl Rupp 
17ef66eb69SBarry Smith   PetscScalar vscale,vshift;
188fe8eb27SJed Brown   Vec         dshift;
198fe8eb27SJed Brown   Vec         left,right;
208fe8eb27SJed Brown   Vec         dshift_owned,left_owned,right_owned;
218fe8eb27SJed Brown   Vec         left_work,right_work;
225edf6516SJed Brown   Vec         left_add_work,right_add_work;
238fe8eb27SJed Brown   PetscBool   usingscaled;
2420563c6bSBarry Smith   void        *ctx;
2588cf3e7dSBarry Smith } Mat_Shell;
268fe8eb27SJed Brown /*
278fe8eb27SJed Brown  The most general expression for the matrix is
288fe8eb27SJed Brown 
298fe8eb27SJed Brown  S = L (a A + B) R
308fe8eb27SJed Brown 
318fe8eb27SJed Brown  where
328fe8eb27SJed Brown  A is the matrix defined by the user's function
338fe8eb27SJed Brown  a is a scalar multiple
348fe8eb27SJed Brown  L is left scaling
358fe8eb27SJed Brown  R is right scaling
368fe8eb27SJed Brown  B is a diagonal shift defined by
378fe8eb27SJed Brown    diag(dshift) if the vector dshift is non-NULL
388fe8eb27SJed Brown    vscale*identity otherwise
398fe8eb27SJed Brown 
408fe8eb27SJed Brown  The following identities apply:
418fe8eb27SJed Brown 
428fe8eb27SJed Brown  Scale by c:
438fe8eb27SJed Brown   c [L (a A + B) R] = L [(a c) A + c B] R
448fe8eb27SJed Brown 
458fe8eb27SJed Brown  Shift by c:
468fe8eb27SJed Brown   [L (a A + B) R] + c = L [a A + (B + c Linv Rinv)] R
478fe8eb27SJed Brown 
488fe8eb27SJed Brown  Diagonal scaling is achieved by simply multiplying with existing L and R vectors
498fe8eb27SJed Brown 
508fe8eb27SJed Brown  In the data structure:
518fe8eb27SJed Brown 
528fe8eb27SJed Brown  vscale=1.0  means no special scaling will be applied
538fe8eb27SJed Brown  dshift=NULL means a constant diagonal shift (fall back to vshift)
548fe8eb27SJed Brown  vshift=0.0  means no constant diagonal shift, note that vshift is only used if dshift is NULL
558fe8eb27SJed Brown */
568fe8eb27SJed Brown 
578fe8eb27SJed Brown static PetscErrorCode MatMult_Shell(Mat,Vec,Vec);
588fe8eb27SJed Brown static PetscErrorCode MatMultTranspose_Shell(Mat,Vec,Vec);
598fe8eb27SJed Brown static PetscErrorCode MatGetDiagonal_Shell(Mat,Vec);
608fe8eb27SJed Brown 
618fe8eb27SJed Brown #undef __FUNCT__
628fe8eb27SJed Brown #define __FUNCT__ "MatShellUseScaledMethods"
638fe8eb27SJed Brown static PetscErrorCode MatShellUseScaledMethods(Mat Y)
648fe8eb27SJed Brown {
658fe8eb27SJed Brown   Mat_Shell *shell = (Mat_Shell*)Y->data;
668fe8eb27SJed Brown 
678fe8eb27SJed Brown   PetscFunctionBegin;
688fe8eb27SJed Brown   if (shell->usingscaled) PetscFunctionReturn(0);
698fe8eb27SJed Brown   shell->mult  = Y->ops->mult;
708fe8eb27SJed Brown   Y->ops->mult = MatMult_Shell;
718fe8eb27SJed Brown   if (Y->ops->multtranspose) {
728fe8eb27SJed Brown     shell->multtranspose  = Y->ops->multtranspose;
738fe8eb27SJed Brown     Y->ops->multtranspose = MatMultTranspose_Shell;
748fe8eb27SJed Brown   }
758fe8eb27SJed Brown   if (Y->ops->getdiagonal) {
768fe8eb27SJed Brown     shell->getdiagonal  = Y->ops->getdiagonal;
778fe8eb27SJed Brown     Y->ops->getdiagonal = MatGetDiagonal_Shell;
788fe8eb27SJed Brown   }
798fe8eb27SJed Brown   shell->usingscaled = PETSC_TRUE;
808fe8eb27SJed Brown   PetscFunctionReturn(0);
818fe8eb27SJed Brown }
828fe8eb27SJed Brown 
838fe8eb27SJed Brown #undef __FUNCT__
848fe8eb27SJed Brown #define __FUNCT__ "MatShellPreScaleLeft"
858fe8eb27SJed Brown static PetscErrorCode MatShellPreScaleLeft(Mat A,Vec x,Vec *xx)
868fe8eb27SJed Brown {
878fe8eb27SJed Brown   Mat_Shell      *shell = (Mat_Shell*)A->data;
888fe8eb27SJed Brown   PetscErrorCode ierr;
898fe8eb27SJed Brown 
908fe8eb27SJed Brown   PetscFunctionBegin;
910298fd71SBarry Smith   *xx = NULL;
928fe8eb27SJed Brown   if (!shell->left) {
938fe8eb27SJed Brown     *xx = x;
948fe8eb27SJed Brown   } else {
958fe8eb27SJed Brown     if (!shell->left_work) {ierr = VecDuplicate(shell->left,&shell->left_work);CHKERRQ(ierr);}
968fe8eb27SJed Brown     ierr = VecPointwiseMult(shell->left_work,x,shell->left);CHKERRQ(ierr);
978fe8eb27SJed Brown     *xx  = shell->left_work;
988fe8eb27SJed Brown   }
998fe8eb27SJed Brown   PetscFunctionReturn(0);
1008fe8eb27SJed Brown }
1018fe8eb27SJed Brown 
1028fe8eb27SJed Brown #undef __FUNCT__
1038fe8eb27SJed Brown #define __FUNCT__ "MatShellPreScaleRight"
1048fe8eb27SJed Brown static PetscErrorCode MatShellPreScaleRight(Mat A,Vec x,Vec *xx)
1058fe8eb27SJed Brown {
1068fe8eb27SJed Brown   Mat_Shell      *shell = (Mat_Shell*)A->data;
1078fe8eb27SJed Brown   PetscErrorCode ierr;
1088fe8eb27SJed Brown 
1098fe8eb27SJed Brown   PetscFunctionBegin;
1100298fd71SBarry Smith   *xx = NULL;
1118fe8eb27SJed Brown   if (!shell->right) {
1128fe8eb27SJed Brown     *xx = x;
1138fe8eb27SJed Brown   } else {
1148fe8eb27SJed Brown     if (!shell->right_work) {ierr = VecDuplicate(shell->right,&shell->right_work);CHKERRQ(ierr);}
1158fe8eb27SJed Brown     ierr = VecPointwiseMult(shell->right_work,x,shell->right);CHKERRQ(ierr);
1168fe8eb27SJed Brown     *xx  = shell->right_work;
1178fe8eb27SJed Brown   }
1188fe8eb27SJed Brown   PetscFunctionReturn(0);
1198fe8eb27SJed Brown }
1208fe8eb27SJed Brown 
1218fe8eb27SJed Brown #undef __FUNCT__
1228fe8eb27SJed Brown #define __FUNCT__ "MatShellPostScaleLeft"
1238fe8eb27SJed Brown static PetscErrorCode MatShellPostScaleLeft(Mat A,Vec x)
1248fe8eb27SJed Brown {
1258fe8eb27SJed Brown   Mat_Shell      *shell = (Mat_Shell*)A->data;
1268fe8eb27SJed Brown   PetscErrorCode ierr;
1278fe8eb27SJed Brown 
1288fe8eb27SJed Brown   PetscFunctionBegin;
1298fe8eb27SJed Brown   if (shell->left) {ierr = VecPointwiseMult(x,x,shell->left);CHKERRQ(ierr);}
1308fe8eb27SJed Brown   PetscFunctionReturn(0);
1318fe8eb27SJed Brown }
1328fe8eb27SJed Brown 
1338fe8eb27SJed Brown #undef __FUNCT__
1348fe8eb27SJed Brown #define __FUNCT__ "MatShellPostScaleRight"
1358fe8eb27SJed Brown static PetscErrorCode MatShellPostScaleRight(Mat A,Vec x)
1368fe8eb27SJed Brown {
1378fe8eb27SJed Brown   Mat_Shell      *shell = (Mat_Shell*)A->data;
1388fe8eb27SJed Brown   PetscErrorCode ierr;
1398fe8eb27SJed Brown 
1408fe8eb27SJed Brown   PetscFunctionBegin;
1418fe8eb27SJed Brown   if (shell->right) {ierr = VecPointwiseMult(x,x,shell->right);CHKERRQ(ierr);}
1428fe8eb27SJed Brown   PetscFunctionReturn(0);
1438fe8eb27SJed Brown }
1448fe8eb27SJed Brown 
1458fe8eb27SJed Brown #undef __FUNCT__
1468fe8eb27SJed Brown #define __FUNCT__ "MatShellShiftAndScale"
1478fe8eb27SJed Brown static PetscErrorCode MatShellShiftAndScale(Mat A,Vec X,Vec Y)
1488fe8eb27SJed Brown {
1498fe8eb27SJed Brown   Mat_Shell      *shell = (Mat_Shell*)A->data;
1508fe8eb27SJed Brown   PetscErrorCode ierr;
1518fe8eb27SJed Brown 
1528fe8eb27SJed Brown   PetscFunctionBegin;
1538fe8eb27SJed Brown   if (shell->dshift) {          /* get arrays because there is no VecPointwiseMultAdd() */
1548fe8eb27SJed Brown     PetscInt          i,m;
1558fe8eb27SJed Brown     const PetscScalar *x,*d;
1568fe8eb27SJed Brown     PetscScalar       *y;
1578fe8eb27SJed Brown     ierr = VecGetLocalSize(X,&m);CHKERRQ(ierr);
1588fe8eb27SJed Brown     ierr = VecGetArrayRead(shell->dshift,&d);CHKERRQ(ierr);
1598fe8eb27SJed Brown     ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1608fe8eb27SJed Brown     ierr = VecGetArray(Y,&y);CHKERRQ(ierr);
1618fe8eb27SJed Brown     for (i=0; i<m; i++) y[i] = shell->vscale*y[i] + d[i]*x[i];
1628fe8eb27SJed Brown     ierr = VecRestoreArrayRead(shell->dshift,&d);CHKERRQ(ierr);
1638fe8eb27SJed Brown     ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1648fe8eb27SJed Brown     ierr = VecRestoreArray(Y,&y);CHKERRQ(ierr);
165880538faSHong Zhang   } else if (PetscAbsScalar(shell->vshift) != 0) {
1668fe8eb27SJed Brown     ierr = VecAXPBY(Y,shell->vshift,shell->vscale,X);CHKERRQ(ierr);
167027c5fb5SJed Brown   } else if (shell->vscale != 1.0) {
168027c5fb5SJed Brown     ierr = VecScale(Y,shell->vscale);CHKERRQ(ierr);
1698fe8eb27SJed Brown   }
1708fe8eb27SJed Brown   PetscFunctionReturn(0);
1718fe8eb27SJed Brown }
172e51e0e81SBarry Smith 
173711e205bSSatish Balay #undef __FUNCT__
174711e205bSSatish Balay #define __FUNCT__ "MatShellGetContext"
1759d225801SJed Brown /*@
176a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
177b4fd4287SBarry Smith 
178c7fcc2eaSBarry Smith     Not Collective
179c7fcc2eaSBarry Smith 
180b4fd4287SBarry Smith     Input Parameter:
181b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
182b4fd4287SBarry Smith 
183b4fd4287SBarry Smith     Output Parameter:
184b4fd4287SBarry Smith .   ctx - the user provided context
185b4fd4287SBarry Smith 
18615091d37SBarry Smith     Level: advanced
18715091d37SBarry Smith 
188*daf670e6SBarry Smith    Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
189*daf670e6SBarry Smith     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
190a62d957aSLois Curfman McInnes 
191a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
192a62d957aSLois Curfman McInnes 
193ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellSetOperation(), MatShellSetContext()
1940bc0a719SBarry Smith @*/
1958fe8eb27SJed Brown PetscErrorCode  MatShellGetContext(Mat mat,void *ctx)
196b4fd4287SBarry Smith {
197dfbe8321SBarry Smith   PetscErrorCode ierr;
198ace3abfcSBarry Smith   PetscBool      flg;
199273d9f13SBarry Smith 
2003a40ed3dSBarry Smith   PetscFunctionBegin;
2010700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2024482741eSBarry Smith   PetscValidPointer(ctx,2);
203251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
204940183f3SBarry Smith   if (flg) *(void**)ctx = ((Mat_Shell*)(mat->data))->ctx;
205ce94432eSBarry Smith   else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot get context from non-shell matrix");
2063a40ed3dSBarry Smith   PetscFunctionReturn(0);
207b4fd4287SBarry Smith }
208b4fd4287SBarry Smith 
209711e205bSSatish Balay #undef __FUNCT__
210711e205bSSatish Balay #define __FUNCT__ "MatDestroy_Shell"
211dfbe8321SBarry Smith PetscErrorCode MatDestroy_Shell(Mat mat)
212e51e0e81SBarry Smith {
213dfbe8321SBarry Smith   PetscErrorCode ierr;
214bf0cc555SLisandro Dalcin   Mat_Shell      *shell = (Mat_Shell*)mat->data;
215ed3cc1f0SBarry Smith 
2163a40ed3dSBarry Smith   PetscFunctionBegin;
217bf0cc555SLisandro Dalcin   if (shell->destroy) {
218bf0cc555SLisandro Dalcin     ierr = (*shell->destroy)(mat);CHKERRQ(ierr);
219bf0cc555SLisandro Dalcin   }
2208fe8eb27SJed Brown   ierr = VecDestroy(&shell->left_owned);CHKERRQ(ierr);
2218fe8eb27SJed Brown   ierr = VecDestroy(&shell->right_owned);CHKERRQ(ierr);
2228fe8eb27SJed Brown   ierr = VecDestroy(&shell->dshift_owned);CHKERRQ(ierr);
2238fe8eb27SJed Brown   ierr = VecDestroy(&shell->left_work);CHKERRQ(ierr);
2248fe8eb27SJed Brown   ierr = VecDestroy(&shell->right_work);CHKERRQ(ierr);
2255edf6516SJed Brown   ierr = VecDestroy(&shell->left_add_work);CHKERRQ(ierr);
2265edf6516SJed Brown   ierr = VecDestroy(&shell->right_add_work);CHKERRQ(ierr);
227bf0cc555SLisandro Dalcin   ierr = PetscFree(mat->data);CHKERRQ(ierr);
2283a40ed3dSBarry Smith   PetscFunctionReturn(0);
229e51e0e81SBarry Smith }
230e51e0e81SBarry Smith 
231711e205bSSatish Balay #undef __FUNCT__
232ef66eb69SBarry Smith #define __FUNCT__ "MatMult_Shell"
233dfbe8321SBarry Smith PetscErrorCode MatMult_Shell(Mat A,Vec x,Vec y)
234ef66eb69SBarry Smith {
235ef66eb69SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)A->data;
236dfbe8321SBarry Smith   PetscErrorCode ierr;
23725578ef6SJed Brown   Vec            xx;
238ef66eb69SBarry Smith 
239ef66eb69SBarry Smith   PetscFunctionBegin;
2408fe8eb27SJed Brown   ierr = MatShellPreScaleRight(A,x,&xx);CHKERRQ(ierr);
2418fe8eb27SJed Brown   ierr = (*shell->mult)(A,xx,y);CHKERRQ(ierr);
2428fe8eb27SJed Brown   ierr = MatShellShiftAndScale(A,xx,y);CHKERRQ(ierr);
2438fe8eb27SJed Brown   ierr = MatShellPostScaleLeft(A,y);CHKERRQ(ierr);
244ef66eb69SBarry Smith   PetscFunctionReturn(0);
245ef66eb69SBarry Smith }
246ef66eb69SBarry Smith 
247ef66eb69SBarry Smith #undef __FUNCT__
2485edf6516SJed Brown #define __FUNCT__ "MatMultAdd_Shell"
2495edf6516SJed Brown PetscErrorCode MatMultAdd_Shell(Mat A,Vec x,Vec y,Vec z)
2505edf6516SJed Brown {
2515edf6516SJed Brown   Mat_Shell      *shell = (Mat_Shell*)A->data;
2525edf6516SJed Brown   PetscErrorCode ierr;
2535edf6516SJed Brown 
2545edf6516SJed Brown   PetscFunctionBegin;
2555edf6516SJed Brown   if (y == z) {
2565edf6516SJed Brown     if (!shell->right_add_work) {ierr = VecDuplicate(z,&shell->right_add_work);CHKERRQ(ierr);}
2575edf6516SJed Brown     ierr = MatMult(A,x,shell->right_add_work);CHKERRQ(ierr);
258b8430d49SBarry Smith     ierr = VecAXPY(z,1.0,shell->right_add_work);CHKERRQ(ierr);
2595edf6516SJed Brown   } else {
2605edf6516SJed Brown     ierr = MatMult(A,x,z);CHKERRQ(ierr);
2615edf6516SJed Brown     ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr);
2625edf6516SJed Brown   }
2635edf6516SJed Brown   PetscFunctionReturn(0);
2645edf6516SJed Brown }
2655edf6516SJed Brown 
2665edf6516SJed Brown #undef __FUNCT__
26718be62a5SSatish Balay #define __FUNCT__ "MatMultTranspose_Shell"
26818be62a5SSatish Balay PetscErrorCode MatMultTranspose_Shell(Mat A,Vec x,Vec y)
26918be62a5SSatish Balay {
27018be62a5SSatish Balay   Mat_Shell      *shell = (Mat_Shell*)A->data;
27118be62a5SSatish Balay   PetscErrorCode ierr;
27225578ef6SJed Brown   Vec            xx;
27318be62a5SSatish Balay 
27418be62a5SSatish Balay   PetscFunctionBegin;
2758fe8eb27SJed Brown   ierr = MatShellPreScaleLeft(A,x,&xx);CHKERRQ(ierr);
2768fe8eb27SJed Brown   ierr = (*shell->multtranspose)(A,xx,y);CHKERRQ(ierr);
2778fe8eb27SJed Brown   ierr = MatShellShiftAndScale(A,xx,y);CHKERRQ(ierr);
2788fe8eb27SJed Brown   ierr = MatShellPostScaleRight(A,y);CHKERRQ(ierr);
27918be62a5SSatish Balay   PetscFunctionReturn(0);
28018be62a5SSatish Balay }
28118be62a5SSatish Balay 
28218be62a5SSatish Balay #undef __FUNCT__
2835edf6516SJed Brown #define __FUNCT__ "MatMultTransposeAdd_Shell"
2845edf6516SJed Brown PetscErrorCode MatMultTransposeAdd_Shell(Mat A,Vec x,Vec y,Vec z)
2855edf6516SJed Brown {
2865edf6516SJed Brown   Mat_Shell      *shell = (Mat_Shell*)A->data;
2875edf6516SJed Brown   PetscErrorCode ierr;
2885edf6516SJed Brown 
2895edf6516SJed Brown   PetscFunctionBegin;
2905edf6516SJed Brown   if (y == z) {
2915edf6516SJed Brown     if (!shell->left_add_work) {ierr = VecDuplicate(z,&shell->left_add_work);CHKERRQ(ierr);}
2925edf6516SJed Brown     ierr = MatMultTranspose(A,x,shell->left_add_work);CHKERRQ(ierr);
2935edf6516SJed Brown     ierr = VecWAXPY(z,1.0,shell->left_add_work,y);CHKERRQ(ierr);
2945edf6516SJed Brown   } else {
2955edf6516SJed Brown     ierr = MatMultTranspose(A,x,z);CHKERRQ(ierr);
2965edf6516SJed Brown     ierr = VecAXPY(z,1.0,y);CHKERRQ(ierr);
2975edf6516SJed Brown   }
2985edf6516SJed Brown   PetscFunctionReturn(0);
2995edf6516SJed Brown }
3005edf6516SJed Brown 
3015edf6516SJed Brown #undef __FUNCT__
30218be62a5SSatish Balay #define __FUNCT__ "MatGetDiagonal_Shell"
30318be62a5SSatish Balay PetscErrorCode MatGetDiagonal_Shell(Mat A,Vec v)
30418be62a5SSatish Balay {
30518be62a5SSatish Balay   Mat_Shell      *shell = (Mat_Shell*)A->data;
30618be62a5SSatish Balay   PetscErrorCode ierr;
30718be62a5SSatish Balay 
30818be62a5SSatish Balay   PetscFunctionBegin;
30918be62a5SSatish Balay   ierr = (*shell->getdiagonal)(A,v);CHKERRQ(ierr);
31018be62a5SSatish Balay   ierr = VecScale(v,shell->vscale);CHKERRQ(ierr);
3118fe8eb27SJed Brown   if (shell->dshift) {
3128fe8eb27SJed Brown     ierr = VecPointwiseMult(v,v,shell->dshift);CHKERRQ(ierr);
3138fe8eb27SJed Brown   } else {
31418be62a5SSatish Balay     ierr = VecShift(v,shell->vshift);CHKERRQ(ierr);
31518be62a5SSatish Balay   }
3168fe8eb27SJed Brown   if (shell->left)  {ierr = VecPointwiseMult(v,v,shell->left);CHKERRQ(ierr);}
3178fe8eb27SJed Brown   if (shell->right) {ierr = VecPointwiseMult(v,v,shell->right);CHKERRQ(ierr);}
31818be62a5SSatish Balay   PetscFunctionReturn(0);
31918be62a5SSatish Balay }
32018be62a5SSatish Balay 
32118be62a5SSatish Balay #undef __FUNCT__
322ef66eb69SBarry Smith #define __FUNCT__ "MatShift_Shell"
323f4df32b1SMatthew Knepley PetscErrorCode MatShift_Shell(Mat Y,PetscScalar a)
324ef66eb69SBarry Smith {
325ef66eb69SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)Y->data;
3268fe8eb27SJed Brown   PetscErrorCode ierr;
327b24ad042SBarry Smith 
328ef66eb69SBarry Smith   PetscFunctionBegin;
3298fe8eb27SJed Brown   if (shell->left || shell->right || shell->dshift) {
3308fe8eb27SJed Brown     if (!shell->dshift) {
3318fe8eb27SJed Brown       if (!shell->dshift_owned) {ierr = VecDuplicate(shell->left ? shell->left : shell->right, &shell->dshift_owned);CHKERRQ(ierr);}
3328fe8eb27SJed Brown       shell->dshift = shell->dshift_owned;
3338fe8eb27SJed Brown       ierr          = VecSet(shell->dshift,shell->vshift+a);CHKERRQ(ierr);
3348fe8eb27SJed Brown     } else {ierr = VecScale(shell->dshift,a);CHKERRQ(ierr);}
3358fe8eb27SJed Brown     if (shell->left)  {ierr = VecPointwiseDivide(shell->dshift,shell->dshift,shell->left);CHKERRQ(ierr);}
3368fe8eb27SJed Brown     if (shell->right) {ierr = VecPointwiseDivide(shell->dshift,shell->dshift,shell->right);CHKERRQ(ierr);}
3378fe8eb27SJed Brown   } else shell->vshift += a;
3388fe8eb27SJed Brown   ierr = MatShellUseScaledMethods(Y);CHKERRQ(ierr);
339ef66eb69SBarry Smith   PetscFunctionReturn(0);
340ef66eb69SBarry Smith }
341ef66eb69SBarry Smith 
342ef66eb69SBarry Smith #undef __FUNCT__
343ef66eb69SBarry Smith #define __FUNCT__ "MatScale_Shell"
344f4df32b1SMatthew Knepley PetscErrorCode MatScale_Shell(Mat Y,PetscScalar a)
345ef66eb69SBarry Smith {
346ef66eb69SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)Y->data;
3478fe8eb27SJed Brown   PetscErrorCode ierr;
348b24ad042SBarry Smith 
349ef66eb69SBarry Smith   PetscFunctionBegin;
350f4df32b1SMatthew Knepley   shell->vscale *= a;
3512205254eSKarl Rupp   if (shell->dshift) {
3522205254eSKarl Rupp     ierr = VecScale(shell->dshift,a);CHKERRQ(ierr);
3532205254eSKarl Rupp   } else shell->vshift *= a;
3548fe8eb27SJed Brown   ierr = MatShellUseScaledMethods(Y);CHKERRQ(ierr);
3558fe8eb27SJed Brown   PetscFunctionReturn(0);
35618be62a5SSatish Balay }
3578fe8eb27SJed Brown 
3588fe8eb27SJed Brown #undef __FUNCT__
3598fe8eb27SJed Brown #define __FUNCT__ "MatDiagonalScale_Shell"
3608fe8eb27SJed Brown static PetscErrorCode MatDiagonalScale_Shell(Mat Y,Vec left,Vec right)
3618fe8eb27SJed Brown {
3628fe8eb27SJed Brown   Mat_Shell      *shell = (Mat_Shell*)Y->data;
3638fe8eb27SJed Brown   PetscErrorCode ierr;
3648fe8eb27SJed Brown 
3658fe8eb27SJed Brown   PetscFunctionBegin;
3668fe8eb27SJed Brown   if (left) {
3678fe8eb27SJed Brown     if (!shell->left_owned) {ierr = VecDuplicate(left,&shell->left_owned);CHKERRQ(ierr);}
3682205254eSKarl Rupp     if (shell->left) {
3692205254eSKarl Rupp       ierr = VecPointwiseMult(shell->left,shell->left,left);CHKERRQ(ierr);
3702205254eSKarl Rupp     } else {
3718fe8eb27SJed Brown       shell->left = shell->left_owned;
3728fe8eb27SJed Brown       ierr        = VecCopy(left,shell->left);CHKERRQ(ierr);
37318be62a5SSatish Balay     }
374ef66eb69SBarry Smith   }
3758fe8eb27SJed Brown   if (right) {
3768fe8eb27SJed Brown     if (!shell->right_owned) {ierr = VecDuplicate(right,&shell->right_owned);CHKERRQ(ierr);}
3772205254eSKarl Rupp     if (shell->right) {
3782205254eSKarl Rupp       ierr = VecPointwiseMult(shell->right,shell->right,right);CHKERRQ(ierr);
3792205254eSKarl Rupp     } else {
3808fe8eb27SJed Brown       shell->right = shell->right_owned;
3818fe8eb27SJed Brown       ierr         = VecCopy(right,shell->right);CHKERRQ(ierr);
3828fe8eb27SJed Brown     }
3838fe8eb27SJed Brown   }
3848fe8eb27SJed Brown   ierr = MatShellUseScaledMethods(Y);CHKERRQ(ierr);
385ef66eb69SBarry Smith   PetscFunctionReturn(0);
386ef66eb69SBarry Smith }
387ef66eb69SBarry Smith 
388ef66eb69SBarry Smith #undef __FUNCT__
389ef66eb69SBarry Smith #define __FUNCT__ "MatAssemblyEnd_Shell"
390dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_Shell(Mat Y,MatAssemblyType t)
391ef66eb69SBarry Smith {
392ef66eb69SBarry Smith   Mat_Shell *shell = (Mat_Shell*)Y->data;
393ef66eb69SBarry Smith 
394ef66eb69SBarry Smith   PetscFunctionBegin;
3958fe8eb27SJed Brown   if (t == MAT_FINAL_ASSEMBLY) {
396ef66eb69SBarry Smith     shell->vshift = 0.0;
397ef66eb69SBarry Smith     shell->vscale = 1.0;
3980298fd71SBarry Smith     shell->dshift = NULL;
3990298fd71SBarry Smith     shell->left   = NULL;
4000298fd71SBarry Smith     shell->right  = NULL;
4017fb7d96aSJed Brown     if (shell->mult) {
402ef66eb69SBarry Smith       Y->ops->mult = shell->mult;
4030298fd71SBarry Smith       shell->mult  = NULL;
4047fb7d96aSJed Brown     }
4057fb7d96aSJed Brown     if (shell->multtranspose) {
40618be62a5SSatish Balay       Y->ops->multtranspose = shell->multtranspose;
4070298fd71SBarry Smith       shell->multtranspose  = NULL;
4087fb7d96aSJed Brown     }
4097fb7d96aSJed Brown     if (shell->getdiagonal) {
41018be62a5SSatish Balay       Y->ops->getdiagonal = shell->getdiagonal;
4110298fd71SBarry Smith       shell->getdiagonal  = NULL;
4127fb7d96aSJed Brown     }
4137fb7d96aSJed Brown     shell->usingscaled = PETSC_FALSE;
414ef66eb69SBarry Smith   }
415ef66eb69SBarry Smith   PetscFunctionReturn(0);
416ef66eb69SBarry Smith }
417ef66eb69SBarry Smith 
41819fd82e9SBarry Smith extern PetscErrorCode MatConvert_Shell(Mat, MatType,MatReuse,Mat*);
419b951964fSBarry Smith 
42009dc0095SBarry Smith static struct _MatOps MatOps_Values = {0,
42120563c6bSBarry Smith                                        0,
42220563c6bSBarry Smith                                        0,
42320563c6bSBarry Smith                                        0,
42497304618SKris Buschelman                                 /* 4*/ 0,
42520563c6bSBarry Smith                                        0,
426b951964fSBarry Smith                                        0,
427b951964fSBarry Smith                                        0,
428b951964fSBarry Smith                                        0,
429b951964fSBarry Smith                                        0,
43097304618SKris Buschelman                                 /*10*/ 0,
431b951964fSBarry Smith                                        0,
432b951964fSBarry Smith                                        0,
433b951964fSBarry Smith                                        0,
434b951964fSBarry Smith                                        0,
43597304618SKris Buschelman                                 /*15*/ 0,
436b951964fSBarry Smith                                        0,
437b951964fSBarry Smith                                        0,
4388fe8eb27SJed Brown                                        MatDiagonalScale_Shell,
439b951964fSBarry Smith                                        0,
44097304618SKris Buschelman                                 /*20*/ 0,
441ef66eb69SBarry Smith                                        MatAssemblyEnd_Shell,
442b951964fSBarry Smith                                        0,
443b951964fSBarry Smith                                        0,
444d519adbfSMatthew Knepley                                 /*24*/ 0,
445b951964fSBarry Smith                                        0,
446b951964fSBarry Smith                                        0,
447b951964fSBarry Smith                                        0,
448b951964fSBarry Smith                                        0,
449d519adbfSMatthew Knepley                                 /*29*/ 0,
450b951964fSBarry Smith                                        0,
451273d9f13SBarry Smith                                        0,
452b951964fSBarry Smith                                        0,
453b951964fSBarry Smith                                        0,
454d519adbfSMatthew Knepley                                 /*34*/ 0,
455b951964fSBarry Smith                                        0,
456b951964fSBarry Smith                                        0,
45709dc0095SBarry Smith                                        0,
45809dc0095SBarry Smith                                        0,
459d519adbfSMatthew Knepley                                 /*39*/ 0,
46009dc0095SBarry Smith                                        0,
46109dc0095SBarry Smith                                        0,
46209dc0095SBarry Smith                                        0,
46309dc0095SBarry Smith                                        0,
464d519adbfSMatthew Knepley                                 /*44*/ 0,
465ef66eb69SBarry Smith                                        MatScale_Shell,
466ef66eb69SBarry Smith                                        MatShift_Shell,
46709dc0095SBarry Smith                                        0,
46809dc0095SBarry Smith                                        0,
469f73d5cc4SBarry Smith                                 /*49*/ 0,
47009dc0095SBarry Smith                                        0,
47109dc0095SBarry Smith                                        0,
47209dc0095SBarry Smith                                        0,
47309dc0095SBarry Smith                                        0,
474d519adbfSMatthew Knepley                                 /*54*/ 0,
47509dc0095SBarry Smith                                        0,
47609dc0095SBarry Smith                                        0,
47709dc0095SBarry Smith                                        0,
47809dc0095SBarry Smith                                        0,
479d519adbfSMatthew Knepley                                 /*59*/ 0,
480b9b97703SBarry Smith                                        MatDestroy_Shell,
48109dc0095SBarry Smith                                        0,
482357abbc8SBarry Smith                                        0,
483273d9f13SBarry Smith                                        0,
484d519adbfSMatthew Knepley                                 /*64*/ 0,
485273d9f13SBarry Smith                                        0,
486273d9f13SBarry Smith                                        0,
487273d9f13SBarry Smith                                        0,
488273d9f13SBarry Smith                                        0,
489d519adbfSMatthew Knepley                                 /*69*/ 0,
490273d9f13SBarry Smith                                        0,
491c87e5d42SMatthew Knepley                                        MatConvert_Shell,
492273d9f13SBarry Smith                                        0,
49397304618SKris Buschelman                                        0,
494d519adbfSMatthew Knepley                                 /*74*/ 0,
49597304618SKris Buschelman                                        0,
49697304618SKris Buschelman                                        0,
49797304618SKris Buschelman                                        0,
49897304618SKris Buschelman                                        0,
499d519adbfSMatthew Knepley                                 /*79*/ 0,
50097304618SKris Buschelman                                        0,
50197304618SKris Buschelman                                        0,
50297304618SKris Buschelman                                        0,
503865e5f61SKris Buschelman                                        0,
504d519adbfSMatthew Knepley                                 /*84*/ 0,
505865e5f61SKris Buschelman                                        0,
506865e5f61SKris Buschelman                                        0,
507865e5f61SKris Buschelman                                        0,
508865e5f61SKris Buschelman                                        0,
509d519adbfSMatthew Knepley                                 /*89*/ 0,
510865e5f61SKris Buschelman                                        0,
511865e5f61SKris Buschelman                                        0,
512865e5f61SKris Buschelman                                        0,
513865e5f61SKris Buschelman                                        0,
514d519adbfSMatthew Knepley                                 /*94*/ 0,
515865e5f61SKris Buschelman                                        0,
516865e5f61SKris Buschelman                                        0,
5173964eb88SJed Brown                                        0,
5183964eb88SJed Brown                                        0,
5193964eb88SJed Brown                                 /*99*/ 0,
5203964eb88SJed Brown                                        0,
5213964eb88SJed Brown                                        0,
5223964eb88SJed Brown                                        0,
5233964eb88SJed Brown                                        0,
5243964eb88SJed Brown                                /*104*/ 0,
5253964eb88SJed Brown                                        0,
5263964eb88SJed Brown                                        0,
5273964eb88SJed Brown                                        0,
5283964eb88SJed Brown                                        0,
5293964eb88SJed Brown                                /*109*/ 0,
5303964eb88SJed Brown                                        0,
5313964eb88SJed Brown                                        0,
5323964eb88SJed Brown                                        0,
5333964eb88SJed Brown                                        0,
5343964eb88SJed Brown                                /*114*/ 0,
5353964eb88SJed Brown                                        0,
5363964eb88SJed Brown                                        0,
5373964eb88SJed Brown                                        0,
5383964eb88SJed Brown                                        0,
5393964eb88SJed Brown                                /*119*/ 0,
5403964eb88SJed Brown                                        0,
5413964eb88SJed Brown                                        0,
5423964eb88SJed Brown                                        0,
5433964eb88SJed Brown                                        0,
5443964eb88SJed Brown                                /*124*/ 0,
5453964eb88SJed Brown                                        0,
5463964eb88SJed Brown                                        0,
5473964eb88SJed Brown                                        0,
5483964eb88SJed Brown                                        0,
5493964eb88SJed Brown                                /*129*/ 0,
5503964eb88SJed Brown                                        0,
5513964eb88SJed Brown                                        0,
5523964eb88SJed Brown                                        0,
5533964eb88SJed Brown                                        0,
5543964eb88SJed Brown                                /*134*/ 0,
5553964eb88SJed Brown                                        0,
5563964eb88SJed Brown                                        0,
5573964eb88SJed Brown                                        0,
5583964eb88SJed Brown                                        0,
5593964eb88SJed Brown                                /*139*/ 0,
560f9426fe0SMark Adams                                        0,
5613964eb88SJed Brown                                        0
5623964eb88SJed Brown };
563273d9f13SBarry Smith 
5640bad9183SKris Buschelman /*MC
565fafad747SKris Buschelman    MATSHELL - MATSHELL = "shell" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
5660bad9183SKris Buschelman 
5670bad9183SKris Buschelman   Level: advanced
5680bad9183SKris Buschelman 
5690bad9183SKris Buschelman .seealso: MatCreateShell
5700bad9183SKris Buschelman M*/
5710bad9183SKris Buschelman 
572711e205bSSatish Balay #undef __FUNCT__
573711e205bSSatish Balay #define __FUNCT__ "MatCreate_Shell"
5748cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Shell(Mat A)
575273d9f13SBarry Smith {
576273d9f13SBarry Smith   Mat_Shell      *b;
577dfbe8321SBarry Smith   PetscErrorCode ierr;
578273d9f13SBarry Smith 
579273d9f13SBarry Smith   PetscFunctionBegin;
580273d9f13SBarry Smith   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
581273d9f13SBarry Smith 
582b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
583273d9f13SBarry Smith   A->data = (void*)b;
584273d9f13SBarry Smith 
58526283091SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
58626283091SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
587273d9f13SBarry Smith 
588273d9f13SBarry Smith   b->ctx           = 0;
589ef66eb69SBarry Smith   b->vshift        = 0.0;
590ef66eb69SBarry Smith   b->vscale        = 1.0;
591ef66eb69SBarry Smith   b->mult          = 0;
59218be62a5SSatish Balay   b->multtranspose = 0;
59318be62a5SSatish Balay   b->getdiagonal   = 0;
594273d9f13SBarry Smith   A->assembled     = PETSC_TRUE;
595210f0121SBarry Smith   A->preallocated  = PETSC_FALSE;
5962205254eSKarl Rupp 
59717667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSHELL);CHKERRQ(ierr);
598273d9f13SBarry Smith   PetscFunctionReturn(0);
599273d9f13SBarry Smith }
600e51e0e81SBarry Smith 
601711e205bSSatish Balay #undef __FUNCT__
602711e205bSSatish Balay #define __FUNCT__ "MatCreateShell"
6034b828684SBarry Smith /*@C
604052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
605ff756334SLois Curfman McInnes    private data storage format.
606e51e0e81SBarry Smith 
607c7fcc2eaSBarry Smith   Collective on MPI_Comm
608c7fcc2eaSBarry Smith 
609e51e0e81SBarry Smith    Input Parameters:
610c7fcc2eaSBarry Smith +  comm - MPI communicator
611c7fcc2eaSBarry Smith .  m - number of local rows (must be given)
612c7fcc2eaSBarry Smith .  n - number of local columns (must be given)
613c7fcc2eaSBarry Smith .  M - number of global rows (may be PETSC_DETERMINE)
614c7fcc2eaSBarry Smith .  N - number of global columns (may be PETSC_DETERMINE)
615c7fcc2eaSBarry Smith -  ctx - pointer to data needed by the shell matrix routines
616e51e0e81SBarry Smith 
617ff756334SLois Curfman McInnes    Output Parameter:
61844cd7ae7SLois Curfman McInnes .  A - the matrix
619e51e0e81SBarry Smith 
620ff2fd236SBarry Smith    Level: advanced
621ff2fd236SBarry Smith 
622f39d1f56SLois Curfman McInnes   Usage:
6237b2a1423SBarry Smith $    extern int mult(Mat,Vec,Vec);
624f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
625c134de8dSSatish Balay $    MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
626f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
627f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
628f39d1f56SLois Curfman McInnes 
629ff756334SLois Curfman McInnes    Notes:
630ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
631ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
632ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
633e51e0e81SBarry Smith 
634*daf670e6SBarry Smith    Fortran Notes: To use this from Fortran with a ctx you must write an interface definition for this
635*daf670e6SBarry Smith     function and for MatShellGetContext() that tells Fortran the Fortran derived data type you are passing
636*daf670e6SBarry Smith     in as the ctx argument.
637f38a8d56SBarry Smith 
638f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
639f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
640645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
641645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
642645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
643645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
644645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
645645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
646645985a0SLois Curfman McInnes    For example,
647f39d1f56SLois Curfman McInnes 
648f39d1f56SLois Curfman McInnes $
649f39d1f56SLois Curfman McInnes $     Vec x, y
6507b2a1423SBarry Smith $     extern int mult(Mat,Vec,Vec);
651645985a0SLois Curfman McInnes $     Mat A
652f39d1f56SLois Curfman McInnes $
653c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,M,&y);
654c94f878dSBarry Smith $     VecCreateMPI(comm,PETSC_DECIDE,N,&x);
655f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
656c7fcc2eaSBarry Smith $     VecGetLocalSize(x,&n);
657c7fcc2eaSBarry Smith $     MatCreateShell(comm,m,n,M,N,ctx,&A);
658c134de8dSSatish Balay $     MatShellSetOperation(mat,MATOP_MULT,(void(*)(void))mult);
659645985a0SLois Curfman McInnes $     MatMult(A,x,y);
660645985a0SLois Curfman McInnes $     MatDestroy(A);
661f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
662645985a0SLois Curfman McInnes $
663e51e0e81SBarry Smith 
6640b627109SLois Curfman McInnes .keywords: matrix, shell, create
6650b627109SLois Curfman McInnes 
666ab50ec6bSBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext(), MatShellSetContext()
667e51e0e81SBarry Smith @*/
6687087cfbeSBarry Smith PetscErrorCode  MatCreateShell(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,void *ctx,Mat *A)
669e51e0e81SBarry Smith {
670dfbe8321SBarry Smith   PetscErrorCode ierr;
671ed3cc1f0SBarry Smith 
6723a40ed3dSBarry Smith   PetscFunctionBegin;
673f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
674f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
675273d9f13SBarry Smith   ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr);
676273d9f13SBarry Smith   ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr);
6770fcd0fccSJed Brown   ierr = MatSetUp(*A);CHKERRQ(ierr);
678273d9f13SBarry Smith   PetscFunctionReturn(0);
679c7fcc2eaSBarry Smith }
680c7fcc2eaSBarry Smith 
681711e205bSSatish Balay #undef __FUNCT__
682711e205bSSatish Balay #define __FUNCT__ "MatShellSetContext"
683c6866cfdSSatish Balay /*@
684273d9f13SBarry Smith     MatShellSetContext - sets the context for a shell matrix
685c7fcc2eaSBarry Smith 
6863f9fe445SBarry Smith    Logically Collective on Mat
687c7fcc2eaSBarry Smith 
688273d9f13SBarry Smith     Input Parameters:
689273d9f13SBarry Smith +   mat - the shell matrix
690273d9f13SBarry Smith -   ctx - the context
691273d9f13SBarry Smith 
692273d9f13SBarry Smith    Level: advanced
693273d9f13SBarry Smith 
694*daf670e6SBarry Smith    Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
695*daf670e6SBarry Smith     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
696273d9f13SBarry Smith 
697273d9f13SBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
6980bc0a719SBarry Smith @*/
6997087cfbeSBarry Smith PetscErrorCode  MatShellSetContext(Mat mat,void *ctx)
700273d9f13SBarry Smith {
701273d9f13SBarry Smith   Mat_Shell      *shell = (Mat_Shell*)mat->data;
702dfbe8321SBarry Smith   PetscErrorCode ierr;
703ace3abfcSBarry Smith   PetscBool      flg;
704273d9f13SBarry Smith 
705273d9f13SBarry Smith   PetscFunctionBegin;
7060700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
707251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
708273d9f13SBarry Smith   if (flg) {
709273d9f13SBarry Smith     shell->ctx = ctx;
710ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot attach context to non-shell matrix");
7113a40ed3dSBarry Smith   PetscFunctionReturn(0);
712e51e0e81SBarry Smith }
713e51e0e81SBarry Smith 
714711e205bSSatish Balay #undef __FUNCT__
715711e205bSSatish Balay #define __FUNCT__ "MatShellSetOperation"
716c16cb8f2SBarry Smith /*@C
7173a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
7183a3eedf2SBarry Smith                            a shell matrix.
719e51e0e81SBarry Smith 
7203f9fe445SBarry Smith    Logically Collective on Mat
721fee21e36SBarry Smith 
722c7fcc2eaSBarry Smith     Input Parameters:
723c7fcc2eaSBarry Smith +   mat - the shell matrix
724c7fcc2eaSBarry Smith .   op - the name of the operation
725c7fcc2eaSBarry Smith -   f - the function that provides the operation.
726c7fcc2eaSBarry Smith 
72715091d37SBarry Smith    Level: advanced
72815091d37SBarry Smith 
729fae171e0SBarry Smith     Usage:
730e93bc3c1Svictor $      extern PetscErrorCode usermult(Mat,Vec,Vec);
731f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
732c134de8dSSatish Balay $      ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
7330b627109SLois Curfman McInnes 
734a62d957aSLois Curfman McInnes     Notes:
735e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
7361c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
737a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
7381c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
739a62d957aSLois Curfman McInnes 
74025296bd5SBarry Smith     All user-provided functions (execept for MATOP_DESTROY) should have the same calling
741deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
742deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
743deebb3c3SLois Curfman McInnes     routines, e.g.,
744a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
745a62d957aSLois Curfman McInnes 
7464aa34b0aSBarry Smith     In particular each function MUST return an error code of 0 on success and
7474aa34b0aSBarry Smith     nonzero on failure.
7484aa34b0aSBarry Smith 
749a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
750a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
751a62d957aSLois Curfman McInnes     set by MatCreateShell().
752a62d957aSLois Curfman McInnes 
7532a7a6963SBarry Smith     Fortran Notes: For MatCreateVecs() the user code should check if the input left or right matrix is -1 and in that case not
754501d9185SBarry Smith        generate a matrix. See src/mat/examples/tests/ex120f.F
755501d9185SBarry Smith 
756a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
757a62d957aSLois Curfman McInnes 
758ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellSetContext()
759e51e0e81SBarry Smith @*/
7607087cfbeSBarry Smith PetscErrorCode  MatShellSetOperation(Mat mat,MatOperation op,void (*f)(void))
761e51e0e81SBarry Smith {
762dfbe8321SBarry Smith   PetscErrorCode ierr;
763ace3abfcSBarry Smith   PetscBool      flg;
764273d9f13SBarry Smith 
7653a40ed3dSBarry Smith   PetscFunctionBegin;
7660700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
7675edf6516SJed Brown   switch (op) {
7685edf6516SJed Brown   case MATOP_DESTROY:
769251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
770273d9f13SBarry Smith     if (flg) {
771a62d957aSLois Curfman McInnes       Mat_Shell *shell = (Mat_Shell*)mat->data;
7726849ba73SBarry Smith       shell->destroy = (PetscErrorCode (*)(Mat))f;
7736849ba73SBarry Smith     } else mat->ops->destroy = (PetscErrorCode (*)(Mat))f;
7745edf6516SJed Brown     break;
7755edf6516SJed Brown   case MATOP_VIEW:
7765edf6516SJed Brown     mat->ops->view = (PetscErrorCode (*)(Mat,PetscViewer))f;
7775edf6516SJed Brown     break;
7785edf6516SJed Brown   case MATOP_MULT:
7795edf6516SJed Brown     mat->ops->mult = (PetscErrorCode (*)(Mat,Vec,Vec))f;
7805edf6516SJed Brown     if (!mat->ops->multadd) mat->ops->multadd = MatMultAdd_Shell;
7815edf6516SJed Brown     break;
7825edf6516SJed Brown   case MATOP_MULT_TRANSPOSE:
7835edf6516SJed Brown     mat->ops->multtranspose = (PetscErrorCode (*)(Mat,Vec,Vec))f;
7845edf6516SJed Brown     if (!mat->ops->multtransposeadd) mat->ops->multtransposeadd = MatMultTransposeAdd_Shell;
7855edf6516SJed Brown     break;
7865edf6516SJed Brown   default:
7875edf6516SJed Brown     (((void(**)(void))mat->ops)[op]) = f;
788a62d957aSLois Curfman McInnes   }
7893a40ed3dSBarry Smith   PetscFunctionReturn(0);
790e51e0e81SBarry Smith }
791f0479e8cSBarry Smith 
792711e205bSSatish Balay #undef __FUNCT__
793711e205bSSatish Balay #define __FUNCT__ "MatShellGetOperation"
794d4bb536fSBarry Smith /*@C
795d4bb536fSBarry Smith     MatShellGetOperation - Gets a matrix function for a shell matrix.
796d4bb536fSBarry Smith 
797c7fcc2eaSBarry Smith     Not Collective
798c7fcc2eaSBarry Smith 
799d4bb536fSBarry Smith     Input Parameters:
800c7fcc2eaSBarry Smith +   mat - the shell matrix
801c7fcc2eaSBarry Smith -   op - the name of the operation
802d4bb536fSBarry Smith 
803d4bb536fSBarry Smith     Output Parameter:
804d4bb536fSBarry Smith .   f - the function that provides the operation.
805d4bb536fSBarry Smith 
80615091d37SBarry Smith     Level: advanced
80715091d37SBarry Smith 
808d4bb536fSBarry Smith     Notes:
809e090d566SSatish Balay     See the file include/petscmat.h for a complete list of matrix
810d4bb536fSBarry Smith     operations, which all have the form MATOP_<OPERATION>, where
811d4bb536fSBarry Smith     <OPERATION> is the name (in all capital letters) of the
812d4bb536fSBarry Smith     user interface routine (e.g., MatMult() -> MATOP_MULT).
813d4bb536fSBarry Smith 
814d4bb536fSBarry Smith     All user-provided functions have the same calling
815d4bb536fSBarry Smith     sequence as the usual matrix interface routines, since they
816d4bb536fSBarry Smith     are intended to be accessed via the usual matrix interface
817d4bb536fSBarry Smith     routines, e.g.,
818d4bb536fSBarry Smith $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
819d4bb536fSBarry Smith 
820d4bb536fSBarry Smith     Within each user-defined routine, the user should call
821d4bb536fSBarry Smith     MatShellGetContext() to obtain the user-defined context that was
822d4bb536fSBarry Smith     set by MatCreateShell().
823d4bb536fSBarry Smith 
824d4bb536fSBarry Smith .keywords: matrix, shell, set, operation
825d4bb536fSBarry Smith 
826ab50ec6bSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation(), MatShellSetContext()
827d4bb536fSBarry Smith @*/
8287087cfbeSBarry Smith PetscErrorCode  MatShellGetOperation(Mat mat,MatOperation op,void(**f)(void))
829d4bb536fSBarry Smith {
830dfbe8321SBarry Smith   PetscErrorCode ierr;
831ace3abfcSBarry Smith   PetscBool      flg;
832273d9f13SBarry Smith 
8333a40ed3dSBarry Smith   PetscFunctionBegin;
8340700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
835d4bb536fSBarry Smith   if (op == MATOP_DESTROY) {
836251f4c67SDmitry Karpeev     ierr = PetscObjectTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr);
837273d9f13SBarry Smith     if (flg) {
838d4bb536fSBarry Smith       Mat_Shell *shell = (Mat_Shell*)mat->data;
839c134de8dSSatish Balay       *f = (void (*)(void))shell->destroy;
840c7fcc2eaSBarry Smith     } else {
841c134de8dSSatish Balay       *f = (void (*)(void))mat->ops->destroy;
842d4bb536fSBarry Smith     }
843c7fcc2eaSBarry Smith   } else if (op == MATOP_VIEW) {
844c134de8dSSatish Balay     *f = (void (*)(void))mat->ops->view;
845c7fcc2eaSBarry Smith   } else {
846c134de8dSSatish Balay     *f = (((void (**)(void))mat->ops)[op]);
847d4bb536fSBarry Smith   }
8483a40ed3dSBarry Smith   PetscFunctionReturn(0);
849d4bb536fSBarry Smith }
850d4bb536fSBarry Smith 
851