1357feee3SLois Curfman McInnes #ifndef lint 2*8f6be9afSLois Curfman McInnes static char vcid[] = "$Id: shell.c,v 1.45 1997/02/22 02:25:22 bsmith 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" 1270f55243SBarry Smith #include "src/mat/matimpl.h" /*I "mat.h" I*/ 13f5eb4b81SSatish 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 225615d1e5SSatish Balay #undef __FUNC__ 235eea60f9SBarry Smith #define __FUNC__ "MatShellGetContext" /* ADIC Ignore */ 24b4fd4287SBarry Smith /*@ 25a62d957aSLois Curfman McInnes MatShellGetContext - Returns the user-provided context associated with a shell matrix. 26b4fd4287SBarry Smith 27b4fd4287SBarry Smith Input Parameter: 28b4fd4287SBarry Smith . mat - the matrix, should have been created with MatCreateShell() 29b4fd4287SBarry Smith 30b4fd4287SBarry Smith Output Parameter: 31b4fd4287SBarry Smith . ctx - the user provided context 32b4fd4287SBarry Smith 33a62d957aSLois Curfman McInnes Notes: 34a62d957aSLois Curfman McInnes This routine is intended for use within various shell matrix routines, 35a62d957aSLois Curfman McInnes as set with MatShellSetOperation(). 36a62d957aSLois Curfman McInnes 37a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context 38a62d957aSLois Curfman McInnes 39a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation() 40b4fd4287SBarry Smith @*/ 41b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx) 42b4fd4287SBarry Smith { 4377c4ece6SBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 44b4fd4287SBarry Smith if (mat->type != MATSHELL) *ctx = 0; 45b4fd4287SBarry Smith else *ctx = ((Mat_Shell *) (mat->data))->ctx; 46b4fd4287SBarry Smith return 0; 47b4fd4287SBarry Smith } 48b4fd4287SBarry Smith 495615d1e5SSatish Balay #undef __FUNC__ 505eea60f9SBarry Smith #define __FUNC__ "MatGetSize_Shell" /* ADIC Ignore */ 51*8f6be9afSLois Curfman McInnes int MatGetSize_Shell(Mat mat,int *M,int *N) 5271b459e3SLois Curfman McInnes { 5371b459e3SLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 54f39d1f56SLois Curfman McInnes *M = shell->M; *N = shell->N; 55f39d1f56SLois Curfman McInnes return 0; 56f39d1f56SLois Curfman McInnes } 57f39d1f56SLois Curfman McInnes 585615d1e5SSatish Balay #undef __FUNC__ 595eea60f9SBarry Smith #define __FUNC__ "MatGetLocalSize_Shell" /* ADIC Ignore */ 60*8f6be9afSLois Curfman McInnes int MatGetLocalSize_Shell(Mat mat,int *m,int *n) 61f39d1f56SLois Curfman McInnes { 62f39d1f56SLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 63f39d1f56SLois Curfman McInnes *m = shell->n; *n = shell->n; 6471b459e3SLois Curfman McInnes return 0; 6571b459e3SLois Curfman McInnes } 6671b459e3SLois Curfman McInnes 675615d1e5SSatish Balay #undef __FUNC__ 685eea60f9SBarry Smith #define __FUNC__ "MatDestroy_Shell" /* ADIC Ignore */ 69*8f6be9afSLois Curfman McInnes int MatDestroy_Shell(PetscObject obj) 70e51e0e81SBarry Smith { 71b9fa9cd0SBarry Smith int ierr; 7220563c6bSBarry Smith Mat mat = (Mat) obj; 7388cf3e7dSBarry Smith Mat_Shell *shell; 74ed3cc1f0SBarry Smith 7588cf3e7dSBarry Smith shell = (Mat_Shell *) mat->data; 763a3eedf2SBarry Smith if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);} 770452661fSBarry Smith PetscFree(shell); 783a3eedf2SBarry Smith PLogObjectDestroy(mat); 793a3eedf2SBarry Smith PetscHeaderDestroy(mat); 80e51e0e81SBarry Smith return 0; 81e51e0e81SBarry Smith } 82e51e0e81SBarry Smith 83*8f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend) 84b951964fSBarry Smith { 85b951964fSBarry Smith MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm); 86b951964fSBarry Smith *rstart = *rend - mat->m; 87b951964fSBarry Smith return 0; 88b951964fSBarry Smith } 89b951964fSBarry Smith 90b951964fSBarry Smith 91b951964fSBarry Smith 92b951964fSBarry Smith 93b951964fSBarry Smith static struct _MatOps MatOps = {0, 9420563c6bSBarry Smith 0, 9520563c6bSBarry Smith 0, 9620563c6bSBarry Smith 0, 9720563c6bSBarry Smith 0, 98b951964fSBarry Smith 0, 99b951964fSBarry Smith 0, 100b951964fSBarry Smith 0, 101b951964fSBarry Smith 0, 102b951964fSBarry Smith 0, 103b951964fSBarry Smith 0, 104b951964fSBarry Smith 0, 105b951964fSBarry Smith 0, 106b951964fSBarry Smith 0, 107b951964fSBarry Smith 0, 108b951964fSBarry Smith 0, 109b951964fSBarry Smith 0, 110b951964fSBarry Smith 0, 111b951964fSBarry Smith 0, 112b951964fSBarry Smith 0, 113b951964fSBarry Smith 0, 114b951964fSBarry Smith 0, 115b951964fSBarry Smith 0, 116b951964fSBarry Smith 0, 117b951964fSBarry Smith 0, 118b951964fSBarry Smith 0, 119b951964fSBarry Smith 0, 120b951964fSBarry Smith 0, 121b951964fSBarry Smith 0, 122b951964fSBarry Smith 0, 123b951964fSBarry Smith MatGetSize_Shell, 124b951964fSBarry Smith MatGetLocalSize_Shell, 125b951964fSBarry Smith MatGetOwnershipRange_Shell, 126b951964fSBarry Smith 0, 127b951964fSBarry Smith 0, 128b951964fSBarry Smith 0, 129b951964fSBarry Smith 0, 130b951964fSBarry Smith 0 }; 131e51e0e81SBarry Smith 1325615d1e5SSatish Balay #undef __FUNC__ 1335eea60f9SBarry Smith #define __FUNC__ "MatCreateShell" /* ADIC Ignore */ 1344b828684SBarry Smith /*@C 135052efed2SBarry Smith MatCreateShell - Creates a new matrix class for use with a user-defined 136ff756334SLois Curfman McInnes private data storage format. 137e51e0e81SBarry Smith 138e51e0e81SBarry Smith Input Parameters: 1396b5873e3SBarry Smith . comm - MPI communicator 140f39d1f56SLois Curfman McInnes . m - number of local rows 141f39d1f56SLois Curfman McInnes . n - number of local columns 142f39d1f56SLois Curfman McInnes . M - number of global rows 143f39d1f56SLois Curfman McInnes . N - number of global columns 144deebb3c3SLois Curfman McInnes . ctx - pointer to data needed by the shell matrix routines 145e51e0e81SBarry Smith 146ff756334SLois Curfman McInnes Output Parameter: 14744cd7ae7SLois Curfman McInnes . A - the matrix 148e51e0e81SBarry Smith 149f39d1f56SLois Curfman McInnes Usage: 150f39d1f56SLois Curfman McInnes $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 1511c1c02c0SLois Curfman McInnes $ MatShellSetOperation(mat,MATOP_MULT,mult); 152f39d1f56SLois Curfman McInnes $ [ Use matrix for operations that have been set ] 153f39d1f56SLois Curfman McInnes $ MatDestroy(mat); 154f39d1f56SLois Curfman McInnes 155ff756334SLois Curfman McInnes Notes: 156ff756334SLois Curfman McInnes The shell matrix type is intended to provide a simple class to use 157ff756334SLois Curfman McInnes with KSP (such as, for use with matrix-free methods). You should not 158ff756334SLois Curfman McInnes use the shell type if you plan to define a complete matrix class. 159e51e0e81SBarry Smith 160f39d1f56SLois Curfman McInnes PETSc requires that matrices and vectors being used for certain 161f39d1f56SLois Curfman McInnes operations are partitioned accordingly. For example, when 162645985a0SLois Curfman McInnes creating a shell matrix, A, that supports parallel matrix-vector 163645985a0SLois Curfman McInnes products using MatMult(A,x,y) the user should set the number 164645985a0SLois Curfman McInnes of local matrix rows to be the number of local elements of the 165645985a0SLois Curfman McInnes corresponding result vector, y. Note that this is information is 166645985a0SLois Curfman McInnes required for use of the matrix interface routines, even though 167645985a0SLois Curfman McInnes the shell matrix may not actually be physically partitioned. 168645985a0SLois Curfman McInnes For example, 169f39d1f56SLois Curfman McInnes 170f39d1f56SLois Curfman McInnes $ 171f39d1f56SLois Curfman McInnes $ Vec x, y 172645985a0SLois Curfman McInnes $ Mat A 173f39d1f56SLois Curfman McInnes $ 174f39d1f56SLois Curfman McInnes $ VecCreate(comm,M,&y); 175f39d1f56SLois Curfman McInnes $ VecCreate(comm,N,&x); 176f39d1f56SLois Curfman McInnes $ VecGetLocalSize(y,&m); 177645985a0SLois Curfman McInnes $ MatCreateShell(comm,m,N,M,N,ctx,&A); 1781c1c02c0SLois Curfman McInnes $ MatShellSetOperation(mat,MATOP_MULT,mult); 179645985a0SLois Curfman McInnes $ MatMult(A,x,y); 180645985a0SLois Curfman McInnes $ MatDestroy(A); 181f39d1f56SLois Curfman McInnes $ VecDestroy(y); VecDestroy(x); 182645985a0SLois Curfman McInnes $ 183e51e0e81SBarry Smith 1840b627109SLois Curfman McInnes .keywords: matrix, shell, create 1850b627109SLois Curfman McInnes 1863a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 187e51e0e81SBarry Smith @*/ 188f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 189e51e0e81SBarry Smith { 19044cd7ae7SLois Curfman McInnes Mat B; 19144cd7ae7SLois Curfman McInnes Mat_Shell *b; 192ed3cc1f0SBarry Smith 19344cd7ae7SLois Curfman McInnes PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm); 19444cd7ae7SLois Curfman McInnes PLogObjectCreate(B); 19544cd7ae7SLois Curfman McInnes B->factor = 0; 19644cd7ae7SLois Curfman McInnes B->destroy = MatDestroy_Shell; 19744cd7ae7SLois Curfman McInnes B->assembled = PETSC_TRUE; 19844cd7ae7SLois Curfman McInnes PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps)); 199227d817aSBarry Smith 20044cd7ae7SLois Curfman McInnes b = PetscNew(Mat_Shell); CHKPTRQ(b); 20144cd7ae7SLois Curfman McInnes PetscMemzero(b,sizeof(Mat_Shell)); 20244cd7ae7SLois Curfman McInnes B->data = (void *) b; 203f39d1f56SLois Curfman McInnes b->M = M; B->M = M; 204f39d1f56SLois Curfman McInnes b->N = N; B->N = N; 205f39d1f56SLois Curfman McInnes b->m = m; B->m = m; 206f39d1f56SLois Curfman McInnes b->n = n; B->n = n; 20744cd7ae7SLois Curfman McInnes b->ctx = ctx; 20844cd7ae7SLois Curfman McInnes *A = B; 209e51e0e81SBarry Smith return 0; 210e51e0e81SBarry Smith } 211e51e0e81SBarry Smith 2125615d1e5SSatish Balay #undef __FUNC__ 2135eea60f9SBarry Smith #define __FUNC__ "MatShellSetOperation" /* ADIC Ignore */ 214c16cb8f2SBarry Smith /*@C 2153a3eedf2SBarry Smith MatShellSetOperation - Allows user to set a matrix operation for 2163a3eedf2SBarry Smith a shell matrix. 217e51e0e81SBarry Smith 218e51e0e81SBarry Smith Input Parameters: 219fae171e0SBarry Smith . mat - the shell matrix 220fae171e0SBarry Smith . op - the name of the operation 221fae171e0SBarry Smith . f - the function that provides the operation. 222e51e0e81SBarry Smith 223fae171e0SBarry Smith Usage: 224a62d957aSLois Curfman McInnes $ extern int usermult(Mat,Vec,Vec); 225f39d1f56SLois Curfman McInnes $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 2261c1c02c0SLois Curfman McInnes $ ierr = MatShellSetOperation(A,MATOP_MULT,usermult); 2270b627109SLois Curfman McInnes 228a62d957aSLois Curfman McInnes Notes: 229a62d957aSLois Curfman McInnes See the file petsc/include/mat.h for a complete list of matrix 2301c1c02c0SLois Curfman McInnes operations, which all have the form MATOP_<OPERATION>, where 231a62d957aSLois Curfman McInnes <OPERATION> is the name (in all capital letters) of the 2321c1c02c0SLois Curfman McInnes user interface routine (e.g., MatMult() -> MATOP_MULT). 233a62d957aSLois Curfman McInnes 234a62d957aSLois Curfman McInnes All user-provided functions should have the same calling 235deebb3c3SLois Curfman McInnes sequence as the usual matrix interface routines, since they 236deebb3c3SLois Curfman McInnes are intended to be accessed via the usual matrix interface 237deebb3c3SLois Curfman McInnes routines, e.g., 238a62d957aSLois Curfman McInnes $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 239a62d957aSLois Curfman McInnes 240a62d957aSLois Curfman McInnes Within each user-defined routine, the user should call 241a62d957aSLois Curfman McInnes MatShellGetContext() to obtain the user-defined context that was 242a62d957aSLois Curfman McInnes set by MatCreateShell(). 243a62d957aSLois Curfman McInnes 244a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation 245a62d957aSLois Curfman McInnes 246a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellGetContext() 247e51e0e81SBarry Smith @*/ 248fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f) 249e51e0e81SBarry Smith { 25077c4ece6SBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 251fae171e0SBarry Smith 2521c1c02c0SLois Curfman McInnes if (op == MATOP_DESTROY) { 253a62d957aSLois Curfman McInnes if (mat->type == MATSHELL) { 254a62d957aSLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 2553a3eedf2SBarry Smith shell->destroy = (int (*)(Mat)) f; 256a62d957aSLois Curfman McInnes } 257a62d957aSLois Curfman McInnes else mat->destroy = (int (*)(PetscObject)) f; 258a62d957aSLois Curfman McInnes } 2591c1c02c0SLois Curfman McInnes else if (op == MATOP_VIEW) mat->view = (int (*)(PetscObject,Viewer)) f; 260fae171e0SBarry Smith else (((void**)&mat->ops)[op]) = f; 261a62d957aSLois Curfman McInnes 26220563c6bSBarry Smith return 0; 263e51e0e81SBarry Smith } 264f0479e8cSBarry Smith 2653a3eedf2SBarry Smith 2663a3eedf2SBarry Smith 267