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