xref: /petsc/src/mat/impls/shell/shell.c (revision 21c89e3ec4e69ad4b25aa55d9d4d19d802791149)
1 #ifndef lint
2 static char vcid[] = "$Id: shell.c,v 1.34 1996/04/08 22:11:17 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;                  /* 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 /*@
23     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
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     Notes:
32     This routine is intended for use within various shell matrix routines,
33     as set with MatShellSetOperation().
34 
35 .keywords: matrix, shell, get, context
36 
37 .seealso: MatCreateShell(), MatShellSetOperation()
38 @*/
39 int MatShellGetContext(Mat mat,void **ctx)
40 {
41   PetscValidHeaderSpecific(mat,MAT_COOKIE);
42   if (mat->type != MATSHELL) *ctx = 0;
43   else                       *ctx = ((Mat_Shell *) (mat->data))->ctx;
44   return 0;
45 }
46 
47 static int MatGetSize_Shell(Mat mat,int *M,int *N)
48 {
49   Mat_Shell *shell = (Mat_Shell *) mat->data;
50   *M = shell->M; *N = shell->N;
51   return 0;
52 }
53 
54 static int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
55 {
56   Mat_Shell *shell = (Mat_Shell *) mat->data;
57   *m = shell->n; *n = shell->n;
58   return 0;
59 }
60 
61 static int MatDestroy_Shell(PetscObject obj)
62 {
63   int       ierr;
64   Mat       mat = (Mat) obj;
65   Mat_Shell *shell;
66 
67   shell = (Mat_Shell *) mat->data;
68   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
69   PetscFree(shell);
70   PLogObjectDestroy(mat);
71   PetscHeaderDestroy(mat);
72   return 0;
73 }
74 
75 static struct _MatOps MatOps = {0,0,
76        0,
77        0,0,0,0,
78        0,0,0,0,
79        0,0,
80        0,
81        0,
82        0,0,0,
83        0,
84        0,0,0,
85        0,0,
86        0,
87        0,0,0,0,
88        0,0,MatGetSize_Shell,MatGetLocalSize_Shell,
89        0,0,0,
90        0,0,0,0 };
91 
92 /*@C
93    MatCreateShell - Creates a new matrix class for use with a user-defined
94    private data storage format.
95 
96    Input Parameters:
97 .  comm - MPI communicator
98 .  m - number of local rows
99 .  n - number of local columns
100 .  M - number of global rows
101 .  N - number of global columns
102 .  ctx - pointer to data needed by the shell matrix routines
103 
104    Output Parameter:
105 .  A - the matrix
106 
107    Usage:
108 $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
109 $    MatShellSetOperation(mat,MAT_MULT,mult);
110 $    [ Use matrix for operations that have been set ]
111 $    MatDestroy(mat);
112 
113    Notes:
114    The shell matrix type is intended to provide a simple class to use
115    with KSP (such as, for use with matrix-free methods). You should not
116    use the shell type if you plan to define a complete matrix class.
117 
118    PETSc requires that matrices and vectors being used for certain
119    operations are partitioned accordingly.  For example, when
120    creating a shell matrix, A, that supports parallel matrix-vector
121    products using MatMult(A,x,y) the user should set the number
122    of local matrix rows to be the number of local elements of the
123    corresponding result vector, y. Note that this is information is
124    required for use of the matrix interface routines, even though
125    the shell matrix may not actually be physically partitioned.
126    For example,
127 
128 $
129 $     Vec x, y
130 $     Mat A
131 $
132 $     VecCreate(comm,M,&y);
133 $     VecCreate(comm,N,&x);
134 $     VecGetLocalSize(y,&m);
135 $     MatCreateShell(comm,m,N,M,N,ctx,&A);
136 $     MatShellSetOperation(mat,MAT_MULT,mult);
137 $     MatMult(A,x,y);
138 $     MatDestroy(A);
139 $     VecDestroy(y); VecDestroy(x);
140 $
141 
142 .keywords: matrix, shell, create
143 
144 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
145 @*/
146 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
147 {
148   Mat       B;
149   Mat_Shell *b;
150 
151   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm);
152   PLogObjectCreate(B);
153   B->factor    = 0;
154   B->destroy   = MatDestroy_Shell;
155   B->assembled = PETSC_TRUE;
156   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
157 
158   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
159   PetscMemzero(b,sizeof(Mat_Shell));
160   B->data   = (void *) b;
161   b->M = M; B->M = M;
162   b->N = N; B->N = N;
163   b->m = m; B->m = m;
164   b->n = n; B->n = n;
165   b->ctx     = ctx;
166   *A = B;
167   return 0;
168 }
169 
170 /*@
171     MatShellSetOperation - Allows user to set a matrix operation for
172                            a shell matrix.
173 
174     Input Parameters:
175 .   mat - the shell matrix
176 .   op - the name of the operation
177 .   f - the function that provides the operation.
178 
179     Usage:
180 $      extern int usermult(Mat,Vec,Vec);
181 $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
182 $      ierr = MatShellSetOperation(A,MAT_MULT,usermult);
183 
184     Notes:
185     See the file petsc/include/mat.h for a complete list of matrix
186     operations, which all have the form MAT_<OPERATION>, where
187     <OPERATION> is the name (in all capital letters) of the
188     user interface routine (e.g., MatMult() -> MAT_MULT).
189 
190     All user-provided functions should have the same calling
191     sequence as the usual matrix interface routines, since they
192     are intended to be accessed via the usual matrix interface
193     routines, e.g.,
194 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
195 
196     Within each user-defined routine, the user should call
197     MatShellGetContext() to obtain the user-defined context that was
198     set by MatCreateShell().
199 
200 .keywords: matrix, shell, set, operation
201 
202 .seealso: MatCreateShell(), MatShellGetContext()
203 @*/
204 int MatShellSetOperation(Mat mat,MatOperation op, void *f)
205 {
206   PetscValidHeaderSpecific(mat,MAT_COOKIE);
207 
208   if (op == MAT_DESTROY) {
209     if (mat->type == MATSHELL) {
210        Mat_Shell *shell = (Mat_Shell *) mat->data;
211        shell->destroy                 = (int (*)(Mat)) f;
212     }
213     else mat->destroy                 = (int (*)(PetscObject)) f;
214   }
215   else if (op == MAT_VIEW) mat->view  = (int (*)(PetscObject,Viewer)) f;
216   else      (((void**)&mat->ops)[op]) = f;
217 
218   return 0;
219 }
220 
221 
222 
223 
224 
225 
226