1357feee3SLois Curfman McInnes #ifndef lint 2*f5eb4b81SSatish Balay static char vcid[] = "$Id: shell.c,v 1.35 1996/04/20 04:20:06 bsmith Exp balay $"; 3357feee3SLois Curfman McInnes #endif 4e51e0e81SBarry Smith 5e51e0e81SBarry Smith /* 620563c6bSBarry Smith This provides a simple shell for Fortran (and C programmers) to 720563c6bSBarry Smith create a very simple matrix class for use with KSP without coding 8ed3cc1f0SBarry Smith much of anything. 9e51e0e81SBarry Smith */ 10e51e0e81SBarry Smith 11e51e0e81SBarry Smith #include "petsc.h" 12e51e0e81SBarry Smith #include "matimpl.h" /*I "mat.h" I*/ 13*f5eb4b81SSatish Balay #include "src/vec/vecimpl.h" 14e51e0e81SBarry Smith 1520563c6bSBarry Smith typedef struct { 16f39d1f56SLois Curfman McInnes int M, N; /* number of global rows, columns */ 17f39d1f56SLois Curfman McInnes int m, n; /* number of local rows, columns */ 183a3eedf2SBarry Smith int (*destroy)(Mat); 1920563c6bSBarry Smith void *ctx; 2088cf3e7dSBarry Smith } Mat_Shell; 21e51e0e81SBarry Smith 22b4fd4287SBarry Smith /*@ 23a62d957aSLois Curfman McInnes MatShellGetContext - Returns the user-provided context associated with a shell matrix. 24b4fd4287SBarry Smith 25b4fd4287SBarry Smith Input Parameter: 26b4fd4287SBarry Smith . mat - the matrix, should have been created with MatCreateShell() 27b4fd4287SBarry Smith 28b4fd4287SBarry Smith Output Parameter: 29b4fd4287SBarry Smith . ctx - the user provided context 30b4fd4287SBarry Smith 31a62d957aSLois Curfman McInnes Notes: 32a62d957aSLois Curfman McInnes This routine is intended for use within various shell matrix routines, 33a62d957aSLois Curfman McInnes as set with MatShellSetOperation(). 34a62d957aSLois Curfman McInnes 35a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context 36a62d957aSLois Curfman McInnes 37a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation() 38b4fd4287SBarry Smith @*/ 39b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx) 40b4fd4287SBarry Smith { 4177c4ece6SBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 42b4fd4287SBarry Smith if (mat->type != MATSHELL) *ctx = 0; 43b4fd4287SBarry Smith else *ctx = ((Mat_Shell *) (mat->data))->ctx; 44b4fd4287SBarry Smith return 0; 45b4fd4287SBarry Smith } 46b4fd4287SBarry Smith 47f39d1f56SLois Curfman McInnes static int MatGetSize_Shell(Mat mat,int *M,int *N) 4871b459e3SLois Curfman McInnes { 4971b459e3SLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 50f39d1f56SLois Curfman McInnes *M = shell->M; *N = shell->N; 51f39d1f56SLois Curfman McInnes return 0; 52f39d1f56SLois Curfman McInnes } 53f39d1f56SLois Curfman McInnes 54f39d1f56SLois Curfman McInnes static int MatGetLocalSize_Shell(Mat mat,int *m,int *n) 55f39d1f56SLois Curfman McInnes { 56f39d1f56SLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 57f39d1f56SLois Curfman McInnes *m = shell->n; *n = shell->n; 5871b459e3SLois Curfman McInnes return 0; 5971b459e3SLois Curfman McInnes } 6071b459e3SLois Curfman McInnes 6188cf3e7dSBarry Smith static int MatDestroy_Shell(PetscObject obj) 62e51e0e81SBarry Smith { 63b9fa9cd0SBarry Smith int ierr; 6420563c6bSBarry Smith Mat mat = (Mat) obj; 6588cf3e7dSBarry Smith Mat_Shell *shell; 66ed3cc1f0SBarry Smith 6788cf3e7dSBarry Smith shell = (Mat_Shell *) mat->data; 683a3eedf2SBarry Smith if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);} 690452661fSBarry Smith PetscFree(shell); 703a3eedf2SBarry Smith PLogObjectDestroy(mat); 713a3eedf2SBarry Smith PetscHeaderDestroy(mat); 72e51e0e81SBarry Smith return 0; 73e51e0e81SBarry Smith } 74e51e0e81SBarry Smith 7520563c6bSBarry Smith static struct _MatOps MatOps = {0,0, 7620563c6bSBarry Smith 0, 77fae171e0SBarry Smith 0,0,0,0, 7820563c6bSBarry Smith 0,0,0,0, 7920563c6bSBarry Smith 0,0, 8020563c6bSBarry Smith 0, 8120563c6bSBarry Smith 0, 8220563c6bSBarry Smith 0,0,0, 8320563c6bSBarry Smith 0, 8420563c6bSBarry Smith 0,0,0, 8520563c6bSBarry Smith 0,0, 8620563c6bSBarry Smith 0, 8720563c6bSBarry Smith 0,0,0,0, 88f39d1f56SLois Curfman McInnes 0,0,MatGetSize_Shell,MatGetLocalSize_Shell, 89f39d1f56SLois Curfman McInnes 0,0,0, 9071b459e3SLois Curfman McInnes 0,0,0,0 }; 91e51e0e81SBarry Smith 924b828684SBarry Smith /*@C 93052efed2SBarry Smith MatCreateShell - Creates a new matrix class for use with a user-defined 94ff756334SLois Curfman McInnes private data storage format. 95e51e0e81SBarry Smith 96e51e0e81SBarry Smith Input Parameters: 976b5873e3SBarry Smith . comm - MPI communicator 98f39d1f56SLois Curfman McInnes . m - number of local rows 99f39d1f56SLois Curfman McInnes . n - number of local columns 100f39d1f56SLois Curfman McInnes . M - number of global rows 101f39d1f56SLois Curfman McInnes . N - number of global columns 102deebb3c3SLois Curfman McInnes . ctx - pointer to data needed by the shell matrix routines 103e51e0e81SBarry Smith 104ff756334SLois Curfman McInnes Output Parameter: 10544cd7ae7SLois Curfman McInnes . A - the matrix 106e51e0e81SBarry Smith 107f39d1f56SLois Curfman McInnes Usage: 108f39d1f56SLois Curfman McInnes $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 109f39d1f56SLois Curfman McInnes $ MatShellSetOperation(mat,MAT_MULT,mult); 110f39d1f56SLois Curfman McInnes $ [ Use matrix for operations that have been set ] 111f39d1f56SLois Curfman McInnes $ MatDestroy(mat); 112f39d1f56SLois Curfman McInnes 113ff756334SLois Curfman McInnes Notes: 114ff756334SLois Curfman McInnes The shell matrix type is intended to provide a simple class to use 115ff756334SLois Curfman McInnes with KSP (such as, for use with matrix-free methods). You should not 116ff756334SLois Curfman McInnes use the shell type if you plan to define a complete matrix class. 117e51e0e81SBarry Smith 118f39d1f56SLois Curfman McInnes PETSc requires that matrices and vectors being used for certain 119f39d1f56SLois Curfman McInnes operations are partitioned accordingly. For example, when 120645985a0SLois Curfman McInnes creating a shell matrix, A, that supports parallel matrix-vector 121645985a0SLois Curfman McInnes products using MatMult(A,x,y) the user should set the number 122645985a0SLois Curfman McInnes of local matrix rows to be the number of local elements of the 123645985a0SLois Curfman McInnes corresponding result vector, y. Note that this is information is 124645985a0SLois Curfman McInnes required for use of the matrix interface routines, even though 125645985a0SLois Curfman McInnes the shell matrix may not actually be physically partitioned. 126645985a0SLois Curfman McInnes For example, 127f39d1f56SLois Curfman McInnes 128f39d1f56SLois Curfman McInnes $ 129f39d1f56SLois Curfman McInnes $ Vec x, y 130645985a0SLois Curfman McInnes $ Mat A 131f39d1f56SLois Curfman McInnes $ 132f39d1f56SLois Curfman McInnes $ VecCreate(comm,M,&y); 133f39d1f56SLois Curfman McInnes $ VecCreate(comm,N,&x); 134f39d1f56SLois Curfman McInnes $ VecGetLocalSize(y,&m); 135645985a0SLois Curfman McInnes $ MatCreateShell(comm,m,N,M,N,ctx,&A); 136a62d957aSLois Curfman McInnes $ MatShellSetOperation(mat,MAT_MULT,mult); 137645985a0SLois Curfman McInnes $ MatMult(A,x,y); 138645985a0SLois Curfman McInnes $ MatDestroy(A); 139f39d1f56SLois Curfman McInnes $ VecDestroy(y); VecDestroy(x); 140645985a0SLois Curfman McInnes $ 141e51e0e81SBarry Smith 1420b627109SLois Curfman McInnes .keywords: matrix, shell, create 1430b627109SLois Curfman McInnes 1443a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 145e51e0e81SBarry Smith @*/ 146f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 147e51e0e81SBarry Smith { 14844cd7ae7SLois Curfman McInnes Mat B; 14944cd7ae7SLois Curfman McInnes Mat_Shell *b; 150ed3cc1f0SBarry Smith 15144cd7ae7SLois Curfman McInnes PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm); 15244cd7ae7SLois Curfman McInnes PLogObjectCreate(B); 15344cd7ae7SLois Curfman McInnes B->factor = 0; 15444cd7ae7SLois Curfman McInnes B->destroy = MatDestroy_Shell; 15544cd7ae7SLois Curfman McInnes B->assembled = PETSC_TRUE; 15644cd7ae7SLois Curfman McInnes PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps)); 157227d817aSBarry Smith 15844cd7ae7SLois Curfman McInnes b = PetscNew(Mat_Shell); CHKPTRQ(b); 15944cd7ae7SLois Curfman McInnes PetscMemzero(b,sizeof(Mat_Shell)); 16044cd7ae7SLois Curfman McInnes B->data = (void *) b; 161f39d1f56SLois Curfman McInnes b->M = M; B->M = M; 162f39d1f56SLois Curfman McInnes b->N = N; B->N = N; 163f39d1f56SLois Curfman McInnes b->m = m; B->m = m; 164f39d1f56SLois Curfman McInnes b->n = n; B->n = n; 16544cd7ae7SLois Curfman McInnes b->ctx = ctx; 16644cd7ae7SLois Curfman McInnes *A = B; 167e51e0e81SBarry Smith return 0; 168e51e0e81SBarry Smith } 169e51e0e81SBarry Smith 170fae171e0SBarry Smith /*@ 1713a3eedf2SBarry Smith MatShellSetOperation - Allows user to set a matrix operation for 1723a3eedf2SBarry Smith a shell matrix. 173e51e0e81SBarry Smith 174e51e0e81SBarry Smith Input Parameters: 175fae171e0SBarry Smith . mat - the shell matrix 176fae171e0SBarry Smith . op - the name of the operation 177fae171e0SBarry Smith . f - the function that provides the operation. 178e51e0e81SBarry Smith 179fae171e0SBarry Smith Usage: 180a62d957aSLois Curfman McInnes $ extern int usermult(Mat,Vec,Vec); 181f39d1f56SLois Curfman McInnes $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 182a62d957aSLois Curfman McInnes $ ierr = MatShellSetOperation(A,MAT_MULT,usermult); 1830b627109SLois Curfman McInnes 184a62d957aSLois Curfman McInnes Notes: 185a62d957aSLois Curfman McInnes See the file petsc/include/mat.h for a complete list of matrix 186a62d957aSLois Curfman McInnes operations, which all have the form MAT_<OPERATION>, where 187a62d957aSLois Curfman McInnes <OPERATION> is the name (in all capital letters) of the 188a62d957aSLois Curfman McInnes user interface routine (e.g., MatMult() -> MAT_MULT). 189a62d957aSLois Curfman McInnes 190a62d957aSLois Curfman McInnes All user-provided functions should have the same calling 191deebb3c3SLois Curfman McInnes sequence as the usual matrix interface routines, since they 192deebb3c3SLois Curfman McInnes are intended to be accessed via the usual matrix interface 193deebb3c3SLois Curfman McInnes routines, e.g., 194a62d957aSLois Curfman McInnes $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 195a62d957aSLois Curfman McInnes 196a62d957aSLois Curfman McInnes Within each user-defined routine, the user should call 197a62d957aSLois Curfman McInnes MatShellGetContext() to obtain the user-defined context that was 198a62d957aSLois Curfman McInnes set by MatCreateShell(). 199a62d957aSLois Curfman McInnes 200a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation 201a62d957aSLois Curfman McInnes 202a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellGetContext() 203e51e0e81SBarry Smith @*/ 204fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f) 205e51e0e81SBarry Smith { 20677c4ece6SBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 207fae171e0SBarry Smith 208a62d957aSLois Curfman McInnes if (op == MAT_DESTROY) { 209a62d957aSLois Curfman McInnes if (mat->type == MATSHELL) { 210a62d957aSLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 2113a3eedf2SBarry Smith shell->destroy = (int (*)(Mat)) f; 212a62d957aSLois Curfman McInnes } 213a62d957aSLois Curfman McInnes else mat->destroy = (int (*)(PetscObject)) f; 214a62d957aSLois Curfman McInnes } 215fae171e0SBarry Smith else if (op == MAT_VIEW) mat->view = (int (*)(PetscObject,Viewer)) f; 216fae171e0SBarry Smith else (((void**)&mat->ops)[op]) = f; 217a62d957aSLois Curfman McInnes 21820563c6bSBarry Smith return 0; 219e51e0e81SBarry Smith } 220f0479e8cSBarry Smith 2213a3eedf2SBarry Smith 2223a3eedf2SBarry Smith 2233a3eedf2SBarry Smith 2243a3eedf2SBarry Smith 2253a3eedf2SBarry Smith 226