1 #ifndef lint 2 static char vcid[] = "$Id: shell.c,v 1.24 1996/01/23 00:18:55 bsmith 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 (*mult)(void*,Vec,Vec); 18 int (*multtransadd)(void*,Vec,Vec,Vec); 19 int (*destroy)(void*); 20 int (*getsize)(void*,int*,int*); 21 void *ctx; 22 } Mat_Shell; 23 24 /*@ 25 MatShellGetContext - Returns the user provided context associated 26 with a MatShell. 27 28 Input Parameter: 29 . mat - the matrix, should have been created with MatCreateShell() 30 31 Output Parameter: 32 . ctx - the user provided context 33 34 @*/ 35 int MatShellGetContext(Mat mat,void **ctx) 36 { 37 PETSCVALIDHEADERSPECIFIC(mat,MAT_COOKIE); 38 if (mat->type != MATSHELL) *ctx = 0; 39 else *ctx = ((Mat_Shell *) (mat->data))->ctx; 40 return 0; 41 } 42 43 static int MatGetSize_Shell(Mat mat,int *m,int *n) 44 { 45 Mat_Shell *shell = (Mat_Shell *) mat->data; 46 *m = shell->m; *n = shell->n; 47 return 0; 48 } 49 50 static int MatMult_Shell(Mat mat,Vec x,Vec y) 51 { 52 Mat_Shell *shell = (Mat_Shell *) mat->data; 53 if (!shell->mult) SETERRQ(1,"MatMult_Shell:You have not provided a multiply for\ 54 your shell matrix"); 55 return (*shell->mult)(shell->ctx,x,y); 56 } 57 58 static int MatMultTransAdd_Shell(Mat mat,Vec x,Vec y,Vec z) 59 { 60 Mat_Shell *shell = (Mat_Shell *) mat->data; 61 return (*shell->multtransadd)(shell->ctx,x,y,z); 62 } 63 64 static int MatDestroy_Shell(PetscObject obj) 65 { 66 int ierr; 67 Mat mat = (Mat) obj; 68 Mat_Shell *shell; 69 70 shell = (Mat_Shell *) mat->data; 71 if (shell->destroy) {ierr = (*shell->destroy)(shell->ctx);CHKERRQ(ierr);} 72 PetscFree(shell); 73 PLogObjectDestroy(mat); 74 PetscHeaderDestroy(mat); 75 return 0; 76 } 77 78 static struct _MatOps MatOps = {0,0, 79 0, 80 MatMult_Shell,0,0,MatMultTransAdd_Shell, 81 0,0,0,0, 82 0,0, 83 0, 84 0, 85 0,0,0, 86 0, 87 0,0,0, 88 0,0, 89 0, 90 0,0,0,0, 91 0,0,MatGetSize_Shell, 92 0,0,0,0, 93 0,0,0,0 }; 94 95 /*@C 96 MatCreateShell - Creates a new matrix class for use with a user-defined 97 private data storage format. 98 99 Input Parameters: 100 . comm - MPI communicator 101 . m - number of rows 102 . n - number of columns 103 . ctx - pointer to data needed by matrix-vector multiplication routine(s) 104 105 Output Parameter: 106 . mat - the matrix 107 108 Notes: 109 The shell matrix type is intended to provide a simple class to use 110 with KSP (such as, for use with matrix-free methods). You should not 111 use the shell type if you plan to define a complete matrix class. 112 113 Usage: 114 $ MatCreateShell(m,n,ctx,&mat); 115 $ MatShellSetMult(mat,mult); 116 117 .keywords: matrix, shell, create 118 119 .seealso: MatShellSetMult(), MatShellSetMultTransAdd() 120 @*/ 121 int MatCreateShell(MPI_Comm comm,int m,int n,void *ctx,Mat *mat) 122 { 123 Mat newmat; 124 Mat_Shell *shell; 125 126 PetscHeaderCreate(newmat,_Mat,MAT_COOKIE,MATSHELL,comm); 127 PLogObjectCreate(newmat); 128 *mat = newmat; 129 newmat->factor = 0; 130 newmat->destroy = MatDestroy_Shell; 131 newmat->assembled = PETSC_TRUE; 132 PetscMemcpy(&newmat->ops,&MatOps,sizeof(struct _MatOps)); 133 134 shell = PetscNew(Mat_Shell); CHKPTRQ(shell); 135 PetscMemzero(shell,sizeof(Mat_Shell)); 136 newmat->data = (void *) shell; 137 shell->mult = 0; 138 shell->m = m; 139 shell->n = n; 140 shell->ctx = ctx; 141 return 0; 142 } 143 144 /*@C 145 MatShellSetMult - Sets the routine for computing the matrix-vector product. 146 147 Input Parameters: 148 . mat - the matrix associated with this operation, created 149 with MatCreateShell() 150 . mult - the user-defined routine 151 152 Calling sequence of mult: 153 int mult (void *ptr,Vec xin,Vec xout) 154 . ptr - the application context for matrix data 155 . xin - input vector 156 . xout - output vector 157 158 .keywords: matrix, multiply, shell, set 159 160 .seealso: MatCreateShell(), MatShellSetMultTransAdd() 161 @*/ 162 int MatShellSetMult(Mat mat,int (*mult)(void*,Vec,Vec)) 163 { 164 Mat_Shell *shell; 165 PETSCVALIDHEADERSPECIFIC(mat,MAT_COOKIE); 166 shell = (Mat_Shell *) mat->data; 167 shell->mult = mult; 168 return 0; 169 } 170 /*@C 171 MatShellSetMultTransAdd - Sets the routine for computing v3 = v2 + A' * v1. 172 173 Input Parameters: 174 . mat - the matrix associated with this operation, created 175 with MatCreateShell() 176 . mult - the user-defined routine 177 178 Calling sequence of mult: 179 int mult (void *ptr,Vec v1,Vec v2,Vec v3) 180 . ptr - the application context for matrix data 181 . v1, v2 - the input vectors 182 . v3 - the result 183 184 .keywords: matrix, multiply, transpose 185 186 .seealso: MatCreateShell(), MatShellSetMult() 187 @*/ 188 int MatShellSetMultTransAdd(Mat mat,int (*mult)(void*,Vec,Vec,Vec)) 189 { 190 Mat_Shell *shell; 191 PETSCVALIDHEADERSPECIFIC(mat,MAT_COOKIE); 192 shell = (Mat_Shell *) mat->data; 193 shell->multtransadd = mult; 194 return 0; 195 } 196 /*@C 197 MatShellSetDestroy - Set the routine to use to destroy the 198 private contents of your MatShell. 199 200 Input Parameters: 201 . mat - the matrix associated with this operation, created 202 with MatCreateShell() 203 . destroy - the user-defined routine 204 205 Calling sequence of mult: 206 int destroy (void *ptr) 207 . ptr - the application context for matrix data 208 209 .keywords: matrix, destroy, shell, set 210 211 .seealso: MatCreateShell() 212 @*/ 213 int MatShellSetDestroy(Mat mat,int (*destroy)(void*)) 214 { 215 Mat_Shell *shell; 216 PETSCVALIDHEADERSPECIFIC(mat,MAT_COOKIE); 217 shell = (Mat_Shell *) mat->data; 218 shell->destroy = destroy; 219 return 0; 220 } 221 222 223