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