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