1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: shell.c,v 1.53 1997/11/28 16:19:55 bsmith Exp bsmith $"; 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 "src/mat/matimpl.h" /*I "mat.h" I*/ 13 #include "src/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 #undef __FUNC__ 23 #define __FUNC__ "MatShellGetContext" 24 /*@ 25 MatShellGetContext - Returns the user-provided context associated with a shell matrix. 26 27 Input Parameter: 28 . mat - the matrix, should have been created with MatCreateShell() 29 30 Output Parameter: 31 . ctx - the user provided context 32 33 Notes: 34 This routine is intended for use within various shell matrix routines, 35 as set with MatShellSetOperation(). 36 37 .keywords: matrix, shell, get, context 38 39 .seealso: MatCreateShell(), MatShellSetOperation() 40 @*/ 41 int MatShellGetContext(Mat mat,void **ctx) 42 { 43 PetscFunctionBegin; 44 PetscValidHeaderSpecific(mat,MAT_COOKIE); 45 if (mat->type != MATSHELL) *ctx = 0; 46 else *ctx = ((Mat_Shell *) (mat->data))->ctx; 47 PetscFunctionReturn(0); 48 } 49 50 #undef __FUNC__ 51 #define __FUNC__ "MatGetSize_Shell" 52 int MatGetSize_Shell(Mat mat,int *M,int *N) 53 { 54 Mat_Shell *shell = (Mat_Shell *) mat->data; 55 56 PetscFunctionBegin; 57 if (M) *M = shell->M; 58 if (N) *N = shell->N; 59 PetscFunctionReturn(0); 60 } 61 62 #undef __FUNC__ 63 #define __FUNC__ "MatGetLocalSize_Shell" 64 int MatGetLocalSize_Shell(Mat mat,int *m,int *n) 65 { 66 Mat_Shell *shell = (Mat_Shell *) mat->data; 67 68 PetscFunctionBegin; 69 if (m) *m = shell->m; 70 if (n) *n = shell->n; 71 PetscFunctionReturn(0); 72 } 73 74 #undef __FUNC__ 75 #define __FUNC__ "MatDestroy_Shell" 76 int MatDestroy_Shell(PetscObject obj) 77 { 78 int ierr; 79 Mat mat = (Mat) obj; 80 Mat_Shell *shell; 81 82 PetscFunctionBegin; 83 shell = (Mat_Shell *) mat->data; 84 if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);} 85 PetscFree(shell); 86 PLogObjectDestroy(mat); 87 PetscHeaderDestroy(mat); 88 PetscFunctionReturn(0); 89 } 90 91 int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend) 92 { 93 int ierr; 94 95 PetscFunctionBegin; 96 ierr = MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr); 97 *rstart = *rend - mat->m; 98 PetscFunctionReturn(0); 99 } 100 101 102 103 104 static struct _MatOps MatOps = {0, 105 0, 106 0, 107 0, 108 0, 109 0, 110 0, 111 0, 112 0, 113 0, 114 0, 115 0, 116 0, 117 0, 118 0, 119 0, 120 0, 121 0, 122 0, 123 0, 124 0, 125 0, 126 0, 127 0, 128 0, 129 0, 130 0, 131 0, 132 0, 133 0, 134 MatGetSize_Shell, 135 MatGetLocalSize_Shell, 136 MatGetOwnershipRange_Shell, 137 0, 138 0, 139 0, 140 0, 141 0 }; 142 143 #undef __FUNC__ 144 #define __FUNC__ "MatCreateShell" 145 /*@C 146 MatCreateShell - Creates a new matrix class for use with a user-defined 147 private data storage format. 148 149 Input Parameters: 150 . comm - MPI communicator 151 . m - number of local rows 152 . n - number of local columns 153 . M - number of global rows 154 . N - number of global columns 155 . ctx - pointer to data needed by the shell matrix routines 156 157 Output Parameter: 158 . A - the matrix 159 160 Usage: 161 $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 162 $ MatShellSetOperation(mat,MATOP_MULT,mult); 163 $ [ Use matrix for operations that have been set ] 164 $ MatDestroy(mat); 165 166 Notes: 167 The shell matrix type is intended to provide a simple class to use 168 with KSP (such as, for use with matrix-free methods). You should not 169 use the shell type if you plan to define a complete matrix class. 170 171 PETSc requires that matrices and vectors being used for certain 172 operations are partitioned accordingly. For example, when 173 creating a shell matrix, A, that supports parallel matrix-vector 174 products using MatMult(A,x,y) the user should set the number 175 of local matrix rows to be the number of local elements of the 176 corresponding result vector, y. Note that this is information is 177 required for use of the matrix interface routines, even though 178 the shell matrix may not actually be physically partitioned. 179 For example, 180 181 $ 182 $ Vec x, y 183 $ Mat A 184 $ 185 $ VecCreate(comm,PETSC_DECIDE,M,&y); 186 $ VecCreate(comm,PETSC_DECIDE,N,&x); 187 $ VecGetLocalSize(y,&m); 188 $ MatCreateShell(comm,m,N,M,N,ctx,&A); 189 $ MatShellSetOperation(mat,MATOP_MULT,mult); 190 $ MatMult(A,x,y); 191 $ MatDestroy(A); 192 $ VecDestroy(y); VecDestroy(x); 193 $ 194 195 .keywords: matrix, shell, create 196 197 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 198 @*/ 199 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 200 { 201 Mat B; 202 Mat_Shell *b; 203 204 PetscFunctionBegin; 205 PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView); 206 PLogObjectCreate(B); 207 B->factor = 0; 208 B->destroy = MatDestroy_Shell; 209 B->assembled = PETSC_TRUE; 210 PetscMemcpy(B->ops,&MatOps,sizeof(struct _MatOps)); 211 212 b = PetscNew(Mat_Shell); CHKPTRQ(b); 213 PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell)); 214 PetscMemzero(b,sizeof(Mat_Shell)); 215 B->data = (void *) b; 216 b->M = M; B->M = M; 217 b->N = N; B->N = N; 218 b->m = m; B->m = m; 219 b->n = n; B->n = n; 220 b->ctx = ctx; 221 *A = B; 222 PetscFunctionReturn(0); 223 } 224 225 #undef __FUNC__ 226 #define __FUNC__ "MatShellSetOperation" 227 /*@C 228 MatShellSetOperation - Allows user to set a matrix operation for 229 a shell matrix. 230 231 Input Parameters: 232 . mat - the shell matrix 233 . op - the name of the operation 234 . f - the function that provides the operation. 235 236 Usage: 237 $ extern int usermult(Mat,Vec,Vec); 238 $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 239 $ ierr = MatShellSetOperation(A,MATOP_MULT,usermult); 240 241 Notes: 242 See the file petsc/include/mat.h for a complete list of matrix 243 operations, which all have the form MATOP_<OPERATION>, where 244 <OPERATION> is the name (in all capital letters) of the 245 user interface routine (e.g., MatMult() -> MATOP_MULT). 246 247 All user-provided functions should have the same calling 248 sequence as the usual matrix interface routines, since they 249 are intended to be accessed via the usual matrix interface 250 routines, e.g., 251 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 252 253 Within each user-defined routine, the user should call 254 MatShellGetContext() to obtain the user-defined context that was 255 set by MatCreateShell(). 256 257 .keywords: matrix, shell, set, operation 258 259 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation() 260 @*/ 261 int MatShellSetOperation(Mat mat,MatOperation op, void *f) 262 { 263 PetscFunctionBegin; 264 PetscValidHeaderSpecific(mat,MAT_COOKIE); 265 266 if (op == MATOP_DESTROY) { 267 if (mat->type == MATSHELL) { 268 Mat_Shell *shell = (Mat_Shell *) mat->data; 269 shell->destroy = (int (*)(Mat)) f; 270 } 271 else mat->destroy = (int (*)(PetscObject)) f; 272 } 273 else if (op == MATOP_VIEW) mat->view = (int (*)(PetscObject,Viewer)) f; 274 else (((void**)mat->ops)[op]) = f; 275 276 PetscFunctionReturn(0); 277 } 278 279 #undef __FUNC__ 280 #define __FUNC__ "MatShellGetOperation" 281 /*@C 282 MatShellGetOperation - Gets a matrix function for a shell matrix. 283 284 Input Parameters: 285 . mat - the shell matrix 286 . op - the name of the operation 287 288 Output Parameter: 289 . f - the function that provides the operation. 290 291 Notes: 292 See the file petsc/include/mat.h for a complete list of matrix 293 operations, which all have the form MATOP_<OPERATION>, where 294 <OPERATION> is the name (in all capital letters) of the 295 user interface routine (e.g., MatMult() -> MATOP_MULT). 296 297 All user-provided functions have the same calling 298 sequence as the usual matrix interface routines, since they 299 are intended to be accessed via the usual matrix interface 300 routines, e.g., 301 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 302 303 Within each user-defined routine, the user should call 304 MatShellGetContext() to obtain the user-defined context that was 305 set by MatCreateShell(). 306 307 .keywords: matrix, shell, set, operation 308 309 .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation() 310 @*/ 311 int MatShellGetOperation(Mat mat,MatOperation op, void **f) 312 { 313 PetscFunctionBegin; 314 PetscValidHeaderSpecific(mat,MAT_COOKIE); 315 316 if (op == MATOP_DESTROY) { 317 if (mat->type == MATSHELL) { 318 Mat_Shell *shell = (Mat_Shell *) mat->data; 319 *f = (void *) shell->destroy; 320 } 321 else *f = (void *) mat->destroy; 322 } 323 else if (op == MATOP_VIEW) *f = (void *) mat->view; 324 else *f = (((void**)&mat->ops)[op]); 325 326 PetscFunctionReturn(0); 327 } 328 329