xref: /petsc/src/mat/impls/shell/shell.c (revision 5615d1e584023db9367fb782d85b1b4ebbb8df18)
1 #ifndef lint
2 static char vcid[] = "$Id: shell.c,v 1.41 1996/12/17 16:54:19 balay Exp balay $";
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 static 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 static 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 static 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 static struct _MatOps MatOps = {0,0,
84        0,
85        0,0,0,0,
86        0,0,0,0,
87        0,0,
88        0,
89        0,
90        0,0,0,
91        0,
92        0,0,0,
93        0,0,
94        0,
95        0,0,0,0,
96        0,MatGetSize_Shell,MatGetLocalSize_Shell,
97        0,0,0,
98        0,0,0,0 };
99 
100 #undef __FUNC__
101 #define __FUNC__ "MatCreateShell"
102 /*@C
103    MatCreateShell - Creates a new matrix class for use with a user-defined
104    private data storage format.
105 
106    Input Parameters:
107 .  comm - MPI communicator
108 .  m - number of local rows
109 .  n - number of local columns
110 .  M - number of global rows
111 .  N - number of global columns
112 .  ctx - pointer to data needed by the shell matrix routines
113 
114    Output Parameter:
115 .  A - the matrix
116 
117    Usage:
118 $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
119 $    MatShellSetOperation(mat,MATOP_MULT,mult);
120 $    [ Use matrix for operations that have been set ]
121 $    MatDestroy(mat);
122 
123    Notes:
124    The shell matrix type is intended to provide a simple class to use
125    with KSP (such as, for use with matrix-free methods). You should not
126    use the shell type if you plan to define a complete matrix class.
127 
128    PETSc requires that matrices and vectors being used for certain
129    operations are partitioned accordingly.  For example, when
130    creating a shell matrix, A, that supports parallel matrix-vector
131    products using MatMult(A,x,y) the user should set the number
132    of local matrix rows to be the number of local elements of the
133    corresponding result vector, y. Note that this is information is
134    required for use of the matrix interface routines, even though
135    the shell matrix may not actually be physically partitioned.
136    For example,
137 
138 $
139 $     Vec x, y
140 $     Mat A
141 $
142 $     VecCreate(comm,M,&y);
143 $     VecCreate(comm,N,&x);
144 $     VecGetLocalSize(y,&m);
145 $     MatCreateShell(comm,m,N,M,N,ctx,&A);
146 $     MatShellSetOperation(mat,MATOP_MULT,mult);
147 $     MatMult(A,x,y);
148 $     MatDestroy(A);
149 $     VecDestroy(y); VecDestroy(x);
150 $
151 
152 .keywords: matrix, shell, create
153 
154 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
155 @*/
156 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
157 {
158   Mat       B;
159   Mat_Shell *b;
160 
161   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm);
162   PLogObjectCreate(B);
163   B->factor    = 0;
164   B->destroy   = MatDestroy_Shell;
165   B->assembled = PETSC_TRUE;
166   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
167 
168   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
169   PetscMemzero(b,sizeof(Mat_Shell));
170   B->data   = (void *) b;
171   b->M = M; B->M = M;
172   b->N = N; B->N = N;
173   b->m = m; B->m = m;
174   b->n = n; B->n = n;
175   b->ctx     = ctx;
176   *A = B;
177   return 0;
178 }
179 
180 #undef __FUNC__
181 #define __FUNC__ "MatShellSetOperation"
182 /*@C
183     MatShellSetOperation - Allows user to set a matrix operation for
184                            a shell matrix.
185 
186     Input Parameters:
187 .   mat - the shell matrix
188 .   op - the name of the operation
189 .   f - the function that provides the operation.
190 
191     Usage:
192 $      extern int usermult(Mat,Vec,Vec);
193 $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
194 $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
195 
196     Notes:
197     See the file petsc/include/mat.h for a complete list of matrix
198     operations, which all have the form MATOP_<OPERATION>, where
199     <OPERATION> is the name (in all capital letters) of the
200     user interface routine (e.g., MatMult() -> MATOP_MULT).
201 
202     All user-provided functions should have the same calling
203     sequence as the usual matrix interface routines, since they
204     are intended to be accessed via the usual matrix interface
205     routines, e.g.,
206 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
207 
208     Within each user-defined routine, the user should call
209     MatShellGetContext() to obtain the user-defined context that was
210     set by MatCreateShell().
211 
212 .keywords: matrix, shell, set, operation
213 
214 .seealso: MatCreateShell(), MatShellGetContext()
215 @*/
216 int MatShellSetOperation(Mat mat,MatOperation op, void *f)
217 {
218   PetscValidHeaderSpecific(mat,MAT_COOKIE);
219 
220   if (op == MATOP_DESTROY) {
221     if (mat->type == MATSHELL) {
222        Mat_Shell *shell = (Mat_Shell *) mat->data;
223        shell->destroy                 = (int (*)(Mat)) f;
224     }
225     else mat->destroy                 = (int (*)(PetscObject)) f;
226   }
227   else if (op == MATOP_VIEW) mat->view  = (int (*)(PetscObject,Viewer)) f;
228   else      (((void**)&mat->ops)[op]) = f;
229 
230   return 0;
231 }
232 
233 
234 
235 
236 
237 
238