1 #ifndef lint 2 static char vcid[] = "$Id: shell.c,v 1.30 1996/03/31 16:50:54 bsmith Exp curfman $"; 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 shell 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, since they 156 are intended to be accessed via the usual matrix interface 157 routines, e.g., 158 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 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