1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: shell.c,v 1.56 1998/04/13 17:37:39 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 = {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 152 #undef __FUNC__ 153 #define __FUNC__ "MatCreateShell" 154 /*@C 155 MatCreateShell - Creates a new matrix class for use with a user-defined 156 private data storage format. 157 158 Input Parameters: 159 . comm - MPI communicator 160 . m - number of local rows 161 . n - number of local columns 162 . M - number of global rows 163 . N - number of global columns 164 . ctx - pointer to data needed by the shell matrix routines 165 166 Output Parameter: 167 . A - the matrix 168 169 Collective on MPI_Comm 170 171 Usage: 172 $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 173 $ MatShellSetOperation(mat,MATOP_MULT,mult); 174 $ [ Use matrix for operations that have been set ] 175 $ MatDestroy(mat); 176 177 Notes: 178 The shell matrix type is intended to provide a simple class to use 179 with KSP (such as, for use with matrix-free methods). You should not 180 use the shell type if you plan to define a complete matrix class. 181 182 PETSc requires that matrices and vectors being used for certain 183 operations are partitioned accordingly. For example, when 184 creating a shell matrix, A, that supports parallel matrix-vector 185 products using MatMult(A,x,y) the user should set the number 186 of local matrix rows to be the number of local elements of the 187 corresponding result vector, y. Note that this is information is 188 required for use of the matrix interface routines, even though 189 the shell matrix may not actually be physically partitioned. 190 For example, 191 192 $ 193 $ Vec x, y 194 $ Mat A 195 $ 196 $ VecCreate(comm,PETSC_DECIDE,M,&y); 197 $ VecCreate(comm,PETSC_DECIDE,N,&x); 198 $ VecGetLocalSize(y,&m); 199 $ MatCreateShell(comm,m,N,M,N,ctx,&A); 200 $ MatShellSetOperation(mat,MATOP_MULT,mult); 201 $ MatMult(A,x,y); 202 $ MatDestroy(A); 203 $ VecDestroy(y); VecDestroy(x); 204 $ 205 206 .keywords: matrix, shell, create 207 208 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 209 @*/ 210 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 211 { 212 Mat B; 213 Mat_Shell *b; 214 215 PetscFunctionBegin; 216 PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView); 217 PLogObjectCreate(B); 218 B->factor = 0; 219 B->assembled = PETSC_TRUE; 220 PetscMemcpy(B->ops,&MatOps,sizeof(struct _MatOps)); 221 B->ops->destroy = MatDestroy_Shell; 222 223 b = PetscNew(Mat_Shell); CHKPTRQ(b); 224 PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell)); 225 PetscMemzero(b,sizeof(Mat_Shell)); 226 B->data = (void *) b; 227 b->M = M; B->M = M; 228 b->N = N; B->N = N; 229 b->m = m; B->m = m; 230 b->n = n; B->n = n; 231 b->ctx = ctx; 232 *A = B; 233 PetscFunctionReturn(0); 234 } 235 236 #undef __FUNC__ 237 #define __FUNC__ "MatShellSetOperation" 238 /*@C 239 MatShellSetOperation - Allows user to set a matrix operation for 240 a shell matrix. 241 242 Input Parameters: 243 . mat - the shell matrix 244 . op - the name of the operation 245 . f - the function that provides the operation. 246 247 Collective on Mat 248 249 Usage: 250 $ extern int usermult(Mat,Vec,Vec); 251 $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 252 $ ierr = MatShellSetOperation(A,MATOP_MULT,usermult); 253 254 Notes: 255 See the file petsc/include/mat.h for a complete list of matrix 256 operations, which all have the form MATOP_<OPERATION>, where 257 <OPERATION> is the name (in all capital letters) of the 258 user interface routine (e.g., MatMult() -> MATOP_MULT). 259 260 All user-provided functions should have the same calling 261 sequence as the usual matrix interface routines, since they 262 are intended to be accessed via the usual matrix interface 263 routines, e.g., 264 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 265 266 Within each user-defined routine, the user should call 267 MatShellGetContext() to obtain the user-defined context that was 268 set by MatCreateShell(). 269 270 .keywords: matrix, shell, set, operation 271 272 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation() 273 @*/ 274 int MatShellSetOperation(Mat mat,MatOperation op, void *f) 275 { 276 PetscFunctionBegin; 277 PetscValidHeaderSpecific(mat,MAT_COOKIE); 278 279 if (op == MATOP_DESTROY) { 280 if (mat->type == MATSHELL) { 281 Mat_Shell *shell = (Mat_Shell *) mat->data; 282 shell->destroy = (int (*)(Mat)) f; 283 } 284 else mat->ops->destroy = (int (*)(Mat)) f; 285 } 286 else if (op == MATOP_VIEW) mat->ops->view = (int (*)(Mat,Viewer)) f; 287 else (((void**)mat->ops)[op]) = f; 288 289 PetscFunctionReturn(0); 290 } 291 292 #undef __FUNC__ 293 #define __FUNC__ "MatShellGetOperation" 294 /*@C 295 MatShellGetOperation - Gets a matrix function for a shell matrix. 296 297 Input Parameters: 298 . mat - the shell matrix 299 . op - the name of the operation 300 301 Output Parameter: 302 . f - the function that provides the operation. 303 304 Not Collective 305 306 Notes: 307 See the file petsc/include/mat.h for a complete list of matrix 308 operations, which all have the form MATOP_<OPERATION>, where 309 <OPERATION> is the name (in all capital letters) of the 310 user interface routine (e.g., MatMult() -> MATOP_MULT). 311 312 All user-provided functions have the same calling 313 sequence as the usual matrix interface routines, since they 314 are intended to be accessed via the usual matrix interface 315 routines, e.g., 316 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 317 318 Within each user-defined routine, the user should call 319 MatShellGetContext() to obtain the user-defined context that was 320 set by MatCreateShell(). 321 322 .keywords: matrix, shell, set, operation 323 324 .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation() 325 @*/ 326 int MatShellGetOperation(Mat mat,MatOperation op, void **f) 327 { 328 PetscFunctionBegin; 329 PetscValidHeaderSpecific(mat,MAT_COOKIE); 330 331 if (op == MATOP_DESTROY) { 332 if (mat->type == MATSHELL) { 333 Mat_Shell *shell = (Mat_Shell *) mat->data; 334 *f = (void *) shell->destroy; 335 } 336 else *f = (void *) mat->ops->destroy; 337 } 338 else if (op == MATOP_VIEW) *f = (void *) mat->ops->view; 339 else *f = (((void**)&mat->ops)[op]); 340 341 PetscFunctionReturn(0); 342 } 343 344