1 /*$Id: shell.c,v 1.84 2001/01/15 21:45:41 bsmith Exp balay $*/ 2 3 /* 4 This provides a simple shell for Fortran (and C programmers) to 5 create a very simple matrix class for use with KSP without coding 6 much of anything. 7 */ 8 9 #include "src/mat/matimpl.h" /*I "petscmat.h" I*/ 10 #include "src/vec/vecimpl.h" 11 12 typedef struct { 13 int (*destroy)(Mat); 14 void *ctx; 15 } Mat_Shell; 16 17 #undef __FUNCT__ 18 #define __FUNCT__ "MatShellGetContext" 19 /*@ 20 MatShellGetContext - Returns the user-provided context associated with a shell matrix. 21 22 Not Collective 23 24 Input Parameter: 25 . mat - the matrix, should have been created with MatCreateShell() 26 27 Output Parameter: 28 . ctx - the user provided context 29 30 Level: advanced 31 32 Notes: 33 This routine is intended for use within various shell matrix routines, 34 as set with MatShellSetOperation(). 35 36 .keywords: matrix, shell, get, context 37 38 .seealso: MatCreateShell(), MatShellSetOperation() 39 @*/ 40 int MatShellGetContext(Mat mat,void **ctx) 41 { 42 int ierr; 43 PetscTruth flg; 44 45 PetscFunctionBegin; 46 PetscValidHeaderSpecific(mat,MAT_COOKIE); 47 ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr); 48 if (!flg) *ctx = 0; 49 else *ctx = ((Mat_Shell*)(mat->data))->ctx; 50 PetscFunctionReturn(0); 51 } 52 53 #undef __FUNCT__ 54 #define __FUNCT__ "MatDestroy_Shell" 55 int MatDestroy_Shell(Mat mat) 56 { 57 int ierr; 58 Mat_Shell *shell; 59 60 PetscFunctionBegin; 61 shell = (Mat_Shell*)mat->data; 62 if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);} 63 ierr = PetscFree(shell);CHKERRQ(ierr); 64 PetscFunctionReturn(0); 65 } 66 67 #undef __FUNCT__ 68 #define __FUNCT__ "MatGetOwnershipRange_Shell" 69 int MatGetOwnershipRange_Shell(Mat mat,int *rstart,int *rend) 70 { 71 int ierr,tmp; 72 73 PetscFunctionBegin; 74 ierr = MPI_Scan(&mat->m,&tmp,1,MPI_INT,MPI_SUM,mat->comm);CHKERRQ(ierr); 75 if (rstart) *rstart = tmp - mat->m; 76 if (rend) *rend = tmp; 77 PetscFunctionReturn(0); 78 } 79 extern int MatConvert_Shell(Mat,MatType,Mat*); 80 81 static struct _MatOps MatOps_Values = {0, 82 0, 83 0, 84 0, 85 0, 86 0, 87 0, 88 0, 89 0, 90 0, 91 0, 92 0, 93 0, 94 0, 95 0, 96 0, 97 0, 98 0, 99 0, 100 0, 101 0, 102 0, 103 0, 104 0, 105 0, 106 0, 107 0, 108 0, 109 0, 110 0, 111 0, 112 MatGetOwnershipRange_Shell, 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 0, 135 0, 136 0, 137 0, 138 0, 139 0, 140 0, 141 0, 142 0, 143 0, 144 MatDestroy_Shell, 145 0, 146 MatGetMaps_Petsc, 147 0, 148 0, 149 0, 150 0, 151 0, 152 0, 153 0, 154 MatConvert_Shell}; 155 156 EXTERN_C_BEGIN 157 #undef __FUNCT__ 158 #define __FUNCT__ "MatCreate_Shell" 159 int MatCreate_Shell(Mat A) 160 { 161 Mat_Shell *b; 162 int ierr; 163 164 PetscFunctionBegin; 165 ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 166 167 ierr = PetscNew(Mat_Shell,&b);CHKERRQ(ierr); 168 PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell)); 169 ierr = PetscMemzero(b,sizeof(Mat_Shell));CHKERRQ(ierr); 170 A->data = (void*)b; 171 172 if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) { 173 SETERRQ(1,"Must give local row and column count for matrix"); 174 } 175 176 ierr = PetscSplitOwnership(A->comm,&A->m,&A->M);CHKERRQ(ierr); 177 ierr = PetscSplitOwnership(A->comm,&A->n,&A->N);CHKERRQ(ierr); 178 179 ierr = MapCreateMPI(A->comm,A->m,A->M,&A->rmap);CHKERRQ(ierr); 180 ierr = MapCreateMPI(A->comm,A->n,A->N,&A->cmap);CHKERRQ(ierr); 181 182 b->ctx = 0; 183 A->assembled = PETSC_TRUE; 184 A->preallocated = PETSC_TRUE; 185 PetscFunctionReturn(0); 186 } 187 EXTERN_C_END 188 189 #undef __FUNCT__ 190 #define __FUNCT__ "MatCreateShell" 191 /*@C 192 MatCreateShell - Creates a new matrix class for use with a user-defined 193 private data storage format. 194 195 Collective on MPI_Comm 196 197 Input Parameters: 198 + comm - MPI communicator 199 . m - number of local rows (must be given) 200 . n - number of local columns (must be given) 201 . M - number of global rows (may be PETSC_DETERMINE) 202 . N - number of global columns (may be PETSC_DETERMINE) 203 - ctx - pointer to data needed by the shell matrix routines 204 205 Output Parameter: 206 . A - the matrix 207 208 Level: advanced 209 210 Usage: 211 $ extern int mult(Mat,Vec,Vec); 212 $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 213 $ MatShellSetOperation(mat,MATOP_MULT,(void *)mult); 214 $ [ Use matrix for operations that have been set ] 215 $ MatDestroy(mat); 216 217 Notes: 218 The shell matrix type is intended to provide a simple class to use 219 with KSP (such as, for use with matrix-free methods). You should not 220 use the shell type if you plan to define a complete matrix class. 221 222 PETSc requires that matrices and vectors being used for certain 223 operations are partitioned accordingly. For example, when 224 creating a shell matrix, A, that supports parallel matrix-vector 225 products using MatMult(A,x,y) the user should set the number 226 of local matrix rows to be the number of local elements of the 227 corresponding result vector, y. Note that this is information is 228 required for use of the matrix interface routines, even though 229 the shell matrix may not actually be physically partitioned. 230 For example, 231 232 $ 233 $ Vec x, y 234 $ extern int mult(Mat,Vec,Vec); 235 $ Mat A 236 $ 237 $ VecCreateMPI(comm,PETSC_DECIDE,M,&y); 238 $ VecCreateMPI(comm,PETSC_DECIDE,N,&x); 239 $ VecGetLocalSize(y,&m); 240 $ VecGetLocalSize(x,&n); 241 $ MatCreateShell(comm,m,n,M,N,ctx,&A); 242 $ MatShellSetOperation(mat,MATOP_MULT,(void *)mult); 243 $ MatMult(A,x,y); 244 $ MatDestroy(A); 245 $ VecDestroy(y); VecDestroy(x); 246 $ 247 248 .keywords: matrix, shell, create 249 250 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 251 @*/ 252 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 253 { 254 int ierr; 255 256 PetscFunctionBegin; 257 ierr = MatCreate(comm,m,n,M,N,A);CHKERRQ(ierr); 258 ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr); 259 ierr = MatShellSetContext(*A,ctx);CHKERRQ(ierr); 260 PetscFunctionReturn(0); 261 } 262 263 #undef __FUNCT__ 264 #define __FUNCT__ "MatShellSetContext" 265 /*@C 266 MatShellSetContext - sets the context for a shell matrix 267 268 Collective on Mat 269 270 Input Parameters: 271 + mat - the shell matrix 272 - ctx - the context 273 274 Level: advanced 275 276 277 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation() 278 @*/ 279 int MatShellSetContext(Mat mat,void *ctx) 280 { 281 Mat_Shell *shell = (Mat_Shell*)mat->data; 282 int ierr; 283 PetscTruth flg; 284 285 PetscFunctionBegin; 286 PetscValidHeaderSpecific(mat,MAT_COOKIE); 287 ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr); 288 if (flg) { 289 shell->ctx = ctx; 290 } 291 PetscFunctionReturn(0); 292 } 293 294 #undef __FUNCT__ 295 #define __FUNCT__ "MatShellSetOperation" 296 /*@C 297 MatShellSetOperation - Allows user to set a matrix operation for 298 a shell matrix. 299 300 Collective on Mat 301 302 Input Parameters: 303 + mat - the shell matrix 304 . op - the name of the operation 305 - f - the function that provides the operation. 306 307 Level: advanced 308 309 Usage: 310 $ extern int usermult(Mat,Vec,Vec); 311 $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 312 $ ierr = MatShellSetOperation(A,MATOP_MULT,(void*) usermult); 313 314 Notes: 315 See the file include/petscmat.h for a complete list of matrix 316 operations, which all have the form MATOP_<OPERATION>, where 317 <OPERATION> is the name (in all capital letters) of the 318 user interface routine (e.g., MatMult() -> MATOP_MULT). 319 320 All user-provided functions should have the same calling 321 sequence as the usual matrix interface routines, since they 322 are intended to be accessed via the usual matrix interface 323 routines, e.g., 324 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 325 326 Within each user-defined routine, the user should call 327 MatShellGetContext() to obtain the user-defined context that was 328 set by MatCreateShell(). 329 330 .keywords: matrix, shell, set, operation 331 332 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation() 333 @*/ 334 int MatShellSetOperation(Mat mat,MatOperation op,void *f) 335 { 336 int ierr; 337 PetscTruth flg; 338 339 PetscFunctionBegin; 340 PetscValidHeaderSpecific(mat,MAT_COOKIE); 341 if (op == MATOP_DESTROY) { 342 ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr); 343 if (flg) { 344 Mat_Shell *shell = (Mat_Shell*)mat->data; 345 shell->destroy = (int (*)(Mat)) f; 346 } else mat->ops->destroy = (int (*)(Mat)) f; 347 } 348 else if (op == MATOP_VIEW) mat->ops->view = (int (*)(Mat,PetscViewer)) f; 349 else (((void**)mat->ops)[op]) = f; 350 351 PetscFunctionReturn(0); 352 } 353 354 #undef __FUNCT__ 355 #define __FUNCT__ "MatShellGetOperation" 356 /*@C 357 MatShellGetOperation - Gets a matrix function for a shell matrix. 358 359 Not Collective 360 361 Input Parameters: 362 + mat - the shell matrix 363 - op - the name of the operation 364 365 Output Parameter: 366 . f - the function that provides the operation. 367 368 Level: advanced 369 370 Notes: 371 See the file include/petscmat.h for a complete list of matrix 372 operations, which all have the form MATOP_<OPERATION>, where 373 <OPERATION> is the name (in all capital letters) of the 374 user interface routine (e.g., MatMult() -> MATOP_MULT). 375 376 All user-provided functions have the same calling 377 sequence as the usual matrix interface routines, since they 378 are intended to be accessed via the usual matrix interface 379 routines, e.g., 380 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 381 382 Within each user-defined routine, the user should call 383 MatShellGetContext() to obtain the user-defined context that was 384 set by MatCreateShell(). 385 386 .keywords: matrix, shell, set, operation 387 388 .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation() 389 @*/ 390 int MatShellGetOperation(Mat mat,MatOperation op,void **f) 391 { 392 int ierr; 393 PetscTruth flg; 394 395 PetscFunctionBegin; 396 PetscValidHeaderSpecific(mat,MAT_COOKIE); 397 if (op == MATOP_DESTROY) { 398 ierr = PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);CHKERRQ(ierr); 399 if (flg) { 400 Mat_Shell *shell = (Mat_Shell*)mat->data; 401 *f = (void*)shell->destroy; 402 } else { 403 *f = (void*)mat->ops->destroy; 404 } 405 } else if (op == MATOP_VIEW) { 406 *f = (void*)mat->ops->view; 407 } else { 408 *f = (((void**)mat->ops)[op]); 409 } 410 411 PetscFunctionReturn(0); 412 } 413 414