xref: /petsc/src/mat/impls/shell/shell.c (revision 5615d1e584023db9367fb782d85b1b4ebbb8df18)
1357feee3SLois Curfman McInnes #ifndef lint
2*5615d1e5SSatish Balay static char vcid[] = "$Id: shell.c,v 1.41 1996/12/17 16:54:19 balay Exp balay $";
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"
1270f55243SBarry Smith #include "src/mat/matimpl.h"        /*I "mat.h" I*/
13f5eb4b81SSatish Balay #include "src/vec/vecimpl.h"
14e51e0e81SBarry Smith 
1520563c6bSBarry Smith typedef struct {
16f39d1f56SLois Curfman McInnes   int  M, N;                  /* number of global rows, columns */
17f39d1f56SLois 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 
22*5615d1e5SSatish Balay #undef __FUNC__
23*5615d1e5SSatish Balay #define __FUNC__ "MatShellGetContext"
24b4fd4287SBarry Smith /*@
25a62d957aSLois Curfman McInnes     MatShellGetContext - Returns the user-provided context associated with a shell matrix.
26b4fd4287SBarry Smith 
27b4fd4287SBarry Smith     Input Parameter:
28b4fd4287SBarry Smith .   mat - the matrix, should have been created with MatCreateShell()
29b4fd4287SBarry Smith 
30b4fd4287SBarry Smith     Output Parameter:
31b4fd4287SBarry Smith .   ctx - the user provided context
32b4fd4287SBarry Smith 
33a62d957aSLois Curfman McInnes     Notes:
34a62d957aSLois Curfman McInnes     This routine is intended for use within various shell matrix routines,
35a62d957aSLois Curfman McInnes     as set with MatShellSetOperation().
36a62d957aSLois Curfman McInnes 
37a62d957aSLois Curfman McInnes .keywords: matrix, shell, get, context
38a62d957aSLois Curfman McInnes 
39a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellSetOperation()
40b4fd4287SBarry Smith @*/
41b4fd4287SBarry Smith int MatShellGetContext(Mat mat,void **ctx)
42b4fd4287SBarry Smith {
4377c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
44b4fd4287SBarry Smith   if (mat->type != MATSHELL) *ctx = 0;
45b4fd4287SBarry Smith   else                       *ctx = ((Mat_Shell *) (mat->data))->ctx;
46b4fd4287SBarry Smith   return 0;
47b4fd4287SBarry Smith }
48b4fd4287SBarry Smith 
49*5615d1e5SSatish Balay #undef __FUNC__
50*5615d1e5SSatish Balay #define __FUNC__ "MatGetSize_Shell"
51f39d1f56SLois Curfman McInnes static int MatGetSize_Shell(Mat mat,int *M,int *N)
5271b459e3SLois Curfman McInnes {
5371b459e3SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
54f39d1f56SLois Curfman McInnes   *M = shell->M; *N = shell->N;
55f39d1f56SLois Curfman McInnes   return 0;
56f39d1f56SLois Curfman McInnes }
57f39d1f56SLois Curfman McInnes 
58*5615d1e5SSatish Balay #undef __FUNC__
59*5615d1e5SSatish Balay #define __FUNC__ "MatGetLocalSize_Shell"
60f39d1f56SLois Curfman McInnes static int MatGetLocalSize_Shell(Mat mat,int *m,int *n)
61f39d1f56SLois Curfman McInnes {
62f39d1f56SLois Curfman McInnes   Mat_Shell *shell = (Mat_Shell *) mat->data;
63f39d1f56SLois Curfman McInnes   *m = shell->n; *n = shell->n;
6471b459e3SLois Curfman McInnes   return 0;
6571b459e3SLois Curfman McInnes }
6671b459e3SLois Curfman McInnes 
67*5615d1e5SSatish Balay #undef __FUNC__
68*5615d1e5SSatish Balay #define __FUNC__ "MatDestroy_Shell"
6988cf3e7dSBarry Smith static int MatDestroy_Shell(PetscObject obj)
70e51e0e81SBarry Smith {
71b9fa9cd0SBarry Smith   int       ierr;
7220563c6bSBarry Smith   Mat       mat = (Mat) obj;
7388cf3e7dSBarry Smith   Mat_Shell *shell;
74ed3cc1f0SBarry Smith 
7588cf3e7dSBarry Smith   shell = (Mat_Shell *) mat->data;
763a3eedf2SBarry Smith   if (shell->destroy) {ierr = (*shell->destroy)(mat);CHKERRQ(ierr);}
770452661fSBarry Smith   PetscFree(shell);
783a3eedf2SBarry Smith   PLogObjectDestroy(mat);
793a3eedf2SBarry Smith   PetscHeaderDestroy(mat);
80e51e0e81SBarry Smith   return 0;
81e51e0e81SBarry Smith }
82e51e0e81SBarry Smith 
8320563c6bSBarry Smith static struct _MatOps MatOps = {0,0,
8420563c6bSBarry Smith        0,
85fae171e0SBarry Smith        0,0,0,0,
8620563c6bSBarry Smith        0,0,0,0,
8720563c6bSBarry Smith        0,0,
8820563c6bSBarry Smith        0,
8920563c6bSBarry Smith        0,
9020563c6bSBarry Smith        0,0,0,
9120563c6bSBarry Smith        0,
9220563c6bSBarry Smith        0,0,0,
9320563c6bSBarry Smith        0,0,
9420563c6bSBarry Smith        0,
9520563c6bSBarry Smith        0,0,0,0,
963b2fbd54SBarry Smith        0,MatGetSize_Shell,MatGetLocalSize_Shell,
97f39d1f56SLois Curfman McInnes        0,0,0,
9871b459e3SLois Curfman McInnes        0,0,0,0 };
99e51e0e81SBarry Smith 
100*5615d1e5SSatish Balay #undef __FUNC__
101*5615d1e5SSatish Balay #define __FUNC__ "MatCreateShell"
1024b828684SBarry Smith /*@C
103052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
104ff756334SLois Curfman McInnes    private data storage format.
105e51e0e81SBarry Smith 
106e51e0e81SBarry Smith    Input Parameters:
1076b5873e3SBarry Smith .  comm - MPI communicator
108f39d1f56SLois Curfman McInnes .  m - number of local rows
109f39d1f56SLois Curfman McInnes .  n - number of local columns
110f39d1f56SLois Curfman McInnes .  M - number of global rows
111f39d1f56SLois Curfman McInnes .  N - number of global columns
112deebb3c3SLois Curfman McInnes .  ctx - pointer to data needed by the shell matrix routines
113e51e0e81SBarry Smith 
114ff756334SLois Curfman McInnes    Output Parameter:
11544cd7ae7SLois Curfman McInnes .  A - the matrix
116e51e0e81SBarry Smith 
117f39d1f56SLois Curfman McInnes    Usage:
118f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
1191c1c02c0SLois Curfman McInnes $    MatShellSetOperation(mat,MATOP_MULT,mult);
120f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
121f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
122f39d1f56SLois Curfman McInnes 
123ff756334SLois Curfman McInnes    Notes:
124ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
125ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
126ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
127e51e0e81SBarry Smith 
128f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
129f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
130645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
131645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
132645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
133645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
134645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
135645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
136645985a0SLois Curfman McInnes    For example,
137f39d1f56SLois Curfman McInnes 
138f39d1f56SLois Curfman McInnes $
139f39d1f56SLois Curfman McInnes $     Vec x, y
140645985a0SLois Curfman McInnes $     Mat A
141f39d1f56SLois Curfman McInnes $
142f39d1f56SLois Curfman McInnes $     VecCreate(comm,M,&y);
143f39d1f56SLois Curfman McInnes $     VecCreate(comm,N,&x);
144f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
145645985a0SLois Curfman McInnes $     MatCreateShell(comm,m,N,M,N,ctx,&A);
1461c1c02c0SLois Curfman McInnes $     MatShellSetOperation(mat,MATOP_MULT,mult);
147645985a0SLois Curfman McInnes $     MatMult(A,x,y);
148645985a0SLois Curfman McInnes $     MatDestroy(A);
149f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
150645985a0SLois Curfman McInnes $
151e51e0e81SBarry Smith 
1520b627109SLois Curfman McInnes .keywords: matrix, shell, create
1530b627109SLois Curfman McInnes 
1543a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
155e51e0e81SBarry Smith @*/
156f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
157e51e0e81SBarry Smith {
15844cd7ae7SLois Curfman McInnes   Mat       B;
15944cd7ae7SLois Curfman McInnes   Mat_Shell *b;
160ed3cc1f0SBarry Smith 
16144cd7ae7SLois Curfman McInnes   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm);
16244cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
16344cd7ae7SLois Curfman McInnes   B->factor    = 0;
16444cd7ae7SLois Curfman McInnes   B->destroy   = MatDestroy_Shell;
16544cd7ae7SLois Curfman McInnes   B->assembled = PETSC_TRUE;
16644cd7ae7SLois Curfman McInnes   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
167227d817aSBarry Smith 
16844cd7ae7SLois Curfman McInnes   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
16944cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_Shell));
17044cd7ae7SLois Curfman McInnes   B->data   = (void *) b;
171f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
172f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
173f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
174f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
17544cd7ae7SLois Curfman McInnes   b->ctx     = ctx;
17644cd7ae7SLois Curfman McInnes   *A = B;
177e51e0e81SBarry Smith   return 0;
178e51e0e81SBarry Smith }
179e51e0e81SBarry Smith 
180*5615d1e5SSatish Balay #undef __FUNC__
181*5615d1e5SSatish Balay #define __FUNC__ "MatShellSetOperation"
182c16cb8f2SBarry Smith /*@C
1833a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
1843a3eedf2SBarry Smith                            a shell matrix.
185e51e0e81SBarry Smith 
186e51e0e81SBarry Smith     Input Parameters:
187fae171e0SBarry Smith .   mat - the shell matrix
188fae171e0SBarry Smith .   op - the name of the operation
189fae171e0SBarry Smith .   f - the function that provides the operation.
190e51e0e81SBarry Smith 
191fae171e0SBarry Smith     Usage:
192a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
193f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
1941c1c02c0SLois Curfman McInnes $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
1950b627109SLois Curfman McInnes 
196a62d957aSLois Curfman McInnes     Notes:
197a62d957aSLois Curfman McInnes     See the file petsc/include/mat.h for a complete list of matrix
1981c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
199a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
2001c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
201a62d957aSLois Curfman McInnes 
202a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
203deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
204deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
205deebb3c3SLois Curfman McInnes     routines, e.g.,
206a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
207a62d957aSLois Curfman McInnes 
208a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
209a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
210a62d957aSLois Curfman McInnes     set by MatCreateShell().
211a62d957aSLois Curfman McInnes 
212a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
213a62d957aSLois Curfman McInnes 
214a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellGetContext()
215e51e0e81SBarry Smith @*/
216fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f)
217e51e0e81SBarry Smith {
21877c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
219fae171e0SBarry Smith 
2201c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
221a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
222a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell *) mat->data;
2233a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
224a62d957aSLois Curfman McInnes     }
225a62d957aSLois Curfman McInnes     else mat->destroy                 = (int (*)(PetscObject)) f;
226a62d957aSLois Curfman McInnes   }
2271c1c02c0SLois Curfman McInnes   else if (op == MATOP_VIEW) mat->view  = (int (*)(PetscObject,Viewer)) f;
228fae171e0SBarry Smith   else      (((void**)&mat->ops)[op]) = f;
229a62d957aSLois Curfman McInnes 
23020563c6bSBarry Smith   return 0;
231e51e0e81SBarry Smith }
232f0479e8cSBarry Smith 
2333a3eedf2SBarry Smith 
2343a3eedf2SBarry Smith 
2353a3eedf2SBarry Smith 
2363a3eedf2SBarry Smith 
2373a3eedf2SBarry Smith 
238