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