xref: /petsc/src/mat/impls/shell/shell.c (revision f39d1f56266ee541fefdb1febe8b22a2eaa95e03)
1357feee3SLois Curfman McInnes #ifndef lint
2*f39d1f56SLois Curfman McInnes static char vcid[] = "$Id: shell.c,v 1.32 1996/04/07 22:47:23 curfman Exp curfman $";
3357feee3SLois Curfman McInnes #endif
4e51e0e81SBarry Smith 
5e51e0e81SBarry Smith /*
620563c6bSBarry Smith    This provides a simple shell for Fortran (and C programmers) to
720563c6bSBarry Smith   create a very simple matrix class for use with KSP without coding
8ed3cc1f0SBarry Smith   much of anything.
9e51e0e81SBarry Smith */
10e51e0e81SBarry Smith 
11e51e0e81SBarry Smith #include "petsc.h"
12e51e0e81SBarry Smith #include "matimpl.h"        /*I "mat.h" I*/
13e51e0e81SBarry Smith #include "vec/vecimpl.h"
14e51e0e81SBarry Smith 
1520563c6bSBarry Smith typedef struct {
16*f39d1f56SLois Curfman McInnes   int  M, N;                  /* number of global rows, columns */
17*f39d1f56SLois Curfman McInnes   int  m, n;                  /* number of local rows, columns */
183a3eedf2SBarry Smith   int  (*destroy)(Mat);
1920563c6bSBarry Smith   void *ctx;
2088cf3e7dSBarry Smith } Mat_Shell;
21e51e0e81SBarry Smith 
22b4fd4287SBarry Smith /*@
23a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
24b4fd4287SBarry Smith 
25b4fd4287SBarry Smith     Input Parameter:
26b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
27b4fd4287SBarry Smith 
28b4fd4287SBarry Smith     Output Parameter:
29b4fd4287SBarry Smith .   ctx - the user provided context
30b4fd4287SBarry Smith 
31a62d957aSLois Curfman McInnes     Notes:
32a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
33a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
34a62d957aSLois Curfman McInnes 
35a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
36a62d957aSLois Curfman McInnes 
37a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation()
38b4fd4287SBarry Smith @*/
39b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx)
40b4fd4287SBarry Smith {
4177c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
42b4fd4287SBarry Smith   if (mat->type != MATSHELL) *ctx = 0;
43b4fd4287SBarry Smith   else                       *ctx = ((Mat_Shell *) (mat->data))->ctx;
44b4fd4287SBarry Smith   return 0;
45b4fd4287SBarry Smith }
46b4fd4287SBarry Smith 
47*f39d1f56SLois Curfman McInnes static int MatGetSize_Shell(Mat mat,int *M,int *N)
4871b459e3SLois Curfman McInnes {
4971b459e3SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
50*f39d1f56SLois Curfman McInnes   *M = shell->M; *N = shell->N;
51*f39d1f56SLois Curfman McInnes   return 0;
52*f39d1f56SLois Curfman McInnes }
53*f39d1f56SLois Curfman McInnes 
54*f39d1f56SLois Curfman McInnes static int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
55*f39d1f56SLois Curfman McInnes {
56*f39d1f56SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
57*f39d1f56SLois Curfman McInnes   *m = shell->n; *n = shell->n;
5871b459e3SLois Curfman McInnes   return 0;
5971b459e3SLois Curfman McInnes }
6071b459e3SLois Curfman McInnes 
6188cf3e7dSBarry Smith static int MatDestroy_Shell(PetscObject obj)
62e51e0e81SBarry Smith {
63b9fa9cd0SBarry Smith   int       ierr;
6420563c6bSBarry Smith   Mat       mat = (Mat) obj;
6588cf3e7dSBarry Smith   Mat_Shell *shell;
66ed3cc1f0SBarry Smith 
6788cf3e7dSBarry Smith   shell = (Mat_Shell *) mat->data;
683a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
690452661fSBarry Smith   PetscFree(shell);
703a3eedf2SBarry Smith   PLogObjectDestroy(mat);
713a3eedf2SBarry Smith   PetscHeaderDestroy(mat);
72e51e0e81SBarry Smith   return 0;
73e51e0e81SBarry Smith }
74e51e0e81SBarry Smith 
7520563c6bSBarry Smith static struct _MatOps MatOps = {0,0,
7620563c6bSBarry Smith        0,
77fae171e0SBarry Smith        0,0,0,0,
7820563c6bSBarry Smith        0,0,0,0,
7920563c6bSBarry Smith        0,0,
8020563c6bSBarry Smith        0,
8120563c6bSBarry Smith        0,
8220563c6bSBarry Smith        0,0,0,
8320563c6bSBarry Smith        0,
8420563c6bSBarry Smith        0,0,0,
8520563c6bSBarry Smith        0,0,
8620563c6bSBarry Smith        0,
8720563c6bSBarry Smith        0,0,0,0,
88*f39d1f56SLois Curfman McInnes        0,0,MatGetSize_Shell,MatGetLocalSize_Shell,
89*f39d1f56SLois Curfman McInnes        0,0,0,
9071b459e3SLois Curfman McInnes        0,0,0,0 };
91e51e0e81SBarry Smith 
924b828684SBarry Smith /*@C
93052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
94ff756334SLois Curfman McInnes    private data storage format.
95e51e0e81SBarry Smith 
96e51e0e81SBarry Smith    Input Parameters:
976b5873e3SBarry Smith .  comm - MPI communicator
98*f39d1f56SLois Curfman McInnes .  m - number of local rows
99*f39d1f56SLois Curfman McInnes .  n - number of local columns
100*f39d1f56SLois Curfman McInnes .  M - number of global rows
101*f39d1f56SLois Curfman McInnes .  N - number of global columns
102deebb3c3SLois Curfman McInnes .  ctx - pointer to data needed by the shell matrix routines
103e51e0e81SBarry Smith 
104ff756334SLois Curfman McInnes    Output Parameter:
10544cd7ae7SLois Curfman McInnes .  A - the matrix
106e51e0e81SBarry Smith 
107*f39d1f56SLois Curfman McInnes    Usage:
108*f39d1f56SLois Curfman McInnes $   MatCreateShell(comm,m,n,M,N,ctx,&mat);
109*f39d1f56SLois Curfman McInnes $   MatShellSetOperation(mat,MAT_MULT,mult);
110*f39d1f56SLois Curfman McInnes $   [ Use matrix for operations that have been set ]
111*f39d1f56SLois Curfman McInnes $   MatDestroy(mat);
112*f39d1f56SLois Curfman McInnes 
113ff756334SLois Curfman McInnes    Notes:
114ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
115ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
116ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
117e51e0e81SBarry Smith 
118*f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
119*f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
120*f39d1f56SLois Curfman McInnes    creating a shell matrix that supports parallel matrix-vector
121*f39d1f56SLois Curfman McInnes    products using MatMult(), the user should set the number of local
122*f39d1f56SLois Curfman McInnes    matrix rows to be the same as the corresponding result vector
123*f39d1f56SLois Curfman McInnes    (even though the shell matrix may not actually be physically
124*f39d1f56SLois Curfman McInnes    partitioned or even stored at all).  For example,
125*f39d1f56SLois Curfman McInnes 
126*f39d1f56SLois Curfman McInnes $  /* Create matrix and vectors to compute y = Ax */
127*f39d1f56SLois Curfman McInnes $
128*f39d1f56SLois Curfman McInnes $     Vec x, y
129*f39d1f56SLois Curfman McInnes $     Mat mat
130*f39d1f56SLois Curfman McInnes $
131*f39d1f56SLois Curfman McInnes $     VecCreate(comm,M,&y);
132*f39d1f56SLois Curfman McInnes $     VecCreate(comm,N,&x);
133*f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
134*f39d1f56SLois Curfman McInnes $     MatCreateShell(comm,m,N,M,N,ctx,&mat);
135a62d957aSLois Curfman McInnes $     MatShellSetOperation(mat,MAT_MULT,mult);
136*f39d1f56SLois Curfman McInnes $     MatMult(mat,x,y);
137a62d957aSLois Curfman McInnes $     MatDestroy(mat);
138*f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
139e51e0e81SBarry Smith 
1400b627109SLois Curfman McInnes .keywords: matrix, shell, create
1410b627109SLois Curfman McInnes 
1423a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
143e51e0e81SBarry Smith @*/
144*f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
145e51e0e81SBarry Smith {
14644cd7ae7SLois Curfman McInnes   Mat       B;
14744cd7ae7SLois Curfman McInnes   Mat_Shell *b;
148ed3cc1f0SBarry Smith 
14944cd7ae7SLois Curfman McInnes   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm);
15044cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
15144cd7ae7SLois Curfman McInnes   B->factor    = 0;
15244cd7ae7SLois Curfman McInnes   B->destroy   = MatDestroy_Shell;
15344cd7ae7SLois Curfman McInnes   B->assembled = PETSC_TRUE;
15444cd7ae7SLois Curfman McInnes   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
155227d817aSBarry Smith 
15644cd7ae7SLois Curfman McInnes   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
15744cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_Shell));
15844cd7ae7SLois Curfman McInnes   B->data   = (void *) b;
159*f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
160*f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
161*f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
162*f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
16344cd7ae7SLois Curfman McInnes   b->ctx     = ctx;
16444cd7ae7SLois Curfman McInnes   *A = B;
165e51e0e81SBarry Smith   return 0;
166e51e0e81SBarry Smith }
167e51e0e81SBarry Smith 
168fae171e0SBarry Smith /*@
1693a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
1703a3eedf2SBarry Smith                            a shell matrix.
171e51e0e81SBarry Smith 
172e51e0e81SBarry Smith     Input Parameters:
173fae171e0SBarry Smith .   mat - the shell matrix
174fae171e0SBarry Smith .   op - the name of the operation
175fae171e0SBarry Smith .   f - the function that provides the operation.
176e51e0e81SBarry Smith 
177fae171e0SBarry Smith     Usage:
178a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
179*f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
180a62d957aSLois Curfman McInnes $      ierr = MatShellSetOperation(A,MAT_MULT,usermult);
1810b627109SLois Curfman McInnes 
182a62d957aSLois Curfman McInnes     Notes:
183a62d957aSLois Curfman McInnes     See the file petsc/include/mat.h for a complete list of matrix
184a62d957aSLois Curfman McInnes     operations, which all have the form MAT_<OPERATION>, where
185a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
186a62d957aSLois Curfman McInnes     user interface routine (e.g., MatMult() -> MAT_MULT).
187a62d957aSLois Curfman McInnes 
188a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
189deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
190deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
191deebb3c3SLois Curfman McInnes     routines, e.g.,
192a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
193a62d957aSLois Curfman McInnes 
194a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
195a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
196a62d957aSLois Curfman McInnes     set by MatCreateShell().
197a62d957aSLois Curfman McInnes 
198a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
199a62d957aSLois Curfman McInnes 
200a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellGetContext()
201e51e0e81SBarry Smith @*/
202fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f)
203e51e0e81SBarry Smith {
20477c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
205fae171e0SBarry Smith 
206a62d957aSLois Curfman McInnes   if (op == MAT_DESTROY) {
207a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
208a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell *) mat->data;
2093a3eedf2SBarry Smith        shell->destroy                                 = (int (*)(Mat)) f;
210a62d957aSLois Curfman McInnes     }
211a62d957aSLois Curfman McInnes     else mat->destroy                                 = (int (*)(PetscObject)) f;
212a62d957aSLois Curfman McInnes   }
213fae171e0SBarry Smith   else if (op == MAT_VIEW) mat->view                  = (int (*)(PetscObject,Viewer)) f;
214fae171e0SBarry Smith   else                     (((void **)&mat->ops)[op]) = f;
215a62d957aSLois Curfman McInnes 
21620563c6bSBarry Smith   return 0;
217e51e0e81SBarry Smith }
218f0479e8cSBarry Smith 
2193a3eedf2SBarry Smith 
2203a3eedf2SBarry Smith 
2213a3eedf2SBarry Smith 
2223a3eedf2SBarry Smith 
2233a3eedf2SBarry Smith 
224