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