Actual source code: mscatter.c
petsc-3.11.4 2019-09-28
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: #include <petsc/private/vecscatterimpl.h>
280: /*@C
281: MatCreateScatter - Creates a new matrix based on a VecScatter
283: Collective on MPI_Comm
285: Input Parameters:
286: + comm - MPI communicator
287: - scatter - a VecScatterContext
289: Output Parameter:
290: . A - the matrix
292: Level: intermediate
294: PETSc requires that matrices and vectors being used for certain
295: operations are partitioned accordingly. For example, when
296: creating a scatter matrix, A, that supports parallel matrix-vector
297: products using MatMult(A,x,y) the user should set the number
298: of local matrix rows to be the number of local elements of the
299: corresponding result vector, y. Note that this is information is
300: required for use of the matrix interface routines, even though
301: the scatter matrix may not actually be physically partitioned.
303: Developer Notes: This directly accesses information inside the VecScatter associated with the matrix-vector product
304: for this matrix. This is not desirable..
307: .keywords: matrix, scatter, create
309: .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER
310: @*/
311: PetscErrorCode MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A)
312: {
316: MatCreate(comm,A);
317: MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);
318: MatSetType(*A,MATSCATTER);
319: MatScatterSetVecScatter(*A,scatter);
320: MatSetUp(*A);
321: return(0);
322: }
324: /*@
325: MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator
327: Collective on Mat
329: Input Parameters:
330: + mat - the scatter matrix
331: - scatter - the scatter context create with VecScatterCreate()
333: Level: advanced
336: .seealso: MatCreateScatter(), MATSCATTER
337: @*/
338: PetscErrorCode MatScatterSetVecScatter(Mat mat,VecScatter scatter)
339: {
340: Mat_Scatter *mscatter = (Mat_Scatter*)mat->data;
347: 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);
348: 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);
350: PetscObjectReference((PetscObject)scatter);
351: VecScatterDestroy(&mscatter->scatter);
353: mscatter->scatter = scatter;
354: return(0);
355: }