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