1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 2*94d884c6SBarry Smith static char vcid[] = "$Id: shell.c,v 1.56 1998/04/13 17:37:39 bsmith 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__ 23d4bb536fSBarry 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 33fee21e36SBarry Smith Not Collective 34fee21e36SBarry Smith 35a62d957aSLois Curfman McInnes Notes: 36a62d957aSLois Curfman McInnes This routine is intended for use within various shell matrix routines, 37a62d957aSLois Curfman McInnes as set with MatShellSetOperation(). 38a62d957aSLois Curfman McInnes 39a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context 40a62d957aSLois Curfman McInnes 41a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation() 42b4fd4287SBarry Smith @*/ 43b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx) 44b4fd4287SBarry Smith { 453a40ed3dSBarry Smith PetscFunctionBegin; 4677c4ece6SBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 47b4fd4287SBarry Smith if (mat->type != MATSHELL) *ctx = 0; 48b4fd4287SBarry Smith else *ctx = ((Mat_Shell *) (mat->data))->ctx; 493a40ed3dSBarry Smith PetscFunctionReturn(0); 50b4fd4287SBarry Smith } 51b4fd4287SBarry Smith 525615d1e5SSatish Balay #undef __FUNC__ 53d4bb536fSBarry Smith #define __FUNC__ "MatGetSize_Shell" 548f6be9afSLois Curfman McInnes int MatGetSize_Shell(Mat mat,int *M,int *N) 5571b459e3SLois Curfman McInnes { 5671b459e3SLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 573a40ed3dSBarry Smith 583a40ed3dSBarry Smith PetscFunctionBegin; 59f830108cSBarry Smith if (M) *M = shell->M; 60f830108cSBarry Smith if (N) *N = shell->N; 613a40ed3dSBarry Smith PetscFunctionReturn(0); 62f39d1f56SLois Curfman McInnes } 63f39d1f56SLois Curfman McInnes 645615d1e5SSatish Balay #undef __FUNC__ 65d4bb536fSBarry Smith #define __FUNC__ "MatGetLocalSize_Shell" 668f6be9afSLois Curfman McInnes int MatGetLocalSize_Shell(Mat mat,int *m,int *n) 67f39d1f56SLois Curfman McInnes { 68f39d1f56SLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 693a40ed3dSBarry Smith 703a40ed3dSBarry Smith PetscFunctionBegin; 71f830108cSBarry Smith if (m) *m = shell->m; 72f830108cSBarry Smith if (n) *n = shell->n; 733a40ed3dSBarry Smith PetscFunctionReturn(0); 7471b459e3SLois Curfman McInnes } 7571b459e3SLois Curfman McInnes 765615d1e5SSatish Balay #undef __FUNC__ 77d4bb536fSBarry Smith #define __FUNC__ "MatDestroy_Shell" 78e1311b90SBarry Smith int MatDestroy_Shell(Mat mat) 79e51e0e81SBarry Smith { 80b9fa9cd0SBarry Smith int ierr; 8188cf3e7dSBarry Smith Mat_Shell *shell; 82ed3cc1f0SBarry Smith 833a40ed3dSBarry Smith PetscFunctionBegin; 84*94d884c6SBarry Smith if (--mat->refct > 0) PetscFunctionReturn(0); 85*94d884c6SBarry Smith 86*94d884c6SBarry Smith if (mat->mapping) { 87*94d884c6SBarry Smith ierr = ISLocalToGlobalMappingDestroy(mat->mapping); CHKERRQ(ierr); 88*94d884c6SBarry Smith } 89*94d884c6SBarry Smith if (mat->bmapping) { 90*94d884c6SBarry Smith ierr = ISLocalToGlobalMappingDestroy(mat->bmapping); CHKERRQ(ierr); 91*94d884c6SBarry Smith } 9288cf3e7dSBarry Smith shell = (Mat_Shell *) mat->data; 933a3eedf2SBarry Smith if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);} 940452661fSBarry Smith PetscFree(shell); 953a3eedf2SBarry Smith PLogObjectDestroy(mat); 963a3eedf2SBarry Smith PetscHeaderDestroy(mat); 973a40ed3dSBarry Smith PetscFunctionReturn(0); 98e51e0e81SBarry Smith } 99e51e0e81SBarry Smith 1008f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend) 101b951964fSBarry Smith { 102ca161407SBarry Smith int ierr; 103ca161407SBarry Smith 104ca161407SBarry Smith PetscFunctionBegin; 105ca161407SBarry Smith ierr = MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr); 106b951964fSBarry Smith *rstart = *rend - mat->m; 1073a40ed3dSBarry Smith PetscFunctionReturn(0); 108b951964fSBarry Smith } 109b951964fSBarry Smith 110b951964fSBarry Smith 111b951964fSBarry Smith 112b951964fSBarry Smith 113b951964fSBarry Smith static struct _MatOps MatOps = {0, 11420563c6bSBarry Smith 0, 11520563c6bSBarry Smith 0, 11620563c6bSBarry Smith 0, 11720563c6bSBarry Smith 0, 118b951964fSBarry Smith 0, 119b951964fSBarry Smith 0, 120b951964fSBarry Smith 0, 121b951964fSBarry Smith 0, 122b951964fSBarry Smith 0, 123b951964fSBarry Smith 0, 124b951964fSBarry Smith 0, 125b951964fSBarry Smith 0, 126b951964fSBarry Smith 0, 127b951964fSBarry Smith 0, 128b951964fSBarry Smith 0, 129b951964fSBarry Smith 0, 130b951964fSBarry Smith 0, 131b951964fSBarry Smith 0, 132b951964fSBarry Smith 0, 133b951964fSBarry Smith 0, 134b951964fSBarry Smith 0, 135b951964fSBarry Smith 0, 136b951964fSBarry Smith 0, 137b951964fSBarry Smith 0, 138b951964fSBarry Smith 0, 139b951964fSBarry Smith 0, 140b951964fSBarry Smith 0, 141b951964fSBarry Smith 0, 142b951964fSBarry Smith 0, 143b951964fSBarry Smith MatGetSize_Shell, 144b951964fSBarry Smith MatGetLocalSize_Shell, 145b951964fSBarry Smith MatGetOwnershipRange_Shell, 146b951964fSBarry Smith 0, 147b951964fSBarry Smith 0, 148b951964fSBarry Smith 0, 149b951964fSBarry Smith 0, 150b951964fSBarry Smith 0 }; 151e51e0e81SBarry Smith 1525615d1e5SSatish Balay #undef __FUNC__ 153d4bb536fSBarry Smith #define __FUNC__ "MatCreateShell" 1544b828684SBarry Smith /*@C 155052efed2SBarry Smith MatCreateShell - Creates a new matrix class for use with a user-defined 156ff756334SLois Curfman McInnes private data storage format. 157e51e0e81SBarry Smith 158e51e0e81SBarry Smith Input Parameters: 1596b5873e3SBarry Smith . comm - MPI communicator 160f39d1f56SLois Curfman McInnes . m - number of local rows 161f39d1f56SLois Curfman McInnes . n - number of local columns 162f39d1f56SLois Curfman McInnes . M - number of global rows 163f39d1f56SLois Curfman McInnes . N - number of global columns 164deebb3c3SLois Curfman McInnes . ctx - pointer to data needed by the shell matrix routines 165e51e0e81SBarry Smith 166ff756334SLois Curfman McInnes Output Parameter: 16744cd7ae7SLois Curfman McInnes . A - the matrix 168e51e0e81SBarry Smith 169fee21e36SBarry Smith Collective on MPI_Comm 170fee21e36SBarry Smith 171f39d1f56SLois Curfman McInnes Usage: 172f39d1f56SLois Curfman McInnes $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 1731c1c02c0SLois Curfman McInnes $ MatShellSetOperation(mat,MATOP_MULT,mult); 174f39d1f56SLois Curfman McInnes $ [ Use matrix for operations that have been set ] 175f39d1f56SLois Curfman McInnes $ MatDestroy(mat); 176f39d1f56SLois Curfman McInnes 177ff756334SLois Curfman McInnes Notes: 178ff756334SLois Curfman McInnes The shell matrix type is intended to provide a simple class to use 179ff756334SLois Curfman McInnes with KSP (such as, for use with matrix-free methods). You should not 180ff756334SLois Curfman McInnes use the shell type if you plan to define a complete matrix class. 181e51e0e81SBarry Smith 182f39d1f56SLois Curfman McInnes PETSc requires that matrices and vectors being used for certain 183f39d1f56SLois Curfman McInnes operations are partitioned accordingly. For example, when 184645985a0SLois Curfman McInnes creating a shell matrix, A, that supports parallel matrix-vector 185645985a0SLois Curfman McInnes products using MatMult(A,x,y) the user should set the number 186645985a0SLois Curfman McInnes of local matrix rows to be the number of local elements of the 187645985a0SLois Curfman McInnes corresponding result vector, y. Note that this is information is 188645985a0SLois Curfman McInnes required for use of the matrix interface routines, even though 189645985a0SLois Curfman McInnes the shell matrix may not actually be physically partitioned. 190645985a0SLois Curfman McInnes For example, 191f39d1f56SLois Curfman McInnes 192f39d1f56SLois Curfman McInnes $ 193f39d1f56SLois Curfman McInnes $ Vec x, y 194645985a0SLois Curfman McInnes $ Mat A 195f39d1f56SLois Curfman McInnes $ 196522c5e43SBarry Smith $ VecCreate(comm,PETSC_DECIDE,M,&y); 197522c5e43SBarry Smith $ VecCreate(comm,PETSC_DECIDE,N,&x); 198f39d1f56SLois Curfman McInnes $ VecGetLocalSize(y,&m); 199645985a0SLois Curfman McInnes $ MatCreateShell(comm,m,N,M,N,ctx,&A); 2001c1c02c0SLois Curfman McInnes $ MatShellSetOperation(mat,MATOP_MULT,mult); 201645985a0SLois Curfman McInnes $ MatMult(A,x,y); 202645985a0SLois Curfman McInnes $ MatDestroy(A); 203f39d1f56SLois Curfman McInnes $ VecDestroy(y); VecDestroy(x); 204645985a0SLois Curfman McInnes $ 205e51e0e81SBarry Smith 2060b627109SLois Curfman McInnes .keywords: matrix, shell, create 2070b627109SLois Curfman McInnes 2083a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 209e51e0e81SBarry Smith @*/ 210f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 211e51e0e81SBarry Smith { 21244cd7ae7SLois Curfman McInnes Mat B; 21344cd7ae7SLois Curfman McInnes Mat_Shell *b; 214ed3cc1f0SBarry Smith 2153a40ed3dSBarry Smith PetscFunctionBegin; 216f830108cSBarry Smith PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView); 21744cd7ae7SLois Curfman McInnes PLogObjectCreate(B); 21844cd7ae7SLois Curfman McInnes B->factor = 0; 21944cd7ae7SLois Curfman McInnes B->assembled = PETSC_TRUE; 220f830108cSBarry Smith PetscMemcpy(B->ops,&MatOps,sizeof(struct _MatOps)); 221e1311b90SBarry Smith B->ops->destroy = MatDestroy_Shell; 222227d817aSBarry Smith 22344cd7ae7SLois Curfman McInnes b = PetscNew(Mat_Shell); CHKPTRQ(b); 224eed86810SBarry Smith PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell)); 22544cd7ae7SLois Curfman McInnes PetscMemzero(b,sizeof(Mat_Shell)); 22644cd7ae7SLois Curfman McInnes B->data = (void *) b; 227f39d1f56SLois Curfman McInnes b->M = M; B->M = M; 228f39d1f56SLois Curfman McInnes b->N = N; B->N = N; 229f39d1f56SLois Curfman McInnes b->m = m; B->m = m; 230f39d1f56SLois Curfman McInnes b->n = n; B->n = n; 23144cd7ae7SLois Curfman McInnes b->ctx = ctx; 23244cd7ae7SLois Curfman McInnes *A = B; 2333a40ed3dSBarry Smith PetscFunctionReturn(0); 234e51e0e81SBarry Smith } 235e51e0e81SBarry Smith 2365615d1e5SSatish Balay #undef __FUNC__ 237d4bb536fSBarry Smith #define __FUNC__ "MatShellSetOperation" 238c16cb8f2SBarry Smith /*@C 2393a3eedf2SBarry Smith MatShellSetOperation - Allows user to set a matrix operation for 2403a3eedf2SBarry Smith a shell matrix. 241e51e0e81SBarry Smith 242e51e0e81SBarry Smith Input Parameters: 243fae171e0SBarry Smith . mat - the shell matrix 244fae171e0SBarry Smith . op - the name of the operation 245fae171e0SBarry Smith . f - the function that provides the operation. 246e51e0e81SBarry Smith 247fee21e36SBarry Smith Collective on Mat 248fee21e36SBarry Smith 249fae171e0SBarry Smith Usage: 250a62d957aSLois Curfman McInnes $ extern int usermult(Mat,Vec,Vec); 251f39d1f56SLois Curfman McInnes $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 2521c1c02c0SLois Curfman McInnes $ ierr = MatShellSetOperation(A,MATOP_MULT,usermult); 2530b627109SLois Curfman McInnes 254a62d957aSLois Curfman McInnes Notes: 255a62d957aSLois Curfman McInnes See the file petsc/include/mat.h for a complete list of matrix 2561c1c02c0SLois Curfman McInnes operations, which all have the form MATOP_<OPERATION>, where 257a62d957aSLois Curfman McInnes <OPERATION> is the name (in all capital letters) of the 2581c1c02c0SLois Curfman McInnes user interface routine (e.g., MatMult() -> MATOP_MULT). 259a62d957aSLois Curfman McInnes 260a62d957aSLois Curfman McInnes All user-provided functions should have the same calling 261deebb3c3SLois Curfman McInnes sequence as the usual matrix interface routines, since they 262deebb3c3SLois Curfman McInnes are intended to be accessed via the usual matrix interface 263deebb3c3SLois Curfman McInnes routines, e.g., 264a62d957aSLois Curfman McInnes $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 265a62d957aSLois Curfman McInnes 266a62d957aSLois Curfman McInnes Within each user-defined routine, the user should call 267a62d957aSLois Curfman McInnes MatShellGetContext() to obtain the user-defined context that was 268a62d957aSLois Curfman McInnes set by MatCreateShell(). 269a62d957aSLois Curfman McInnes 270a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation 271a62d957aSLois Curfman McInnes 272d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation() 273e51e0e81SBarry Smith @*/ 274fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f) 275e51e0e81SBarry Smith { 2763a40ed3dSBarry Smith PetscFunctionBegin; 27777c4ece6SBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 278fae171e0SBarry Smith 2791c1c02c0SLois Curfman McInnes if (op == MATOP_DESTROY) { 280a62d957aSLois Curfman McInnes if (mat->type == MATSHELL) { 281a62d957aSLois Curfman McInnes Mat_Shell *shell = (Mat_Shell *) mat->data; 2823a3eedf2SBarry Smith shell->destroy = (int (*)(Mat)) f; 283a62d957aSLois Curfman McInnes } 284e1311b90SBarry Smith else mat->ops->destroy = (int (*)(Mat)) f; 285a62d957aSLois Curfman McInnes } 286e1311b90SBarry Smith else if (op == MATOP_VIEW) mat->ops->view = (int (*)(Mat,Viewer)) f; 287f830108cSBarry Smith else (((void**)mat->ops)[op]) = f; 288a62d957aSLois Curfman McInnes 2893a40ed3dSBarry Smith PetscFunctionReturn(0); 290e51e0e81SBarry Smith } 291f0479e8cSBarry Smith 292d4bb536fSBarry Smith #undef __FUNC__ 293d4bb536fSBarry Smith #define __FUNC__ "MatShellGetOperation" 294d4bb536fSBarry Smith /*@C 295d4bb536fSBarry Smith MatShellGetOperation - Gets a matrix function for a shell matrix. 296d4bb536fSBarry Smith 297d4bb536fSBarry Smith Input Parameters: 298d4bb536fSBarry Smith . mat - the shell matrix 299d4bb536fSBarry Smith . op - the name of the operation 300d4bb536fSBarry Smith 301d4bb536fSBarry Smith Output Parameter: 302d4bb536fSBarry Smith . f - the function that provides the operation. 303d4bb536fSBarry Smith 304fee21e36SBarry Smith Not Collective 305fee21e36SBarry Smith 306d4bb536fSBarry Smith Notes: 307d4bb536fSBarry Smith See the file petsc/include/mat.h for a complete list of matrix 308d4bb536fSBarry Smith operations, which all have the form MATOP_<OPERATION>, where 309d4bb536fSBarry Smith <OPERATION> is the name (in all capital letters) of the 310d4bb536fSBarry Smith user interface routine (e.g., MatMult() -> MATOP_MULT). 311d4bb536fSBarry Smith 312d4bb536fSBarry Smith All user-provided functions have the same calling 313d4bb536fSBarry Smith sequence as the usual matrix interface routines, since they 314d4bb536fSBarry Smith are intended to be accessed via the usual matrix interface 315d4bb536fSBarry Smith routines, e.g., 316d4bb536fSBarry Smith $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 317d4bb536fSBarry Smith 318d4bb536fSBarry Smith Within each user-defined routine, the user should call 319d4bb536fSBarry Smith MatShellGetContext() to obtain the user-defined context that was 320d4bb536fSBarry Smith set by MatCreateShell(). 321d4bb536fSBarry Smith 322d4bb536fSBarry Smith .keywords: matrix, shell, set, operation 323d4bb536fSBarry Smith 324d4bb536fSBarry Smith .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation() 325d4bb536fSBarry Smith @*/ 326d4bb536fSBarry Smith int MatShellGetOperation(Mat mat,MatOperation op, void **f) 327d4bb536fSBarry Smith { 3283a40ed3dSBarry Smith PetscFunctionBegin; 329d4bb536fSBarry Smith PetscValidHeaderSpecific(mat,MAT_COOKIE); 330d4bb536fSBarry Smith 331d4bb536fSBarry Smith if (op == MATOP_DESTROY) { 332d4bb536fSBarry Smith if (mat->type == MATSHELL) { 333d4bb536fSBarry Smith Mat_Shell *shell = (Mat_Shell *) mat->data; 334d4bb536fSBarry Smith *f = (void *) shell->destroy; 335d4bb536fSBarry Smith } 336e1311b90SBarry Smith else *f = (void *) mat->ops->destroy; 337d4bb536fSBarry Smith } 338e1311b90SBarry Smith else if (op == MATOP_VIEW) *f = (void *) mat->ops->view; 339d4bb536fSBarry Smith else *f = (((void**)&mat->ops)[op]); 340d4bb536fSBarry Smith 3413a40ed3dSBarry Smith PetscFunctionReturn(0); 342d4bb536fSBarry Smith } 343d4bb536fSBarry Smith 344