1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 2*d4bb536fSBarry Smith static char vcid[] = "$Id: shell.c,v 1.49 1997/07/09 20:54:17 balay Exp bsmith $"; 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__ 23*d4bb536fSBarry Smith #define __FUNC__ "MatShellGetContext" 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__ 50*d4bb536fSBarry Smith #define __FUNC__ "MatGetSize_Shell" 518f6be9afSLois 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__ 59*d4bb536fSBarry Smith #define __FUNC__ "MatGetLocalSize_Shell" 608f6be9afSLois 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__ 68*d4bb536fSBarry Smith #define __FUNC__ "MatDestroy_Shell" 698f6be9afSLois 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 838f6be9afSLois 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__ 133*d4bb536fSBarry Smith #define __FUNC__ "MatCreateShell" 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 193*d4bb536fSBarry Smith PetscHeaderCreate(B,_p_Mat,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView); 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); 201eed86810SBarry Smith PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell)); 20244cd7ae7SLois Curfman McInnes PetscMemzero(b,sizeof(Mat_Shell)); 20344cd7ae7SLois Curfman McInnes B->data = (void *) b; 204f39d1f56SLois Curfman McInnes b->M = M; B->M = M; 205f39d1f56SLois Curfman McInnes b->N = N; B->N = N; 206f39d1f56SLois Curfman McInnes b->m = m; B->m = m; 207f39d1f56SLois Curfman McInnes b->n = n; B->n = n; 20844cd7ae7SLois Curfman McInnes b->ctx = ctx; 20944cd7ae7SLois Curfman McInnes *A = B; 210e51e0e81SBarry Smith return 0; 211e51e0e81SBarry Smith } 212e51e0e81SBarry Smith 2135615d1e5SSatish Balay #undef __FUNC__ 214*d4bb536fSBarry Smith #define __FUNC__ "MatShellSetOperation" 215c16cb8f2SBarry Smith /*@C 2163a3eedf2SBarry Smith MatShellSetOperation - Allows user to set a matrix operation for 2173a3eedf2SBarry Smith a shell matrix. 218e51e0e81SBarry Smith 219e51e0e81SBarry Smith Input Parameters: 220fae171e0SBarry Smith . mat - the shell matrix 221fae171e0SBarry Smith . op - the name of the operation 222fae171e0SBarry Smith . f - the function that provides the operation. 223e51e0e81SBarry Smith 224fae171e0SBarry Smith Usage: 225a62d957aSLois Curfman McInnes $ extern int usermult(Mat,Vec,Vec); 226f39d1f56SLois Curfman McInnes $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 2271c1c02c0SLois Curfman McInnes $ ierr = MatShellSetOperation(A,MATOP_MULT,usermult); 2280b627109SLois Curfman McInnes 229a62d957aSLois Curfman McInnes Notes: 230a62d957aSLois Curfman McInnes See the file petsc/include/mat.h for a complete list of matrix 2311c1c02c0SLois Curfman McInnes operations, which all have the form MATOP_<OPERATION>, where 232a62d957aSLois Curfman McInnes <OPERATION> is the name (in all capital letters) of the 2331c1c02c0SLois Curfman McInnes user interface routine (e.g., MatMult() -> MATOP_MULT). 234a62d957aSLois Curfman McInnes 235a62d957aSLois Curfman McInnes All user-provided functions should have the same calling 236deebb3c3SLois Curfman McInnes sequence as the usual matrix interface routines, since they 237deebb3c3SLois Curfman McInnes are intended to be accessed via the usual matrix interface 238deebb3c3SLois Curfman McInnes routines, e.g., 239a62d957aSLois Curfman McInnes $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 240a62d957aSLois Curfman McInnes 241a62d957aSLois Curfman McInnes Within each user-defined routine, the user should call 242a62d957aSLois Curfman McInnes MatShellGetContext() to obtain the user-defined context that was 243a62d957aSLois Curfman McInnes set by MatCreateShell(). 244a62d957aSLois Curfman McInnes 245a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation 246a62d957aSLois Curfman McInnes 247*d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation() 248e51e0e81SBarry Smith @*/ 249fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f) 250e51e0e81SBarry Smith { 25177c4ece6SBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 252fae171e0SBarry Smith 2531c1c02c0SLois Curfman McInnes if (op == MATOP_DESTROY) { 254a62d957aSLois Curfman McInnes if (mat->type == MATSHELL) { 255a62d957aSLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 2563a3eedf2SBarry Smith shell->destroy = (int (*)(Mat)) f; 257a62d957aSLois Curfman McInnes } 258a62d957aSLois Curfman McInnes else mat->destroy = (int (*)(PetscObject)) f; 259a62d957aSLois Curfman McInnes } 2601c1c02c0SLois Curfman McInnes else if (op == MATOP_VIEW) mat->view = (int (*)(PetscObject,Viewer)) f; 261fae171e0SBarry Smith else (((void**)&mat->ops)[op]) = f; 262a62d957aSLois Curfman McInnes 26320563c6bSBarry Smith return 0; 264e51e0e81SBarry Smith } 265f0479e8cSBarry Smith 2663a3eedf2SBarry Smith 2673a3eedf2SBarry Smith 268*d4bb536fSBarry Smith #undef __FUNC__ 269*d4bb536fSBarry Smith #define __FUNC__ "MatShellGetOperation" 270*d4bb536fSBarry Smith /*@C 271*d4bb536fSBarry Smith MatShellGetOperation - Gets a matrix function for a shell matrix. 272*d4bb536fSBarry Smith 273*d4bb536fSBarry Smith Input Parameters: 274*d4bb536fSBarry Smith . mat - the shell matrix 275*d4bb536fSBarry Smith . op - the name of the operation 276*d4bb536fSBarry Smith 277*d4bb536fSBarry Smith Output Parameter: 278*d4bb536fSBarry Smith . f - the function that provides the operation. 279*d4bb536fSBarry Smith 280*d4bb536fSBarry Smith Notes: 281*d4bb536fSBarry Smith See the file petsc/include/mat.h for a complete list of matrix 282*d4bb536fSBarry Smith operations, which all have the form MATOP_<OPERATION>, where 283*d4bb536fSBarry Smith <OPERATION> is the name (in all capital letters) of the 284*d4bb536fSBarry Smith user interface routine (e.g., MatMult() -> MATOP_MULT). 285*d4bb536fSBarry Smith 286*d4bb536fSBarry Smith All user-provided functions have the same calling 287*d4bb536fSBarry Smith sequence as the usual matrix interface routines, since they 288*d4bb536fSBarry Smith are intended to be accessed via the usual matrix interface 289*d4bb536fSBarry Smith routines, e.g., 290*d4bb536fSBarry Smith $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 291*d4bb536fSBarry Smith 292*d4bb536fSBarry Smith Within each user-defined routine, the user should call 293*d4bb536fSBarry Smith MatShellGetContext() to obtain the user-defined context that was 294*d4bb536fSBarry Smith set by MatCreateShell(). 295*d4bb536fSBarry Smith 296*d4bb536fSBarry Smith .keywords: matrix, shell, set, operation 297*d4bb536fSBarry Smith 298*d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation() 299*d4bb536fSBarry Smith @*/ 300*d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op, void **f) 301*d4bb536fSBarry Smith { 302*d4bb536fSBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 303*d4bb536fSBarry Smith 304*d4bb536fSBarry Smith if (op == MATOP_DESTROY) { 305*d4bb536fSBarry Smith if (mat->type == MATSHELL) { 306*d4bb536fSBarry Smith Mat_Shell *shell = (Mat_Shell *) mat->data; 307*d4bb536fSBarry Smith *f = (void *) shell->destroy; 308*d4bb536fSBarry Smith } 309*d4bb536fSBarry Smith else *f = (void *) mat->destroy; 310*d4bb536fSBarry Smith } 311*d4bb536fSBarry Smith else if (op == MATOP_VIEW) *f = (void *) mat->view; 312*d4bb536fSBarry Smith else *f = (((void**)&mat->ops)[op]); 313*d4bb536fSBarry Smith 314*d4bb536fSBarry Smith return 0; 315*d4bb536fSBarry Smith } 316*d4bb536fSBarry Smith 317