1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: shell.c,v 1.48 1997/06/05 12:54:00 bsmith 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 PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell)); 202 PetscMemzero(b,sizeof(Mat_Shell)); 203 B->data = (void *) b; 204 b->M = M; B->M = M; 205 b->N = N; B->N = N; 206 b->m = m; B->m = m; 207 b->n = n; B->n = n; 208 b->ctx = ctx; 209 *A = B; 210 return 0; 211 } 212 213 #undef __FUNC__ 214 #define __FUNC__ "MatShellSetOperation" /* ADIC Ignore */ 215 /*@C 216 MatShellSetOperation - Allows user to set a matrix operation for 217 a shell matrix. 218 219 Input Parameters: 220 . mat - the shell matrix 221 . op - the name of the operation 222 . f - the function that provides the operation. 223 224 Usage: 225 $ extern int usermult(Mat,Vec,Vec); 226 $ ierr = MatCreateShell(comm,m,n,M,N,ctx,&A); 227 $ ierr = MatShellSetOperation(A,MATOP_MULT,usermult); 228 229 Notes: 230 See the file petsc/include/mat.h for a complete list of matrix 231 operations, which all have the form MATOP_<OPERATION>, where 232 <OPERATION> is the name (in all capital letters) of the 233 user interface routine (e.g., MatMult() -> MATOP_MULT). 234 235 All user-provided functions should have the same calling 236 sequence as the usual matrix interface routines, since they 237 are intended to be accessed via the usual matrix interface 238 routines, e.g., 239 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 240 241 Within each user-defined routine, the user should call 242 MatShellGetContext() to obtain the user-defined context that was 243 set by MatCreateShell(). 244 245 .keywords: matrix, shell, set, operation 246 247 .seealso: MatCreateShell(), MatShellGetContext() 248 @*/ 249 int MatShellSetOperation(Mat mat,MatOperation op, void *f) 250 { 251 PetscValidHeaderSpecific(mat,MAT_COOKIE); 252 253 if (op == MATOP_DESTROY) { 254 if (mat->type == MATSHELL) { 255 Mat_Shell *shell = (Mat_Shell *) mat->data; 256 shell->destroy = (int (*)(Mat)) f; 257 } 258 else mat->destroy = (int (*)(PetscObject)) f; 259 } 260 else if (op == MATOP_VIEW) mat->view = (int (*)(PetscObject,Viewer)) f; 261 else (((void**)&mat->ops)[op]) = f; 262 263 return 0; 264 } 265 266 267 268