xref: /petsc/src/mat/impls/shell/shell.c (revision f39d1f56266ee541fefdb1febe8b22a2eaa95e03) !
1 #ifndef lint
2 static char vcid[] = "$Id: shell.c,v 1.32 1996/04/07 22:47:23 curfman Exp curfman $";
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 that supports parallel matrix-vector
121    products using MatMult(), the user should set the number of local
122    matrix rows to be the same as the corresponding result vector
123    (even though the shell matrix may not actually be physically
124    partitioned or even stored at all).  For example,
125 
126 $  /* Create matrix and vectors to compute y = Ax */
127 $
128 $     Vec x, y
129 $     Mat mat
130 $
131 $     VecCreate(comm,M,&y);
132 $     VecCreate(comm,N,&x);
133 $     VecGetLocalSize(y,&m);
134 $     MatCreateShell(comm,m,N,M,N,ctx,&mat);
135 $     MatShellSetOperation(mat,MAT_MULT,mult);
136 $     MatMult(mat,x,y);
137 $     MatDestroy(mat);
138 $     VecDestroy(y); VecDestroy(x);
139 
140 .keywords: matrix, shell, create
141 
142 .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
143 @*/
144 int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
145 {
146   Mat       B;
147   Mat_Shell *b;
148 
149   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm);
150   PLogObjectCreate(B);
151   B->factor    = 0;
152   B->destroy   = MatDestroy_Shell;
153   B->assembled = PETSC_TRUE;
154   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
155 
156   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
157   PetscMemzero(b,sizeof(Mat_Shell));
158   B->data   = (void *) b;
159   b->M = M; B->M = M;
160   b->N = N; B->N = N;
161   b->m = m; B->m = m;
162   b->n = n; B->n = n;
163   b->ctx     = ctx;
164   *A = B;
165   return 0;
166 }
167 
168 /*@
169     MatShellSetOperation - Allows user to set a matrix operation for
170                            a shell matrix.
171 
172     Input Parameters:
173 .   mat - the shell matrix
174 .   op - the name of the operation
175 .   f - the function that provides the operation.
176 
177     Usage:
178 $      extern int usermult(Mat,Vec,Vec);
179 $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
180 $      ierr = MatShellSetOperation(A,MAT_MULT,usermult);
181 
182     Notes:
183     See the file petsc/include/mat.h for a complete list of matrix
184     operations, which all have the form MAT_<OPERATION>, where
185     <OPERATION> is the name (in all capital letters) of the
186     user interface routine (e.g., MatMult() -> MAT_MULT).
187 
188     All user-provided functions should have the same calling
189     sequence as the usual matrix interface routines, since they
190     are intended to be accessed via the usual matrix interface
191     routines, e.g.,
192 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
193 
194     Within each user-defined routine, the user should call
195     MatShellGetContext() to obtain the user-defined context that was
196     set by MatCreateShell().
197 
198 .keywords: matrix, shell, set, operation
199 
200 .seealso: MatCreateShell(), MatShellGetContext()
201 @*/
202 int MatShellSetOperation(Mat mat,MatOperation op, void *f)
203 {
204   PetscValidHeaderSpecific(mat,MAT_COOKIE);
205 
206   if (op == MAT_DESTROY) {
207     if (mat->type == MATSHELL) {
208        Mat_Shell *shell = (Mat_Shell *) mat->data;
209        shell->destroy                                 = (int (*)(Mat)) f;
210     }
211     else mat->destroy                                 = (int (*)(PetscObject)) f;
212   }
213   else if (op == MAT_VIEW) mat->view                  = (int (*)(PetscObject,Viewer)) f;
214   else                     (((void **)&mat->ops)[op]) = f;
215 
216   return 0;
217 }
218 
219 
220 
221 
222 
223 
224