1 #ifndef lint 2 static char vcid[] = "$Id: shell.c,v 1.34 1996/04/08 22:11:17 curfman 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 "matimpl.h" /*I "mat.h" I*/ 13 #include "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 /*@ 23 MatShellGetContext - Returns the user-provided context associated with a shell matrix. 24 25 Input Parameter: 26 . mat - the matrix, should have been created with MatCreateShell() 27 28 Output Parameter: 29 . ctx - the user provided context 30 31 Notes: 32 This routine is intended for use within various shell matrix routines, 33 as set with MatShellSetOperation(). 34 35 .keywords: matrix, shell, get, context 36 37 .seealso: MatCreateShell(), MatShellSetOperation() 38 @*/ 39 int MatShellGetContext(Mat mat,void **ctx) 40 { 41 PetscValidHeaderSpecific(mat,MAT_COOKIE); 42 if (mat->type != MATSHELL) *ctx = 0; 43 else *ctx = ((Mat_Shell *) (mat->data))->ctx; 44 return 0; 45 } 46 47 static int MatGetSize_Shell(Mat mat,int *M,int *N) 48 { 49 Mat_Shell *shell = (Mat_Shell *) mat->data; 50 *M = shell->M; *N = shell->N; 51 return 0; 52 } 53 54 static int MatGetLocalSize_Shell(Mat mat,int *m,int *n) 55 { 56 Mat_Shell *shell = (Mat_Shell *) mat->data; 57 *m = shell->n; *n = shell->n; 58 return 0; 59 } 60 61 static int MatDestroy_Shell(PetscObject obj) 62 { 63 int ierr; 64 Mat mat = (Mat) obj; 65 Mat_Shell *shell; 66 67 shell = (Mat_Shell *) mat->data; 68 if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);} 69 PetscFree(shell); 70 PLogObjectDestroy(mat); 71 PetscHeaderDestroy(mat); 72 return 0; 73 } 74 75 static struct _MatOps MatOps = {0,0, 76 0, 77 0,0,0,0, 78 0,0,0,0, 79 0,0, 80 0, 81 0, 82 0,0,0, 83 0, 84 0,0,0, 85 0,0, 86 0, 87 0,0,0,0, 88 0,0,MatGetSize_Shell,MatGetLocalSize_Shell, 89 0,0,0, 90 0,0,0,0 }; 91 92 /*@C 93 MatCreateShell - Creates a new matrix class for use with a user-defined 94 private data storage format. 95 96 Input Parameters: 97 . comm - MPI communicator 98 . m - number of local rows 99 . n - number of local columns 100 . M - number of global rows 101 . N - number of global columns 102 . ctx - pointer to data needed by the shell matrix routines 103 104 Output Parameter: 105 . A - the matrix 106 107 Usage: 108 $ MatCreateShell(comm,m,n,M,N,ctx,&mat); 109 $ MatShellSetOperation(mat,MAT_MULT,mult); 110 $ [ Use matrix for operations that have been set ] 111 $ MatDestroy(mat); 112 113 Notes: 114 The shell matrix type is intended to provide a simple class to use 115 with KSP (such as, for use with matrix-free methods). You should not 116 use the shell type if you plan to define a complete matrix class. 117 118 PETSc requires that matrices and vectors being used for certain 119 operations are partitioned accordingly. For example, when 120 creating a shell matrix, A, that supports parallel matrix-vector 121 products using MatMult(A,x,y) the user should set the number 122 of local matrix rows to be the number of local elements of the 123 corresponding result vector, y. Note that this is information is 124 required for use of the matrix interface routines, even though 125 the shell matrix may not actually be physically partitioned. 126 For example, 127 128 $ 129 $ Vec x, y 130 $ Mat A 131 $ 132 $ VecCreate(comm,M,&y); 133 $ VecCreate(comm,N,&x); 134 $ VecGetLocalSize(y,&m); 135 $ MatCreateShell(comm,m,N,M,N,ctx,&A); 136 $ MatShellSetOperation(mat,MAT_MULT,mult); 137 $ MatMult(A,x,y); 138 $ MatDestroy(A); 139 $ VecDestroy(y); VecDestroy(x); 140 $ 141 142 .keywords: matrix, shell, create 143 144 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext() 145 @*/ 146 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A) 147 { 148 Mat B; 149 Mat_Shell *b; 150 151 PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm); 152 PLogObjectCreate(B); 153 B->factor = 0; 154 B->destroy = MatDestroy_Shell; 155 B->assembled = PETSC_TRUE; 156 PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps)); 157 158 b = PetscNew(Mat_Shell); CHKPTRQ(b); 159 PetscMemzero(b,sizeof(Mat_Shell)); 160 B->data = (void *) b; 161 b->M = M; B->M = M; 162 b->N = N; B->N = N; 163 b->m = m; B->m = m; 164 b->n = n; B->n = n; 165 b->ctx = ctx; 166 *A = B; 167 return 0; 168 } 169 170 /*@ 171 MatShellSetOperation - Allows user to set a matrix operation for 172 a shell matrix. 173 174 Input Parameters: 175 . mat - the shell matrix 176 . op - the name of the operation 177 . f - the function that provides the operation. 178 179 Usage: 180 $ extern int usermult(Mat,Vec,Vec); 181 $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 182 $ ierr = MatShellSetOperation(A,MAT_MULT,usermult); 183 184 Notes: 185 See the file petsc/include/mat.h for a complete list of matrix 186 operations, which all have the form MAT_<OPERATION>, where 187 <OPERATION> is the name (in all capital letters) of the 188 user interface routine (e.g., MatMult() -> MAT_MULT). 189 190 All user-provided functions should have the same calling 191 sequence as the usual matrix interface routines, since they 192 are intended to be accessed via the usual matrix interface 193 routines, e.g., 194 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 195 196 Within each user-defined routine, the user should call 197 MatShellGetContext() to obtain the user-defined context that was 198 set by MatCreateShell(). 199 200 .keywords: matrix, shell, set, operation 201 202 .seealso: MatCreateShell(), MatShellGetContext() 203 @*/ 204 int MatShellSetOperation(Mat mat,MatOperation op, void *f) 205 { 206 PetscValidHeaderSpecific(mat,MAT_COOKIE); 207 208 if (op == MAT_DESTROY) { 209 if (mat->type == MATSHELL) { 210 Mat_Shell *shell = (Mat_Shell *) mat->data; 211 shell->destroy = (int (*)(Mat)) f; 212 } 213 else mat->destroy = (int (*)(PetscObject)) f; 214 } 215 else if (op == MAT_VIEW) mat->view = (int (*)(PetscObject,Viewer)) f; 216 else (((void**)&mat->ops)[op]) = f; 217 218 return 0; 219 } 220 221 222 223 224 225 226