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