Actual source code: mscatter.c
petsc-3.8.4 2018-03-24
2: /*
3: This provides a matrix that applies a VecScatter to a vector.
4: */
6: #include <petsc/private/matimpl.h>
7: #include <petsc/private/vecimpl.h>
9: typedef struct {
10: VecScatter scatter;
11: } Mat_Scatter;
13: /*@
14: MatScatterGetVecScatter - Returns the user-provided scatter set with MatScatterSetVecScatter()
16: Not Collective, but not cannot use scatter if not used collectively on Mat
18: Input Parameter:
19: . mat - the matrix, should have been created with MatCreateScatter() or have type MATSCATTER
21: Output Parameter:
22: . scatter - the scatter context
24: Level: intermediate
26: .keywords: matrix, scatter, get
28: .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MATSCATTER
29: @*/
30: PetscErrorCode MatScatterGetVecScatter(Mat mat,VecScatter *scatter)
31: {
32: Mat_Scatter *mscatter;
37: mscatter = (Mat_Scatter*)mat->data;
38: *scatter = mscatter->scatter;
39: return(0);
40: }
42: PetscErrorCode MatDestroy_Scatter(Mat mat)
43: {
45: Mat_Scatter *scatter = (Mat_Scatter*)mat->data;
48: VecScatterDestroy(&scatter->scatter);
49: PetscFree(mat->data);
50: return(0);
51: }
53: PetscErrorCode MatMult_Scatter(Mat A,Vec x,Vec y)
54: {
55: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
59: if (!scatter->scatter) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
60: VecZeroEntries(y);
61: VecScatterBegin(scatter->scatter,x,y,ADD_VALUES,SCATTER_FORWARD);
62: VecScatterEnd(scatter->scatter,x,y,ADD_VALUES,SCATTER_FORWARD);
63: return(0);
64: }
66: PetscErrorCode MatMultAdd_Scatter(Mat A,Vec x,Vec y,Vec z)
67: {
68: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
72: if (!scatter->scatter) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
73: if (z != y) {VecCopy(y,z);}
74: VecScatterBegin(scatter->scatter,x,z,ADD_VALUES,SCATTER_FORWARD);
75: VecScatterEnd(scatter->scatter,x,z,ADD_VALUES,SCATTER_FORWARD);
76: return(0);
77: }
79: PetscErrorCode MatMultTranspose_Scatter(Mat A,Vec x,Vec y)
80: {
81: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
85: if (!scatter->scatter) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
86: VecZeroEntries(y);
87: VecScatterBegin(scatter->scatter,x,y,ADD_VALUES,SCATTER_REVERSE);
88: VecScatterEnd(scatter->scatter,x,y,ADD_VALUES,SCATTER_REVERSE);
89: return(0);
90: }
92: PetscErrorCode MatMultTransposeAdd_Scatter(Mat A,Vec x,Vec y,Vec z)
93: {
94: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
98: if (!scatter->scatter) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
99: if (z != y) {VecCopy(y,z);}
100: VecScatterBegin(scatter->scatter,x,z,ADD_VALUES,SCATTER_REVERSE);
101: VecScatterEnd(scatter->scatter,x,z,ADD_VALUES,SCATTER_REVERSE);
102: return(0);
103: }
105: static struct _MatOps MatOps_Values = {0,
106: 0,
107: 0,
108: MatMult_Scatter,
109: /* 4*/ MatMultAdd_Scatter,
110: MatMultTranspose_Scatter,
111: MatMultTransposeAdd_Scatter,
112: 0,
113: 0,
114: 0,
115: /* 10*/ 0,
116: 0,
117: 0,
118: 0,
119: 0,
120: /* 15*/ 0,
121: 0,
122: 0,
123: 0,
124: 0,
125: /* 20*/ 0,
126: 0,
127: 0,
128: 0,
129: /* 24*/ 0,
130: 0,
131: 0,
132: 0,
133: 0,
134: /* 29*/ 0,
135: 0,
136: 0,
137: 0,
138: 0,
139: /* 34*/ 0,
140: 0,
141: 0,
142: 0,
143: 0,
144: /* 39*/ 0,
145: 0,
146: 0,
147: 0,
148: 0,
149: /* 44*/ 0,
150: 0,
151: MatShift_Basic,
152: 0,
153: 0,
154: /* 49*/ 0,
155: 0,
156: 0,
157: 0,
158: 0,
159: /* 54*/ 0,
160: 0,
161: 0,
162: 0,
163: 0,
164: /* 59*/ 0,
165: MatDestroy_Scatter,
166: 0,
167: 0,
168: 0,
169: /* 64*/ 0,
170: 0,
171: 0,
172: 0,
173: 0,
174: /* 69*/ 0,
175: 0,
176: 0,
177: 0,
178: 0,
179: /* 74*/ 0,
180: 0,
181: 0,
182: 0,
183: 0,
184: /* 79*/ 0,
185: 0,
186: 0,
187: 0,
188: 0,
189: /* 84*/ 0,
190: 0,
191: 0,
192: 0,
193: 0,
194: /* 89*/ 0,
195: 0,
196: 0,
197: 0,
198: 0,
199: /* 94*/ 0,
200: 0,
201: 0,
202: 0,
203: 0,
204: /*99*/ 0,
205: 0,
206: 0,
207: 0,
208: 0,
209: /*104*/ 0,
210: 0,
211: 0,
212: 0,
213: 0,
214: /*109*/ 0,
215: 0,
216: 0,
217: 0,
218: 0,
219: /*114*/ 0,
220: 0,
221: 0,
222: 0,
223: 0,
224: /*119*/ 0,
225: 0,
226: 0,
227: 0,
228: 0,
229: /*124*/ 0,
230: 0,
231: 0,
232: 0,
233: 0,
234: /*129*/ 0,
235: 0,
236: 0,
237: 0,
238: 0,
239: /*134*/ 0,
240: 0,
241: 0,
242: 0,
243: 0,
244: /*139*/ 0,
245: 0,
246: 0
247: };
249: /*MC
250: MATSCATTER - MATSCATTER = "scatter" - A matrix type that simply applies a VecScatterBegin/End()
252: Level: advanced
254: .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MatScatterGetVecScatter()
256: M*/
258: PETSC_EXTERN PetscErrorCode MatCreate_Scatter(Mat A)
259: {
260: Mat_Scatter *b;
264: PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));
265: PetscNewLog(A,&b);
267: A->data = (void*)b;
269: PetscLayoutSetUp(A->rmap);
270: PetscLayoutSetUp(A->cmap);
272: A->assembled = PETSC_TRUE;
273: A->preallocated = PETSC_FALSE;
275: PetscObjectChangeTypeName((PetscObject)A,MATSCATTER);
276: return(0);
277: }
279: /*@C
280: MatCreateScatter - Creates a new matrix based on a VecScatter
282: Collective on MPI_Comm
284: Input Parameters:
285: + comm - MPI communicator
286: - scatter - a VecScatterContext
288: Output Parameter:
289: . A - the matrix
291: Level: intermediate
293: PETSc requires that matrices and vectors being used for certain
294: operations are partitioned accordingly. For example, when
295: creating a scatter matrix, A, that supports parallel matrix-vector
296: products using MatMult(A,x,y) the user should set the number
297: of local matrix rows to be the number of local elements of the
298: corresponding result vector, y. Note that this is information is
299: required for use of the matrix interface routines, even though
300: the scatter matrix may not actually be physically partitioned.
302: .keywords: matrix, scatter, create
304: .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER
305: @*/
306: PetscErrorCode MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A)
307: {
311: MatCreate(comm,A);
312: MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);
313: MatSetType(*A,MATSCATTER);
314: MatScatterSetVecScatter(*A,scatter);
315: MatSetUp(*A);
316: return(0);
317: }
319: /*@
320: MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator
322: Collective on Mat
324: Input Parameters:
325: + mat - the scatter matrix
326: - scatter - the scatter context create with VecScatterCreate()
328: Level: advanced
331: .seealso: MatCreateScatter(), MATSCATTER
332: @*/
333: PetscErrorCode MatScatterSetVecScatter(Mat mat,VecScatter scatter)
334: {
335: Mat_Scatter *mscatter = (Mat_Scatter*)mat->data;
342: if (mat->rmap->n != scatter->to_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Number of local rows in matrix %D not equal local scatter size %D",mat->rmap->n,scatter->to_n);
343: if (mat->cmap->n != scatter->from_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Number of local columns in matrix %D not equal local scatter size %D",mat->cmap->n,scatter->from_n);
345: PetscObjectReference((PetscObject)scatter);
346: VecScatterDestroy(&mscatter->scatter);
348: mscatter->scatter = scatter;
349: return(0);
350: }