1357feee3SLois Curfman McInnes #ifndef lint 2*f39d1f56SLois Curfman McInnes static char vcid[] = "$Id: shell.c,v 1.32 1996/04/07 22:47:23 curfman Exp curfman $"; 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*/ 13e51e0e81SBarry Smith #include "vec/vecimpl.h" 14e51e0e81SBarry Smith 1520563c6bSBarry Smith typedef struct { 16*f39d1f56SLois Curfman McInnes int M, N; /* number of global rows, columns */ 17*f39d1f56SLois 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 47*f39d1f56SLois 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; 50*f39d1f56SLois Curfman McInnes *M = shell->M; *N = shell->N; 51*f39d1f56SLois Curfman McInnes return 0; 52*f39d1f56SLois Curfman McInnes } 53*f39d1f56SLois Curfman McInnes 54*f39d1f56SLois Curfman McInnes static int MatGetLocalSize_Shell(Mat mat,int *m,int *n) 55*f39d1f56SLois Curfman McInnes { 56*f39d1f56SLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 57*f39d1f56SLois 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, 88*f39d1f56SLois Curfman McInnes 0,0,MatGetSize_Shell,MatGetLocalSize_Shell, 89*f39d1f56SLois 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 98*f39d1f56SLois Curfman McInnes . m - number of local rows 99*f39d1f56SLois Curfman McInnes . n - number of local columns 100*f39d1f56SLois Curfman McInnes . M - number of global rows 101*f39d1f56SLois 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 107*f39d1f56SLois Curfman McInnes Usage: 108*f39d1f56SLois Curfman McInnes $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 109*f39d1f56SLois Curfman McInnes $ MatShellSetOperation(mat,MAT_MULT,mult); 110*f39d1f56SLois Curfman McInnes $ [ Use matrix for operations that have been set ] 111*f39d1f56SLois Curfman McInnes $ MatDestroy(mat); 112*f39d1f56SLois 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 118*f39d1f56SLois Curfman McInnes PETSc requires that matrices and vectors being used for certain 119*f39d1f56SLois Curfman McInnes operations are partitioned accordingly. For example, when 120*f39d1f56SLois Curfman McInnes creating a shell matrix that supports parallel matrix-vector 121*f39d1f56SLois Curfman McInnes products using MatMult(), the user should set the number of local 122*f39d1f56SLois Curfman McInnes matrix rows to be the same as the corresponding result vector 123*f39d1f56SLois Curfman McInnes (even though the shell matrix may not actually be physically 124*f39d1f56SLois Curfman McInnes partitioned or even stored at all). For example, 125*f39d1f56SLois Curfman McInnes 126*f39d1f56SLois Curfman McInnes $ /* Create matrix and vectors to compute y = Ax */ 127*f39d1f56SLois Curfman McInnes $ 128*f39d1f56SLois Curfman McInnes $ Vec x, y 129*f39d1f56SLois Curfman McInnes $ Mat mat 130*f39d1f56SLois Curfman McInnes $ 131*f39d1f56SLois Curfman McInnes $ VecCreate(comm,M,&y); 132*f39d1f56SLois Curfman McInnes $ VecCreate(comm,N,&x); 133*f39d1f56SLois Curfman McInnes $ VecGetLocalSize(y,&m); 134*f39d1f56SLois Curfman McInnes $ MatCreateShell(comm,m,N,M,N,ctx,&mat); 135a62d957aSLois Curfman McInnes $ MatShellSetOperation(mat,MAT_MULT,mult); 136*f39d1f56SLois Curfman McInnes $ MatMult(mat,x,y); 137a62d957aSLois Curfman McInnes $ MatDestroy(mat); 138*f39d1f56SLois Curfman McInnes $ VecDestroy(y); VecDestroy(x); 139e51e0e81SBarry Smith 1400b627109SLois Curfman McInnes .keywords: matrix, shell, create 1410b627109SLois Curfman McInnes 1423a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 143e51e0e81SBarry Smith @*/ 144*f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 145e51e0e81SBarry Smith { 14644cd7ae7SLois Curfman McInnes Mat B; 14744cd7ae7SLois Curfman McInnes Mat_Shell *b; 148ed3cc1f0SBarry Smith 14944cd7ae7SLois Curfman McInnes PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm); 15044cd7ae7SLois Curfman McInnes PLogObjectCreate(B); 15144cd7ae7SLois Curfman McInnes B->factor = 0; 15244cd7ae7SLois Curfman McInnes B->destroy = MatDestroy_Shell; 15344cd7ae7SLois Curfman McInnes B->assembled = PETSC_TRUE; 15444cd7ae7SLois Curfman McInnes PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps)); 155227d817aSBarry Smith 15644cd7ae7SLois Curfman McInnes b = PetscNew(Mat_Shell); CHKPTRQ(b); 15744cd7ae7SLois Curfman McInnes PetscMemzero(b,sizeof(Mat_Shell)); 15844cd7ae7SLois Curfman McInnes B->data = (void *) b; 159*f39d1f56SLois Curfman McInnes b->M = M; B->M = M; 160*f39d1f56SLois Curfman McInnes b->N = N; B->N = N; 161*f39d1f56SLois Curfman McInnes b->m = m; B->m = m; 162*f39d1f56SLois Curfman McInnes b->n = n; B->n = n; 16344cd7ae7SLois Curfman McInnes b->ctx = ctx; 16444cd7ae7SLois Curfman McInnes *A = B; 165e51e0e81SBarry Smith return 0; 166e51e0e81SBarry Smith } 167e51e0e81SBarry Smith 168fae171e0SBarry Smith /*@ 1693a3eedf2SBarry Smith MatShellSetOperation - Allows user to set a matrix operation for 1703a3eedf2SBarry Smith a shell matrix. 171e51e0e81SBarry Smith 172e51e0e81SBarry Smith Input Parameters: 173fae171e0SBarry Smith . mat - the shell matrix 174fae171e0SBarry Smith . op - the name of the operation 175fae171e0SBarry Smith . f - the function that provides the operation. 176e51e0e81SBarry Smith 177fae171e0SBarry Smith Usage: 178a62d957aSLois Curfman McInnes $ extern int usermult(Mat,Vec,Vec); 179*f39d1f56SLois Curfman McInnes $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 180a62d957aSLois Curfman McInnes $ ierr = MatShellSetOperation(A,MAT_MULT,usermult); 1810b627109SLois Curfman McInnes 182a62d957aSLois Curfman McInnes Notes: 183a62d957aSLois Curfman McInnes See the file petsc/include/mat.h for a complete list of matrix 184a62d957aSLois Curfman McInnes operations, which all have the form MAT_<OPERATION>, where 185a62d957aSLois Curfman McInnes <OPERATION> is the name (in all capital letters) of the 186a62d957aSLois Curfman McInnes user interface routine (e.g., MatMult() -> MAT_MULT). 187a62d957aSLois Curfman McInnes 188a62d957aSLois Curfman McInnes All user-provided functions should have the same calling 189deebb3c3SLois Curfman McInnes sequence as the usual matrix interface routines, since they 190deebb3c3SLois Curfman McInnes are intended to be accessed via the usual matrix interface 191deebb3c3SLois Curfman McInnes routines, e.g., 192a62d957aSLois Curfman McInnes $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 193a62d957aSLois Curfman McInnes 194a62d957aSLois Curfman McInnes Within each user-defined routine, the user should call 195a62d957aSLois Curfman McInnes MatShellGetContext() to obtain the user-defined context that was 196a62d957aSLois Curfman McInnes set by MatCreateShell(). 197a62d957aSLois Curfman McInnes 198a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation 199a62d957aSLois Curfman McInnes 200a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellGetContext() 201e51e0e81SBarry Smith @*/ 202fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f) 203e51e0e81SBarry Smith { 20477c4ece6SBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 205fae171e0SBarry Smith 206a62d957aSLois Curfman McInnes if (op == MAT_DESTROY) { 207a62d957aSLois Curfman McInnes if (mat->type == MATSHELL) { 208a62d957aSLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 2093a3eedf2SBarry Smith shell->destroy = (int (*)(Mat)) f; 210a62d957aSLois Curfman McInnes } 211a62d957aSLois Curfman McInnes else mat->destroy = (int (*)(PetscObject)) f; 212a62d957aSLois Curfman McInnes } 213fae171e0SBarry Smith else if (op == MAT_VIEW) mat->view = (int (*)(PetscObject,Viewer)) f; 214fae171e0SBarry Smith else (((void **)&mat->ops)[op]) = f; 215a62d957aSLois Curfman McInnes 21620563c6bSBarry Smith return 0; 217e51e0e81SBarry Smith } 218f0479e8cSBarry Smith 2193a3eedf2SBarry Smith 2203a3eedf2SBarry Smith 2213a3eedf2SBarry Smith 2223a3eedf2SBarry Smith 2233a3eedf2SBarry Smith 224