xref: /petsc/src/mat/impls/shell/shell.c (revision 3a3eedf2169b507b1efbdb3dd065481a2d2f2a88)
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