xref: /petsc/src/mat/impls/shell/shell.c (revision d4bb536f0e426e9a0292bbfd5743770a9b03f0d5)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: shell.c,v 1.49 1997/07/09 20:54:17 balay 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 "src/mat/matimpl.h"        /*I "mat.h" I*/
13 #include "src/vec/vecimpl.h"
14 
15 typedef struct {
16   int  M, N;                  /* number of global rows, columns */
17   int  m, n;                  /* number of local rows, columns */
18   int  (*destroy)(Mat);
19   void *ctx;
20 } Mat_Shell;
21 
22 #undef __FUNC__
23 #define __FUNC__ "MatShellGetContext"
24 /*@
25     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
26 
27     Input Parameter:
28 .   mat - the matrix, should have been created with MatCreateShell()
29 
30     Output Parameter:
31 .   ctx - the user provided context
32 
33     Notes:
34     This routine is intended for use within various shell matrix routines,
35     as set with MatShellSetOperation().
36 
37 .keywords: matrix, shell, get, context
38 
39 .seealso: MatCreateShell(), MatShellSetOperation()
40 @*/
41 int MatShellGetContext(Mat mat,void **ctx)
42 {
43   PetscValidHeaderSpecific(mat,MAT_COOKIE);
44   if (mat->type != MATSHELL) *ctx = 0;
45   else                       *ctx = ((Mat_Shell *) (mat->data))->ctx;
46   return 0;
47 }
48 
49 #undef __FUNC__
50 #define __FUNC__ "MatGetSize_Shell"
51 int MatGetSize_Shell(Mat mat,int *M,int *N)
52 {
53   Mat_Shell *shell = (Mat_Shell *) mat->data;
54   *M = shell->M; *N = shell->N;
55   return 0;
56 }
57 
58 #undef __FUNC__
59 #define __FUNC__ "MatGetLocalSize_Shell"
60 int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
61 {
62   Mat_Shell *shell = (Mat_Shell *) mat->data;
63   *m = shell->n; *n = shell->n;
64   return 0;
65 }
66 
67 #undef __FUNC__
68 #define __FUNC__ "MatDestroy_Shell"
69 int MatDestroy_Shell(PetscObject obj)
70 {
71   int       ierr;
72   Mat       mat = (Mat) obj;
73   Mat_Shell *shell;
74 
75   shell = (Mat_Shell *) mat->data;
76   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
77   PetscFree(shell);
78   PLogObjectDestroy(mat);
79   PetscHeaderDestroy(mat);
80   return 0;
81 }
82 
83 int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
84 {
85   MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);
86   *rstart = *rend - mat->m;
87   return 0;
88 }
89 
90 
91 
92 
93 static struct _MatOps MatOps = {0,
94        0,
95        0,
96        0,
97        0,
98        0,
99        0,
100        0,
101        0,
102        0,
103        0,
104        0,
105        0,
106        0,
107        0,
108        0,
109        0,
110        0,
111        0,
112        0,
113        0,
114        0,
115        0,
116        0,
117        0,
118        0,
119        0,
120        0,
121        0,
122        0,
123        MatGetSize_Shell,
124        MatGetLocalSize_Shell,
125        MatGetOwnershipRange_Shell,
126        0,
127        0,
128        0,
129        0,
130        0 };
131 
132 #undef __FUNC__
133 #define __FUNC__ "MatCreateShell"
134 /*@C
135    MatCreateShell - Creates a new matrix class for use with a user-defined
136    private data storage format.
137 
138    Input Parameters:
139 .  comm - MPI communicator
140 .  m - number of local rows
141 .  n - number of local columns
142 .  M - number of global rows
143 .  N - number of global columns
144 .  ctx - pointer to data needed by the shell matrix routines
145 
146    Output Parameter:
147 .  A - the matrix
148 
149    Usage:
150 $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
151 $    MatShellSetOperation(mat,MATOP_MULT,mult);
152 $    [ Use matrix for operations that have been set ]
153 $    MatDestroy(mat);
154 
155    Notes:
156    The shell matrix type is intended to provide a simple class to use
157    with KSP (such as, for use with matrix-free methods). You should not
158    use the shell type if you plan to define a complete matrix class.
159 
160    PETSc requires that matrices and vectors being used for certain
161    operations are partitioned accordingly.  For example, when
162    creating a shell matrix, A, that supports parallel matrix-vector
163    products using MatMult(A,x,y) the user should set the number
164    of local matrix rows to be the number of local elements of the
165    corresponding result vector, y. Note that this is information is
166    required for use of the matrix interface routines, even though
167    the shell matrix may not actually be physically partitioned.
168    For example,
169 
170 $
171 $     Vec x, y
172 $     Mat A
173 $
174 $     VecCreate(comm,M,&y);
175 $     VecCreate(comm,N,&x);
176 $     VecGetLocalSize(y,&m);
177 $     MatCreateShell(comm,m,N,M,N,ctx,&A);
178 $     MatShellSetOperation(mat,MATOP_MULT,mult);
179 $     MatMult(A,x,y);
180 $     MatDestroy(A);
181 $     VecDestroy(y); VecDestroy(x);
182 $
183 
184 .keywords: matrix, shell, create
185 
186 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
187 @*/
188 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
189 {
190   Mat       B;
191   Mat_Shell *b;
192 
193   PetscHeaderCreate(B,_p_Mat,MAT_COOKIE,MATSHELL,comm,MatDestroy,MatView);
194   PLogObjectCreate(B);
195   B->factor    = 0;
196   B->destroy   = MatDestroy_Shell;
197   B->assembled = PETSC_TRUE;
198   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
199 
200   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
201   PLogObjectMemory(B,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
202   PetscMemzero(b,sizeof(Mat_Shell));
203   B->data   = (void *) b;
204   b->M = M; B->M = M;
205   b->N = N; B->N = N;
206   b->m = m; B->m = m;
207   b->n = n; B->n = n;
208   b->ctx     = ctx;
209   *A = B;
210   return 0;
211 }
212 
213 #undef __FUNC__
214 #define __FUNC__ "MatShellSetOperation"
215 /*@C
216     MatShellSetOperation - Allows user to set a matrix operation for
217                            a shell matrix.
218 
219     Input Parameters:
220 .   mat - the shell matrix
221 .   op - the name of the operation
222 .   f - the function that provides the operation.
223 
224     Usage:
225 $      extern int usermult(Mat,Vec,Vec);
226 $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
227 $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
228 
229     Notes:
230     See the file petsc/include/mat.h for a complete list of matrix
231     operations, which all have the form MATOP_<OPERATION>, where
232     <OPERATION> is the name (in all capital letters) of the
233     user interface routine (e.g., MatMult() -> MATOP_MULT).
234 
235     All user-provided functions should have the same calling
236     sequence as the usual matrix interface routines, since they
237     are intended to be accessed via the usual matrix interface
238     routines, e.g.,
239 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
240 
241     Within each user-defined routine, the user should call
242     MatShellGetContext() to obtain the user-defined context that was
243     set by MatCreateShell().
244 
245 .keywords: matrix, shell, set, operation
246 
247 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
248 @*/
249 int MatShellSetOperation(Mat mat,MatOperation op, void *f)
250 {
251   PetscValidHeaderSpecific(mat,MAT_COOKIE);
252 
253   if (op == MATOP_DESTROY) {
254     if (mat->type == MATSHELL) {
255        Mat_Shell *shell = (Mat_Shell *) mat->data;
256        shell->destroy                 = (int (*)(Mat)) f;
257     }
258     else mat->destroy                 = (int (*)(PetscObject)) f;
259   }
260   else if (op == MATOP_VIEW) mat->view  = (int (*)(PetscObject,Viewer)) f;
261   else      (((void**)&mat->ops)[op]) = f;
262 
263   return 0;
264 }
265 
266 
267 
268 #undef __FUNC__
269 #define __FUNC__ "MatShellGetOperation"
270 /*@C
271     MatShellGetOperation - Gets a matrix function for a shell matrix.
272 
273     Input Parameters:
274 .   mat - the shell matrix
275 .   op - the name of the operation
276 
277     Output Parameter:
278 .   f - the function that provides the operation.
279 
280     Notes:
281     See the file petsc/include/mat.h for a complete list of matrix
282     operations, which all have the form MATOP_<OPERATION>, where
283     <OPERATION> is the name (in all capital letters) of the
284     user interface routine (e.g., MatMult() -> MATOP_MULT).
285 
286     All user-provided functions have the same calling
287     sequence as the usual matrix interface routines, since they
288     are intended to be accessed via the usual matrix interface
289     routines, e.g.,
290 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
291 
292     Within each user-defined routine, the user should call
293     MatShellGetContext() to obtain the user-defined context that was
294     set by MatCreateShell().
295 
296 .keywords: matrix, shell, set, operation
297 
298 .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
299 @*/
300 int MatShellGetOperation(Mat mat,MatOperation op, void **f)
301 {
302   PetscValidHeaderSpecific(mat,MAT_COOKIE);
303 
304   if (op == MATOP_DESTROY) {
305     if (mat->type == MATSHELL) {
306        Mat_Shell *shell = (Mat_Shell *) mat->data;
307        *f = (void *) shell->destroy;
308     }
309     else *f = (void *) mat->destroy;
310   }
311   else if (op == MATOP_VIEW) *f = (void *) mat->view;
312   else      *f = (((void**)&mat->ops)[op]);
313 
314   return 0;
315 }
316 
317