1 #ifndef lint 2 static char vcid[] = "$Id: shell.c,v 1.26 1996/03/19 21:26:12 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 (*destroy)(void*); 18 void *ctx; 19 } Mat_Shell; 20 21 /*@ 22 MatShellGetContext - Returns the user provided context associated 23 with a MatShell. 24 25 Input Parameter: 26 . mat - the matrix, should have been created with MatCreateShell() 27 28 Output Parameter: 29 . ctx - the user provided context 30 31 @*/ 32 int MatShellGetContext(Mat mat,void **ctx) 33 { 34 PetscValidHeaderSpecific(mat,MAT_COOKIE); 35 if (mat->type != MATSHELL) *ctx = 0; 36 else *ctx = ((Mat_Shell *) (mat->data))->ctx; 37 return 0; 38 } 39 40 static int MatGetSize_Shell(Mat mat,int *m,int *n) 41 { 42 Mat_Shell *shell = (Mat_Shell *) mat->data; 43 *m = shell->m; *n = shell->n; 44 return 0; 45 } 46 47 static int MatDestroy_Shell(PetscObject obj) 48 { 49 int ierr; 50 Mat mat = (Mat) obj; 51 Mat_Shell *shell; 52 53 shell = (Mat_Shell *) mat->data; 54 if (shell->destroy) {ierr = (*shell->destroy)(shell->ctx);CHKERRQ(ierr);} 55 PetscFree(shell); 56 PLogObjectDestroy(mat); 57 PetscHeaderDestroy(mat); 58 return 0; 59 } 60 61 static struct _MatOps MatOps = {0,0, 62 0, 63 0,0,0,0, 64 0,0,0,0, 65 0,0, 66 0, 67 0, 68 0,0,0, 69 0, 70 0,0,0, 71 0,0, 72 0, 73 0,0,0,0, 74 0,0,MatGetSize_Shell, 75 0,0,0,0, 76 0,0,0,0 }; 77 78 /*@C 79 MatCreateShell - Creates a new matrix class for use with a user-defined 80 private data storage format. 81 82 Input Parameters: 83 . comm - MPI communicator 84 . m - number of rows 85 . n - number of columns 86 . ctx - pointer to data needed by the matrix routines 87 88 Output Parameter: 89 . mat - the matrix 90 91 Notes: 92 The shell matrix type is intended to provide a simple class to use 93 with KSP (such as, for use with matrix-free methods). You should not 94 use the shell type if you plan to define a complete matrix class. 95 96 Usage: 97 $ MatCreateShell(m,n,ctx,&mat); 98 $ MatSetOperation(mat,MAT_MULT,mult); 99 100 .keywords: matrix, shell, create 101 102 .seealso: MatSetOperation(), MatHasOperation(), MatShellGetContext() 103 @*/ 104 int MatCreateShell(MPI_Comm comm,int m,int n,void *ctx,Mat *mat) 105 { 106 Mat newmat; 107 Mat_Shell *shell; 108 109 PetscHeaderCreate(newmat,_Mat,MAT_COOKIE,MATSHELL,comm); 110 PLogObjectCreate(newmat); 111 *mat = newmat; 112 newmat->factor = 0; 113 newmat->destroy = MatDestroy_Shell; 114 newmat->assembled = PETSC_TRUE; 115 PetscMemcpy(&newmat->ops,&MatOps,sizeof(struct _MatOps)); 116 117 shell = PetscNew(Mat_Shell); CHKPTRQ(shell); 118 PetscMemzero(shell,sizeof(Mat_Shell)); 119 newmat->data = (void *) shell; 120 shell->m = m; 121 shell->n = n; 122 shell->ctx = ctx; 123 return 0; 124 } 125 126 /*@ 127 MatShellSetOperation - Allows use to set a matrix operation for a shell matrix. 128 129 Input Parameters: 130 . mat - the shell matrix 131 . op - the name of the operation 132 . f - the function that provides the operation. 133 134 Usage: 135 extern int mult(Mat,Vec,Vec); 136 ierr = MatCreateShell(comm,m,m,ctx,&A); 137 ierr = MatSetOperation(A,MAT_MULT,mult); 138 139 In the user provided function, use MatShellGetContext() to obtain the 140 context passed into MatCreateShell(). 141 @*/ 142 int MatShellSetOperation(Mat mat,MatOperation op, void *f) 143 { 144 PetscValidHeaderSpecific(mat,MAT_COOKIE); 145 146 if (op == MAT_DESTROY) mat->destroy = (int (*)(PetscObject)) f; 147 else if (op == MAT_VIEW) mat->view = (int (*)(PetscObject,Viewer)) f; 148 else (((void **)&mat->ops)[op])= f; 149 return 0; 150 } 151 152