xref: /petsc/src/mat/impls/shell/shell.c (revision 8f6be9af63786f3ee06b3c15b3b32a30d03edbd3)
1357feee3SLois Curfman McInnes #ifndef lint
2*8f6be9afSLois Curfman McInnes static char vcid[] = "$Id: shell.c,v 1.45 1997/02/22 02:25:22 bsmith 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"
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 
225615d1e5SSatish Balay #undef __FUNC__
235eea60f9SBarry Smith #define __FUNC__ "MatShellGetContext" /* ADIC Ignore */
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 
495615d1e5SSatish Balay #undef __FUNC__
505eea60f9SBarry Smith #define __FUNC__ "MatGetSize_Shell" /* ADIC Ignore */
51*8f6be9afSLois Curfman McInnes 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 
585615d1e5SSatish Balay #undef __FUNC__
595eea60f9SBarry Smith #define __FUNC__ "MatGetLocalSize_Shell" /* ADIC Ignore */
60*8f6be9afSLois Curfman McInnes 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 
675615d1e5SSatish Balay #undef __FUNC__
685eea60f9SBarry Smith #define __FUNC__ "MatDestroy_Shell" /* ADIC Ignore */
69*8f6be9afSLois Curfman McInnes 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 
83*8f6be9afSLois Curfman McInnes int MatGetOwnershipRange_Shell(Mat mat, int *rstart,int *rend)
84b951964fSBarry Smith {
85b951964fSBarry Smith   MPI_Scan(&mat->m,rend,1,MPI_INT,MPI_SUM,mat->comm);
86b951964fSBarry Smith   *rstart = *rend - mat->m;
87b951964fSBarry Smith   return 0;
88b951964fSBarry Smith }
89b951964fSBarry Smith 
90b951964fSBarry Smith 
91b951964fSBarry Smith 
92b951964fSBarry Smith 
93b951964fSBarry Smith static struct _MatOps MatOps = {0,
9420563c6bSBarry Smith        0,
9520563c6bSBarry Smith        0,
9620563c6bSBarry Smith        0,
9720563c6bSBarry Smith        0,
98b951964fSBarry Smith        0,
99b951964fSBarry Smith        0,
100b951964fSBarry Smith        0,
101b951964fSBarry Smith        0,
102b951964fSBarry Smith        0,
103b951964fSBarry Smith        0,
104b951964fSBarry Smith        0,
105b951964fSBarry Smith        0,
106b951964fSBarry Smith        0,
107b951964fSBarry Smith        0,
108b951964fSBarry Smith        0,
109b951964fSBarry Smith        0,
110b951964fSBarry Smith        0,
111b951964fSBarry Smith        0,
112b951964fSBarry Smith        0,
113b951964fSBarry Smith        0,
114b951964fSBarry Smith        0,
115b951964fSBarry Smith        0,
116b951964fSBarry Smith        0,
117b951964fSBarry Smith        0,
118b951964fSBarry Smith        0,
119b951964fSBarry Smith        0,
120b951964fSBarry Smith        0,
121b951964fSBarry Smith        0,
122b951964fSBarry Smith        0,
123b951964fSBarry Smith        MatGetSize_Shell,
124b951964fSBarry Smith        MatGetLocalSize_Shell,
125b951964fSBarry Smith        MatGetOwnershipRange_Shell,
126b951964fSBarry Smith        0,
127b951964fSBarry Smith        0,
128b951964fSBarry Smith        0,
129b951964fSBarry Smith        0,
130b951964fSBarry Smith        0 };
131e51e0e81SBarry Smith 
1325615d1e5SSatish Balay #undef __FUNC__
1335eea60f9SBarry Smith #define __FUNC__ "MatCreateShell" /* ADIC Ignore */
1344b828684SBarry Smith /*@C
135052efed2SBarry Smith    MatCreateShell - Creates a new matrix class for use with a user-defined
136ff756334SLois Curfman McInnes    private data storage format.
137e51e0e81SBarry Smith 
138e51e0e81SBarry Smith    Input Parameters:
1396b5873e3SBarry Smith .  comm - MPI communicator
140f39d1f56SLois Curfman McInnes .  m - number of local rows
141f39d1f56SLois Curfman McInnes .  n - number of local columns
142f39d1f56SLois Curfman McInnes .  M - number of global rows
143f39d1f56SLois Curfman McInnes .  N - number of global columns
144deebb3c3SLois Curfman McInnes .  ctx - pointer to data needed by the shell matrix routines
145e51e0e81SBarry Smith 
146ff756334SLois Curfman McInnes    Output Parameter:
14744cd7ae7SLois Curfman McInnes .  A - the matrix
148e51e0e81SBarry Smith 
149f39d1f56SLois Curfman McInnes    Usage:
150f39d1f56SLois Curfman McInnes $    MatCreateShell(comm,m,n,M,N,ctx,&mat);
1511c1c02c0SLois Curfman McInnes $    MatShellSetOperation(mat,MATOP_MULT,mult);
152f39d1f56SLois Curfman McInnes $    [ Use matrix for operations that have been set ]
153f39d1f56SLois Curfman McInnes $    MatDestroy(mat);
154f39d1f56SLois Curfman McInnes 
155ff756334SLois Curfman McInnes    Notes:
156ff756334SLois Curfman McInnes    The shell matrix type is intended to provide a simple class to use
157ff756334SLois Curfman McInnes    with KSP (such as, for use with matrix-free methods). You should not
158ff756334SLois Curfman McInnes    use the shell type if you plan to define a complete matrix class.
159e51e0e81SBarry Smith 
160f39d1f56SLois Curfman McInnes    PETSc requires that matrices and vectors being used for certain
161f39d1f56SLois Curfman McInnes    operations are partitioned accordingly.  For example, when
162645985a0SLois Curfman McInnes    creating a shell matrix, A, that supports parallel matrix-vector
163645985a0SLois Curfman McInnes    products using MatMult(A,x,y) the user should set the number
164645985a0SLois Curfman McInnes    of local matrix rows to be the number of local elements of the
165645985a0SLois Curfman McInnes    corresponding result vector, y. Note that this is information is
166645985a0SLois Curfman McInnes    required for use of the matrix interface routines, even though
167645985a0SLois Curfman McInnes    the shell matrix may not actually be physically partitioned.
168645985a0SLois Curfman McInnes    For example,
169f39d1f56SLois Curfman McInnes 
170f39d1f56SLois Curfman McInnes $
171f39d1f56SLois Curfman McInnes $     Vec x, y
172645985a0SLois Curfman McInnes $     Mat A
173f39d1f56SLois Curfman McInnes $
174f39d1f56SLois Curfman McInnes $     VecCreate(comm,M,&y);
175f39d1f56SLois Curfman McInnes $     VecCreate(comm,N,&x);
176f39d1f56SLois Curfman McInnes $     VecGetLocalSize(y,&m);
177645985a0SLois Curfman McInnes $     MatCreateShell(comm,m,N,M,N,ctx,&A);
1781c1c02c0SLois Curfman McInnes $     MatShellSetOperation(mat,MATOP_MULT,mult);
179645985a0SLois Curfman McInnes $     MatMult(A,x,y);
180645985a0SLois Curfman McInnes $     MatDestroy(A);
181f39d1f56SLois Curfman McInnes $     VecDestroy(y); VecDestroy(x);
182645985a0SLois Curfman McInnes $
183e51e0e81SBarry Smith 
1840b627109SLois Curfman McInnes .keywords: matrix, shell, create
1850b627109SLois Curfman McInnes 
1863a3eedf2SBarry Smith .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
187e51e0e81SBarry Smith @*/
188f39d1f56SLois Curfman McInnes int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
189e51e0e81SBarry Smith {
19044cd7ae7SLois Curfman McInnes   Mat       B;
19144cd7ae7SLois Curfman McInnes   Mat_Shell *b;
192ed3cc1f0SBarry Smith 
19344cd7ae7SLois Curfman McInnes   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSHELL,comm);
19444cd7ae7SLois Curfman McInnes   PLogObjectCreate(B);
19544cd7ae7SLois Curfman McInnes   B->factor    = 0;
19644cd7ae7SLois Curfman McInnes   B->destroy   = MatDestroy_Shell;
19744cd7ae7SLois Curfman McInnes   B->assembled = PETSC_TRUE;
19844cd7ae7SLois Curfman McInnes   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
199227d817aSBarry Smith 
20044cd7ae7SLois Curfman McInnes   b          = PetscNew(Mat_Shell); CHKPTRQ(b);
20144cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_Shell));
20244cd7ae7SLois Curfman McInnes   B->data   = (void *) b;
203f39d1f56SLois Curfman McInnes   b->M = M; B->M = M;
204f39d1f56SLois Curfman McInnes   b->N = N; B->N = N;
205f39d1f56SLois Curfman McInnes   b->m = m; B->m = m;
206f39d1f56SLois Curfman McInnes   b->n = n; B->n = n;
20744cd7ae7SLois Curfman McInnes   b->ctx     = ctx;
20844cd7ae7SLois Curfman McInnes   *A = B;
209e51e0e81SBarry Smith   return 0;
210e51e0e81SBarry Smith }
211e51e0e81SBarry Smith 
2125615d1e5SSatish Balay #undef __FUNC__
2135eea60f9SBarry Smith #define __FUNC__ "MatShellSetOperation" /* ADIC Ignore */
214c16cb8f2SBarry Smith /*@C
2153a3eedf2SBarry Smith     MatShellSetOperation - Allows user to set a matrix operation for
2163a3eedf2SBarry Smith                            a shell matrix.
217e51e0e81SBarry Smith 
218e51e0e81SBarry Smith     Input Parameters:
219fae171e0SBarry Smith .   mat - the shell matrix
220fae171e0SBarry Smith .   op - the name of the operation
221fae171e0SBarry Smith .   f - the function that provides the operation.
222e51e0e81SBarry Smith 
223fae171e0SBarry Smith     Usage:
224a62d957aSLois Curfman McInnes $      extern int usermult(Mat,Vec,Vec);
225f39d1f56SLois Curfman McInnes $      ierr = MatCreateShell(comm,m,n,M,N,ctx,&A);
2261c1c02c0SLois Curfman McInnes $      ierr = MatShellSetOperation(A,MATOP_MULT,usermult);
2270b627109SLois Curfman McInnes 
228a62d957aSLois Curfman McInnes     Notes:
229a62d957aSLois Curfman McInnes     See the file petsc/include/mat.h for a complete list of matrix
2301c1c02c0SLois Curfman McInnes     operations, which all have the form MATOP_<OPERATION>, where
231a62d957aSLois Curfman McInnes     <OPERATION> is the name (in all capital letters) of the
2321c1c02c0SLois Curfman McInnes     user interface routine (e.g., MatMult() -> MATOP_MULT).
233a62d957aSLois Curfman McInnes 
234a62d957aSLois Curfman McInnes     All user-provided functions should have the same calling
235deebb3c3SLois Curfman McInnes     sequence as the usual matrix interface routines, since they
236deebb3c3SLois Curfman McInnes     are intended to be accessed via the usual matrix interface
237deebb3c3SLois Curfman McInnes     routines, e.g.,
238a62d957aSLois Curfman McInnes $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
239a62d957aSLois Curfman McInnes 
240a62d957aSLois Curfman McInnes     Within each user-defined routine, the user should call
241a62d957aSLois Curfman McInnes     MatShellGetContext() to obtain the user-defined context that was
242a62d957aSLois Curfman McInnes     set by MatCreateShell().
243a62d957aSLois Curfman McInnes 
244a62d957aSLois Curfman McInnes .keywords: matrix, shell, set, operation
245a62d957aSLois Curfman McInnes 
246a62d957aSLois Curfman McInnes .seealso: MatCreateShell(), MatShellGetContext()
247e51e0e81SBarry Smith @*/
248fae171e0SBarry Smith int MatShellSetOperation(Mat mat,MatOperation op, void *f)
249e51e0e81SBarry Smith {
25077c4ece6SBarry Smith   PetscValidHeaderSpecific(mat,MAT_COOKIE);
251fae171e0SBarry Smith 
2521c1c02c0SLois Curfman McInnes   if (op == MATOP_DESTROY) {
253a62d957aSLois Curfman McInnes     if (mat->type == MATSHELL) {
254a62d957aSLois Curfman McInnes        Mat_Shell *shell = (Mat_Shell *) mat->data;
2553a3eedf2SBarry Smith        shell->destroy                 = (int (*)(Mat)) f;
256a62d957aSLois Curfman McInnes     }
257a62d957aSLois Curfman McInnes     else mat->destroy                 = (int (*)(PetscObject)) f;
258a62d957aSLois Curfman McInnes   }
2591c1c02c0SLois Curfman McInnes   else if (op == MATOP_VIEW) mat->view  = (int (*)(PetscObject,Viewer)) f;
260fae171e0SBarry Smith   else      (((void**)&mat->ops)[op]) = f;
261a62d957aSLois Curfman McInnes 
26220563c6bSBarry Smith   return 0;
263e51e0e81SBarry Smith }
264f0479e8cSBarry Smith 
2653a3eedf2SBarry Smith 
2663a3eedf2SBarry Smith 
267