1 #ifndef lint 2 static char vcid[] = "$Id: shell.c,v 1.32 1996/04/07 22:47:23 curfman Exp curfman $"; 3 #endif 4 5 /* 6 This provides a simple shell for Fortran (and C programmers) to 7 create a very simple matrix class for use with KSP without coding 8 much of anything. 9 */ 10 11 #include "petsc.h" 12 #include "matimpl.h" /*I "mat.h" I*/ 13 #include "vec/vecimpl.h" 14 15 typedef struct { 16 int M, N; /* number of global rows, columns */ 17 int m, n; /* number of local rows, columns */ 18 int (*destroy)(Mat); 19 void *ctx; 20 } Mat_Shell; 21 22 /*@ 23 MatShellGetContext - Returns the user-provided context associated with a shell matrix. 24 25 Input Parameter: 26 . mat - the matrix, should have been created with MatCreateShell() 27 28 Output Parameter: 29 . ctx - the user provided context 30 31 Notes: 32 This routine is intended for use within various shell matrix routines, 33 as set with MatShellSetOperation(). 34 35 .keywords: matrix, shell, get, context 36 37 .seealso: MatCreateShell(), MatShellSetOperation() 38 @*/ 39 int MatShellGetContext(Mat mat,void **ctx) 40 { 41 PetscValidHeaderSpecific(mat,MAT_COOKIE); 42 if (mat->type != MATSHELL) *ctx = 0; 43 else *ctx = ((Mat_Shell *) (mat->data))->ctx; 44 return 0; 45 } 46 47 static int MatGetSize_Shell(Mat mat,int *M,int *N) 48 { 49 Mat_Shell *shell = (Mat_Shell *) mat->data; 50 *M = shell->M; *N = shell->N; 51 return 0; 52 } 53 54 static int MatGetLocalSize_Shell(Mat mat,int *m,int *n) 55 { 56 Mat_Shell *shell = (Mat_Shell *) mat->data; 57 *m = shell->n; *n = shell->n; 58 return 0; 59 } 60 61 static int MatDestroy_Shell(PetscObject obj) 62 { 63 int ierr; 64 Mat mat = (Mat) obj; 65 Mat_Shell *shell; 66 67 shell = (Mat_Shell *) mat->data; 68 if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);} 69 PetscFree(shell); 70 PLogObjectDestroy(mat); 71 PetscHeaderDestroy(mat); 72 return 0; 73 } 74 75 static struct _MatOps MatOps = {0,0, 76 0, 77 0,0,0,0, 78 0,0,0,0, 79 0,0, 80 0, 81 0, 82 0,0,0, 83 0, 84 0,0,0, 85 0,0, 86 0, 87 0,0,0,0, 88 0,0,MatGetSize_Shell,MatGetLocalSize_Shell, 89 0,0,0, 90 0,0,0,0 }; 91 92 /*@C 93 MatCreateShell - Creates a new matrix class for use with a user-defined 94 private data storage format. 95 96 Input Parameters: 97 . comm - MPI communicator 98 . m - number of local rows 99 . n - number of local columns 100 . M - number of global rows 101 . N - number of global columns 102 . ctx - pointer to data needed by the shell matrix routines 103 104 Output Parameter: 105 . A - the matrix 106 107 Usage: 108 $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 109 $ MatShellSetOperation(mat,MAT_MULT,mult); 110 $ [ Use matrix for operations that have been set ] 111 $ MatDestroy(mat); 112 113 Notes: 114 The shell matrix type is intended to provide a simple class to use 115 with KSP (such as, for use with matrix-free methods). You should not 116 use the shell type if you plan to define a complete matrix class. 117 118 PETSc requires that matrices and vectors being used for certain 119 operations are partitioned accordingly. For example, when 120 creating a shell matrix that supports parallel matrix-vector 121 products using MatMult(), the user should set the number of local 122 matrix rows to be the same as the corresponding result vector 123 (even though the shell matrix may not actually be physically 124 partitioned or even stored at all). For example, 125 126 $ /* Create matrix and vectors to compute y = Ax */ 127 $ 128 $ Vec x, y 129 $ Mat mat 130 $ 131 $ VecCreate(comm,M,&y); 132 $ VecCreate(comm,N,&x); 133 $ VecGetLocalSize(y,&m); 134 $ MatCreateShell(comm,m,N,M,N,ctx,&mat); 135 $ MatShellSetOperation(mat,MAT_MULT,mult); 136 $ MatMult(mat,x,y); 137 $ MatDestroy(mat); 138 $ VecDestroy(y); VecDestroy(x); 139 140 .keywords: matrix, shell, create 141 142 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 143 @*/ 144 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 145 { 146 Mat B; 147 Mat_Shell *b; 148 149 PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm); 150 PLogObjectCreate(B); 151 B->factor = 0; 152 B->destroy = MatDestroy_Shell; 153 B->assembled = PETSC_TRUE; 154 PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps)); 155 156 b = PetscNew(Mat_Shell); CHKPTRQ(b); 157 PetscMemzero(b,sizeof(Mat_Shell)); 158 B->data = (void *) b; 159 b->M = M; B->M = M; 160 b->N = N; B->N = N; 161 b->m = m; B->m = m; 162 b->n = n; B->n = n; 163 b->ctx = ctx; 164 *A = B; 165 return 0; 166 } 167 168 /*@ 169 MatShellSetOperation - Allows user to set a matrix operation for 170 a shell matrix. 171 172 Input Parameters: 173 . mat - the shell matrix 174 . op - the name of the operation 175 . f - the function that provides the operation. 176 177 Usage: 178 $ extern int usermult(Mat,Vec,Vec); 179 $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 180 $ ierr = MatShellSetOperation(A,MAT_MULT,usermult); 181 182 Notes: 183 See the file petsc/include/mat.h for a complete list of matrix 184 operations, which all have the form MAT_<OPERATION>, where 185 <OPERATION> is the name (in all capital letters) of the 186 user interface routine (e.g., MatMult() -> MAT_MULT). 187 188 All user-provided functions should have the same calling 189 sequence as the usual matrix interface routines, since they 190 are intended to be accessed via the usual matrix interface 191 routines, e.g., 192 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 193 194 Within each user-defined routine, the user should call 195 MatShellGetContext() to obtain the user-defined context that was 196 set by MatCreateShell(). 197 198 .keywords: matrix, shell, set, operation 199 200 .seealso: MatCreateShell(), MatShellGetContext() 201 @*/ 202 int MatShellSetOperation(Mat mat,MatOperation op, void *f) 203 { 204 PetscValidHeaderSpecific(mat,MAT_COOKIE); 205 206 if (op == MAT_DESTROY) { 207 if (mat->type == MATSHELL) { 208 Mat_Shell *shell = (Mat_Shell *) mat->data; 209 shell->destroy = (int (*)(Mat)) f; 210 } 211 else mat->destroy = (int (*)(PetscObject)) f; 212 } 213 else if (op == MAT_VIEW) mat->view = (int (*)(PetscObject,Viewer)) f; 214 else (((void **)&mat->ops)[op]) = f; 215 216 return 0; 217 } 218 219 220 221 222 223 224