1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: shell.c,v 1.58 1998/07/13 20:36:26 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 if (mat->rmap) { 93 ierr = MapDestroy(mat->rmap);CHKERRQ(ierr); 94 } 95 if (mat->cmap) { 96 ierr = MapDestroy(mat->cmap);CHKERRQ(ierr); 97 } 98 shell = (Mat_Shell *) mat->data; 99 if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);} 100 PetscFree(shell); 101 PLogObjectDestroy(mat); 102 PetscHeaderDestroy(mat); 103 PetscFunctionReturn(0); 104 } 105 106 int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend) 107 { 108 int ierr; 109 110 PetscFunctionBegin; 111 ierr = MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr); 112 *rstart = *rend - mat->m; 113 PetscFunctionReturn(0); 114 } 115 116 117 118 119 static struct _MatOps MatOps_Values = {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 0, 144 0, 145 0, 146 0, 147 0, 148 0, 149 MatGetSize_Shell, 150 MatGetLocalSize_Shell, 151 MatGetOwnershipRange_Shell, 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 0, 179 0, 180 0, 181 0, 182 0, 183 0, 184 MatGetMaps_Petsc}; 185 186 #undef __FUNC__ 187 #define __FUNC__ "MatCreateShell" 188 /*@C 189 MatCreateShell - Creates a new matrix class for use with a user-defined 190 private data storage format. 191 192 Input Parameters: 193 . comm - MPI communicator 194 . m - number of local rows 195 . n - number of local columns 196 . M - number of global rows 197 . N - number of global columns 198 . ctx - pointer to data needed by the shell matrix routines 199 200 Output Parameter: 201 . A - the matrix 202 203 Collective on MPI_Comm 204 205 Usage: 206 $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 207 $ MatShellSetOperation(mat,MATOP_MULT,mult); 208 $ [ Use matrix for operations that have been set ] 209 $ MatDestroy(mat); 210 211 Notes: 212 The shell matrix type is intended to provide a simple class to use 213 with KSP (such as, for use with matrix-free methods). You should not 214 use the shell type if you plan to define a complete matrix class. 215 216 PETSc requires that matrices and vectors being used for certain 217 operations are partitioned accordingly. For example, when 218 creating a shell matrix, A, that supports parallel matrix-vector 219 products using MatMult(A,x,y) the user should set the number 220 of local matrix rows to be the number of local elements of the 221 corresponding result vector, y. Note that this is information is 222 required for use of the matrix interface routines, even though 223 the shell matrix may not actually be physically partitioned. 224 For example, 225 226 $ 227 $ Vec x, y 228 $ Mat A 229 $ 230 $ VecCreate(comm,PETSC_DECIDE,M,&y); 231 $ VecCreate(comm,PETSC_DECIDE,N,&x); 232 $ VecGetLocalSize(y,&m); 233 $ MatCreateShell(comm,m,N,M,N,ctx,&A); 234 $ MatShellSetOperation(mat,MATOP_MULT,mult); 235 $ MatMult(A,x,y); 236 $ MatDestroy(A); 237 $ VecDestroy(y); VecDestroy(x); 238 $ 239 240 .keywords: matrix, shell, create 241 242 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 243 @*/ 244 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 245 { 246 Mat B; 247 Mat_Shell *b; 248 249 PetscFunctionBegin; 250 PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView); 251 PLogObjectCreate(B); 252 B->factor = 0; 253 B->assembled = PETSC_TRUE; 254 PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps)); 255 B->ops->destroy = MatDestroy_Shell; 256 257 b = PetscNew(Mat_Shell); CHKPTRQ(b); 258 PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell)); 259 PetscMemzero(b,sizeof(Mat_Shell)); 260 B->data = (void *) b; 261 b->M = M; B->M = M; 262 b->N = N; B->N = N; 263 b->m = m; B->m = m; 264 b->n = n; B->n = n; 265 b->ctx = ctx; 266 *A = B; 267 PetscFunctionReturn(0); 268 } 269 270 #undef __FUNC__ 271 #define __FUNC__ "MatShellSetOperation" 272 /*@C 273 MatShellSetOperation - Allows user to set a matrix operation for 274 a shell matrix. 275 276 Input Parameters: 277 . mat - the shell matrix 278 . op - the name of the operation 279 . f - the function that provides the operation. 280 281 Collective on Mat 282 283 Usage: 284 $ extern int usermult(Mat,Vec,Vec); 285 $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 286 $ ierr = MatShellSetOperation(A,MATOP_MULT,usermult); 287 288 Notes: 289 See the file petsc/include/mat.h for a complete list of matrix 290 operations, which all have the form MATOP_<OPERATION>, where 291 <OPERATION> is the name (in all capital letters) of the 292 user interface routine (e.g., MatMult() -> MATOP_MULT). 293 294 All user-provided functions should have the same calling 295 sequence as the usual matrix interface routines, since they 296 are intended to be accessed via the usual matrix interface 297 routines, e.g., 298 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 299 300 Within each user-defined routine, the user should call 301 MatShellGetContext() to obtain the user-defined context that was 302 set by MatCreateShell(). 303 304 .keywords: matrix, shell, set, operation 305 306 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation() 307 @*/ 308 int MatShellSetOperation(Mat mat,MatOperation op, void *f) 309 { 310 PetscFunctionBegin; 311 PetscValidHeaderSpecific(mat,MAT_COOKIE); 312 313 if (op == MATOP_DESTROY) { 314 if (mat->type == MATSHELL) { 315 Mat_Shell *shell = (Mat_Shell *) mat->data; 316 shell->destroy = (int (*)(Mat)) f; 317 } 318 else mat->ops->destroy = (int (*)(Mat)) f; 319 } 320 else if (op == MATOP_VIEW) mat->ops->view = (int (*)(Mat,Viewer)) f; 321 else (((void**)mat->ops)[op]) = f; 322 323 PetscFunctionReturn(0); 324 } 325 326 #undef __FUNC__ 327 #define __FUNC__ "MatShellGetOperation" 328 /*@C 329 MatShellGetOperation - Gets a matrix function for a shell matrix. 330 331 Input Parameters: 332 . mat - the shell matrix 333 . op - the name of the operation 334 335 Output Parameter: 336 . f - the function that provides the operation. 337 338 Not Collective 339 340 Notes: 341 See the file petsc/include/mat.h for a complete list of matrix 342 operations, which all have the form MATOP_<OPERATION>, where 343 <OPERATION> is the name (in all capital letters) of the 344 user interface routine (e.g., MatMult() -> MATOP_MULT). 345 346 All user-provided functions have the same calling 347 sequence as the usual matrix interface routines, since they 348 are intended to be accessed via the usual matrix interface 349 routines, e.g., 350 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 351 352 Within each user-defined routine, the user should call 353 MatShellGetContext() to obtain the user-defined context that was 354 set by MatCreateShell(). 355 356 .keywords: matrix, shell, set, operation 357 358 .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation() 359 @*/ 360 int MatShellGetOperation(Mat mat,MatOperation op, void **f) 361 { 362 PetscFunctionBegin; 363 PetscValidHeaderSpecific(mat,MAT_COOKIE); 364 365 if (op == MATOP_DESTROY) { 366 if (mat->type == MATSHELL) { 367 Mat_Shell *shell = (Mat_Shell *) mat->data; 368 *f = (void *) shell->destroy; 369 } 370 else *f = (void *) mat->ops->destroy; 371 } 372 else if (op == MATOP_VIEW) *f = (void *) mat->ops->view; 373 else *f = (((void**)&mat->ops)[op]); 374 375 PetscFunctionReturn(0); 376 } 377 378