Actual source code: mscatter.c
1: #define PETSCMAT_DLL
3: /*
4: This provides a matrix that applies a VecScatter to a vector.
5: */
7: #include include/private/matimpl.h
8: #include private/vecimpl.h
10: typedef struct {
11: VecScatter scatter;
12: } Mat_Scatter;
16: /*@
17: MatScatterGetVecScatter - Returns the user-provided scatter set with MatScatterSetVecScatter()
19: Not Collective, but not cannot use scatter if not used collectively on Mat
21: Input Parameter:
22: . mat - the matrix, should have been created with MatCreateScatter() or have type MATSCATTER
24: Output Parameter:
25: . scatter - the scatter context
27: Level: intermediate
29: .keywords: matrix, scatter, get
31: .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MATSCATTER
32: @*/
33: PetscErrorCode MatScatterGetVecScatter(Mat mat,VecScatter *scatter)
34: {
35: Mat_Scatter *mscatter;
40: mscatter = (Mat_Scatter*)mat->data;
41: *scatter = mscatter->scatter;
42: return(0);
43: }
47: PetscErrorCode MatDestroy_Scatter(Mat mat)
48: {
50: Mat_Scatter *scatter = (Mat_Scatter*)mat->data;
53: if (scatter->scatter) {VecScatterDestroy(scatter->scatter);}
54: PetscFree(scatter);
55: return(0);
56: }
60: PetscErrorCode MatMult_Scatter(Mat A,Vec x,Vec y)
61: {
62: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
66: if (!scatter->scatter) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
67: VecScatterBegin(x,y,INSERT_VALUES,SCATTER_FORWARD,scatter->scatter);
68: VecScatterEnd(x,y,INSERT_VALUES,SCATTER_FORWARD,scatter->scatter);
69: return(0);
70: }
74: PetscErrorCode MatMultAdd_Scatter(Mat A,Vec x,Vec y,Vec z)
75: {
76: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
80: if (!scatter->scatter) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
81: if (z != y) {VecCopy(y,z);}
82: VecScatterBegin(x,z,ADD_VALUES,SCATTER_FORWARD,scatter->scatter);
83: VecScatterEnd(x,z,ADD_VALUES,SCATTER_FORWARD,scatter->scatter);
84: return(0);
85: }
89: PetscErrorCode MatMultTranspose_Scatter(Mat A,Vec x,Vec y)
90: {
91: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
95: if (!scatter->scatter) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
96: VecScatterBegin(x,y,INSERT_VALUES,SCATTER_REVERSE,scatter->scatter);
97: VecScatterEnd(x,y,INSERT_VALUES,SCATTER_REVERSE,scatter->scatter);
98: return(0);
99: }
103: PetscErrorCode MatMultTransposeAdd_Scatter(Mat A,Vec x,Vec y,Vec z)
104: {
105: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
109: if (!scatter->scatter) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
110: if (z != y) {VecCopy(y,z);}
111: VecScatterBegin(x,z,ADD_VALUES,SCATTER_REVERSE,scatter->scatter);
112: VecScatterEnd(x,z,ADD_VALUES,SCATTER_REVERSE,scatter->scatter);
113: return(0);
114: }
116: static struct _MatOps MatOps_Values = {0,
117: 0,
118: 0,
119: MatMult_Scatter,
120: /* 4*/ MatMultAdd_Scatter,
121: MatMultTranspose_Scatter,
122: MatMultTransposeAdd_Scatter,
123: 0,
124: 0,
125: 0,
126: /*10*/ 0,
127: 0,
128: 0,
129: 0,
130: 0,
131: /*15*/ 0,
132: 0,
133: 0,
134: 0,
135: 0,
136: /*20*/ 0,
137: 0,
138: 0,
139: 0,
140: 0,
141: /*25*/ 0,
142: 0,
143: 0,
144: 0,
145: 0,
146: /*30*/ 0,
147: 0,
148: 0,
149: 0,
150: 0,
151: /*35*/ 0,
152: 0,
153: 0,
154: 0,
155: 0,
156: /*40*/ 0,
157: 0,
158: 0,
159: 0,
160: 0,
161: /*45*/ 0,
162: 0,
163: 0,
164: 0,
165: 0,
166: /*50*/ 0,
167: 0,
168: 0,
169: 0,
170: 0,
171: /*55*/ 0,
172: 0,
173: 0,
174: 0,
175: 0,
176: /*60*/ 0,
177: MatDestroy_Scatter,
178: 0,
179: 0,
180: 0,
181: /*65*/ 0,
182: 0,
183: 0,
184: 0,
185: 0,
186: /*70*/ 0,
187: 0,
188: 0,
189: 0,
190: 0,
191: /*75*/ 0,
192: 0,
193: 0,
194: 0,
195: 0,
196: /*80*/ 0,
197: 0,
198: 0,
199: 0,
200: 0,
201: /*85*/ 0,
202: 0,
203: 0,
204: 0,
205: 0,
206: /*90*/ 0,
207: 0,
208: 0,
209: 0,
210: 0,
211: /*95*/ 0,
212: 0,
213: 0,
214: 0};
216: /*MC
217: MATSCATTER - MATSCATTER = "scatter" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
219: Level: advanced
221: .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MatScatterGetVecScatter()
223: M*/
228: PetscErrorCode MatCreate_Scatter(Mat A)
229: {
230: Mat_Scatter *b;
234: PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));
235: PetscNew(Mat_Scatter,&b);
237: A->data = (void*)b;
239: PetscMapInitialize(A->comm,&A->rmap);
240: PetscMapInitialize(A->comm,&A->cmap);
242: A->assembled = PETSC_TRUE;
243: A->preallocated = PETSC_FALSE;
244: return(0);
245: }
250: /*@C
251: MatCreateScatter - Creates a new matrix based on a VecScatter
253: Collective on MPI_Comm
255: Input Parameters:
256: + comm - MPI communicator
257: - scatter - a VecScatterContext
259: Output Parameter:
260: . A - the matrix
262: Level: intermediate
264: PETSc requires that matrices and vectors being used for certain
265: operations are partitioned accordingly. For example, when
266: creating a scatter matrix, A, that supports parallel matrix-vector
267: products using MatMult(A,x,y) the user should set the number
268: of local matrix rows to be the number of local elements of the
269: corresponding result vector, y. Note that this is information is
270: required for use of the matrix interface routines, even though
271: the scatter matrix may not actually be physically partitioned.
272: For example,
274: .keywords: matrix, scatter, create
276: .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER
277: @*/
278: PetscErrorCode MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A)
279: {
283: MatCreate(comm,A);
284: MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);
285: MatSetType(*A,MATSCATTER);
286: MatScatterSetVecScatter(*A,scatter);
287: return(0);
288: }
292: /*@
293: MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator
295: Collective on Mat
297: Input Parameters:
298: + mat - the scatter matrix
299: - scatter - the scatter context create with VecScatterCreate()
301: Level: advanced
304: .seealso: MatCreateScatter(), MATSCATTER
305: @*/
306: PetscErrorCode MatScatterSetVecScatter(Mat mat,VecScatter scatter)
307: {
308: Mat_Scatter *mscatter = (Mat_Scatter*)mat->data;
315: if (mat->rmap.n != scatter->to_n) SETERRQ2(PETSC_ERR_ARG_SIZ,"Number of local rows in matrix %D not equal local scatter size %D",mat->rmap.n,scatter->to_n);
316: if (mat->cmap.n != scatter->from_n) SETERRQ2(PETSC_ERR_ARG_SIZ,"Number of local columns in matrix %D not equal local scatter size %D",mat->cmap.n,scatter->from_n);
318: if (mscatter->scatter) {VecScatterDestroy(mscatter->scatter);}
319: mscatter->scatter = scatter;
320: PetscObjectReference((PetscObject)scatter);
321: return(0);
322: }