Actual source code: shell.c
1: /*$Id: shell.c,v 1.86 2001/03/28 19:41:21 balay Exp $*/
3: /*
4: This provides a simple shell for Fortran (and C programmers) to
5: create a very simple matrix class for use with KSP without coding
6: much of anything.
7: */
9: #include "src/mat/matimpl.h" /*I "petscmat.h" I*/
10: #include "src/vec/vecimpl.h"
12: typedef struct {
13: int (*destroy)(Mat);
14: void *ctx;
15: } Mat_Shell;
17: /*@
18: MatShellGetContext - Returns the user-provided context associated with a shell matrix.
20: Not Collective
22: Input Parameter:
23: . mat - the matrix, should have been created with MatCreateShell()
25: Output Parameter:
26: . ctx - the user provided context
28: Level: advanced
30: Notes:
31: This routine is intended for use within various shell matrix routines,
32: as set with MatShellSetOperation().
33:
34: .keywords: matrix, shell, get, context
36: .seealso: MatCreateShell(), MatShellSetOperation()
37: @*/
38: int MatShellGetContext(Mat mat,void **ctx)
39: {
40: int ierr;
41: PetscTruth flg;
45: PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);
46: if (!flg) *ctx = 0;
47: else *ctx = ((Mat_Shell*)(mat->data))->ctx;
48: return(0);
49: }
51: int MatDestroy_Shell(Mat mat)
52: {
53: int ierr;
54: Mat_Shell *shell;
57: shell = (Mat_Shell*)mat->data;
58: if (shell->destroy) {(*shell->destroy)(mat);}
59: PetscFree(shell);
60: return(0);
61: }
63: int MatGetOwnershipRange_Shell(Mat mat,int *rstart,int *rend)
64: {
65: int ierr,tmp;
68: MPI_Scan(&mat->m,&tmp,1,MPI_INT,MPI_SUM,mat->comm);
69: if (rstart) *rstart = tmp - mat->m;
70: if (rend) *rend = tmp;
71: return(0);
72: }
73: extern int MatConvert_Shell(Mat,MatType,Mat*);
75: static struct _MatOps MatOps_Values = {0,
76: 0,
77: 0,
78: 0,
79: 0,
80: 0,
81: 0,
82: 0,
83: 0,
84: 0,
85: 0,
86: 0,
87: 0,
88: 0,
89: 0,
90: 0,
91: 0,
92: 0,
93: 0,
94: 0,
95: 0,
96: 0,
97: 0,
98: 0,
99: 0,
100: 0,
101: 0,
102: 0,
103: 0,
104: 0,
105: 0,
106: MatGetOwnershipRange_Shell,
107: 0,
108: 0,
109: 0,
110: 0,
111: 0,
112: 0,
113: 0,
114: 0,
115: 0,
116: 0,
117: 0,
118: 0,
119: 0,
120: 0,
121: 0,
122: 0,
123: 0,
124: 0,
125: 0,
126: 0,
127: 0,
128: 0,
129: 0,
130: 0,
131: 0,
132: 0,
133: 0,
134: 0,
135: 0,
136: 0,
137: 0,
138: MatDestroy_Shell,
139: 0,
140: MatGetMaps_Petsc,
141: 0,
142: 0,
143: 0,
144: 0,
145: 0,
146: 0,
147: 0,
148: MatConvert_Shell};
150: EXTERN_C_BEGIN
151: int MatCreate_Shell(Mat A)
152: {
153: Mat_Shell *b;
154: int ierr;
157: ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));
159: PetscNew(Mat_Shell,&b);
160: PetscLogObjectMemory(A,sizeof(struct _p_Mat)+sizeof(Mat_Shell));
161: ierr = PetscMemzero(b,sizeof(Mat_Shell));
162: A->data = (void*)b;
164: if (A->m == PETSC_DECIDE || A->n == PETSC_DECIDE) {
165: SETERRQ(1,"Must give local row and column count for matrix");
166: }
168: PetscSplitOwnership(A->comm,&A->m,&A->M);
169: PetscSplitOwnership(A->comm,&A->n,&A->N);
171: MapCreateMPI(A->comm,A->m,A->M,&A->rmap);
172: MapCreateMPI(A->comm,A->n,A->N,&A->cmap);
174: b->ctx = 0;
175: A->assembled = PETSC_TRUE;
176: A->preallocated = PETSC_TRUE;
177: return(0);
178: }
179: EXTERN_C_END
181: /*@C
182: MatCreateShell - Creates a new matrix class for use with a user-defined
183: private data storage format.
185: Collective on MPI_Comm
187: Input Parameters:
188: + comm - MPI communicator
189: . m - number of local rows (must be given)
190: . n - number of local columns (must be given)
191: . M - number of global rows (may be PETSC_DETERMINE)
192: . N - number of global columns (may be PETSC_DETERMINE)
193: - ctx - pointer to data needed by the shell matrix routines
195: Output Parameter:
196: . A - the matrix
198: Level: advanced
200: Usage:
201: $ extern int mult(Mat,Vec,Vec);
202: $ MatCreateShell(comm,m,n,M,N,ctx,&mat);
203: $ MatShellSetOperation(mat,MATOP_MULT,(void(*)())mult);
204: $ [ Use matrix for operations that have been set ]
205: $ MatDestroy(mat);
207: Notes:
208: The shell matrix type is intended to provide a simple class to use
209: with KSP (such as, for use with matrix-free methods). You should not
210: use the shell type if you plan to define a complete matrix class.
212: PETSc requires that matrices and vectors being used for certain
213: operations are partitioned accordingly. For example, when
214: creating a shell matrix, A, that supports parallel matrix-vector
215: products using MatMult(A,x,y) the user should set the number
216: of local matrix rows to be the number of local elements of the
217: corresponding result vector, y. Note that this is information is
218: required for use of the matrix interface routines, even though
219: the shell matrix may not actually be physically partitioned.
220: For example,
222: $
223: $ Vec x, y
224: $ extern int mult(Mat,Vec,Vec);
225: $ Mat A
226: $
227: $ VecCreateMPI(comm,PETSC_DECIDE,M,&y);
228: $ VecCreateMPI(comm,PETSC_DECIDE,N,&x);
229: $ VecGetLocalSize(y,&m);
230: $ VecGetLocalSize(x,&n);
231: $ MatCreateShell(comm,m,n,M,N,ctx,&A);
232: $ MatShellSetOperation(mat,MATOP_MULT,(void(*)())mult);
233: $ MatMult(A,x,y);
234: $ MatDestroy(A);
235: $ VecDestroy(y); VecDestroy(x);
236: $
238: .keywords: matrix, shell, create
240: .seealso: MatShellSetOperation(), MatHasOperation(), MatShellGetContext()
241: @*/
242: int MatCreateShell(MPI_Comm comm,int m,int n,int M,int N,void *ctx,Mat *A)
243: {
244: int ierr;
247: MatCreate(comm,m,n,M,N,A);
248: MatSetType(*A,MATSHELL);
249: MatShellSetContext(*A,ctx);
250: return(0);
251: }
253: /*@C
254: MatShellSetContext - sets the context for a shell matrix
256: Collective on Mat
258: Input Parameters:
259: + mat - the shell matrix
260: - ctx - the context
262: Level: advanced
265: .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
266: @*/
267: int MatShellSetContext(Mat mat,void *ctx)
268: {
269: Mat_Shell *shell = (Mat_Shell*)mat->data;
270: int ierr;
271: PetscTruth flg;
275: PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);
276: if (flg) {
277: shell->ctx = ctx;
278: }
279: return(0);
280: }
282: /*@C
283: MatShellSetOperation - Allows user to set a matrix operation for
284: a shell matrix.
286: Collective on Mat
288: Input Parameters:
289: + mat - the shell matrix
290: . op - the name of the operation
291: - f - the function that provides the operation.
293: Level: advanced
295: Usage:
296: $ extern int usermult(Mat,Vec,Vec);
297: $ MatCreateShell(comm,m,n,M,N,ctx,&A);
298: $ MatShellSetOperation(A,MATOP_MULT,(void(*)())usermult);
300: Notes:
301: See the file include/petscmat.h for a complete list of matrix
302: operations, which all have the form MATOP_<OPERATION>, where
303: <OPERATION> is the name (in all capital letters) of the
304: user interface routine (e.g., MatMult() -> MATOP_MULT).
306: All user-provided functions should have the same calling
307: sequence as the usual matrix interface routines, since they
308: are intended to be accessed via the usual matrix interface
309: routines, e.g.,
310: $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
312: Within each user-defined routine, the user should call
313: MatShellGetContext() to obtain the user-defined context that was
314: set by MatCreateShell().
316: .keywords: matrix, shell, set, operation
318: .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation()
319: @*/
320: int MatShellSetOperation(Mat mat,MatOperation op,void (*f)())
321: {
322: int ierr;
323: PetscTruth flg;
327: if (op == MATOP_DESTROY) {
328: PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);
329: if (flg) {
330: Mat_Shell *shell = (Mat_Shell*)mat->data;
331: shell->destroy = (int (*)(Mat)) f;
332: } else mat->ops->destroy = (int (*)(Mat)) f;
333: }
334: else if (op == MATOP_VIEW) mat->ops->view = (int (*)(Mat,PetscViewer)) f;
335: else (((void(**)())mat->ops)[op]) = f;
337: return(0);
338: }
340: /*@C
341: MatShellGetOperation - Gets a matrix function for a shell matrix.
343: Not Collective
345: Input Parameters:
346: + mat - the shell matrix
347: - op - the name of the operation
349: Output Parameter:
350: . f - the function that provides the operation.
352: Level: advanced
354: Notes:
355: See the file include/petscmat.h for a complete list of matrix
356: operations, which all have the form MATOP_<OPERATION>, where
357: <OPERATION> is the name (in all capital letters) of the
358: user interface routine (e.g., MatMult() -> MATOP_MULT).
360: All user-provided functions have the same calling
361: sequence as the usual matrix interface routines, since they
362: are intended to be accessed via the usual matrix interface
363: routines, e.g.,
364: $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
366: Within each user-defined routine, the user should call
367: MatShellGetContext() to obtain the user-defined context that was
368: set by MatCreateShell().
370: .keywords: matrix, shell, set, operation
372: .seealso: MatCreateShell(), MatShellGetContext(), MatShellSetOperation()
373: @*/
374: int MatShellGetOperation(Mat mat,MatOperation op,void(**f)())
375: {
376: int ierr;
377: PetscTruth flg;
381: if (op == MATOP_DESTROY) {
382: PetscTypeCompare((PetscObject)mat,MATSHELL,&flg);
383: if (flg) {
384: Mat_Shell *shell = (Mat_Shell*)mat->data;
385: *f = (void(*)())shell->destroy;
386: } else {
387: *f = (void(*)())mat->ops->destroy;
388: }
389: } else if (op == MATOP_VIEW) {
390: *f = (void(*)())mat->ops->view;
391: } else {
392: *f = (((void(**)())mat->ops)[op]);
393: }
395: return(0);
396: }