Actual source code: mscatter.c
petsc-3.12.5 2020-03-29
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: .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MATSCATTER
27: @*/
28: PetscErrorCode MatScatterGetVecScatter(Mat mat,VecScatter *scatter)
29: {
30: Mat_Scatter *mscatter;
35: mscatter = (Mat_Scatter*)mat->data;
36: *scatter = mscatter->scatter;
37: return(0);
38: }
40: PetscErrorCode MatDestroy_Scatter(Mat mat)
41: {
43: Mat_Scatter *scatter = (Mat_Scatter*)mat->data;
46: VecScatterDestroy(&scatter->scatter);
47: PetscFree(mat->data);
48: return(0);
49: }
51: PetscErrorCode MatMult_Scatter(Mat A,Vec x,Vec y)
52: {
53: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
57: if (!scatter->scatter) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
58: VecZeroEntries(y);
59: VecScatterBegin(scatter->scatter,x,y,ADD_VALUES,SCATTER_FORWARD);
60: VecScatterEnd(scatter->scatter,x,y,ADD_VALUES,SCATTER_FORWARD);
61: return(0);
62: }
64: PetscErrorCode MatMultAdd_Scatter(Mat A,Vec x,Vec y,Vec z)
65: {
66: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
70: if (!scatter->scatter) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
71: if (z != y) {VecCopy(y,z);}
72: VecScatterBegin(scatter->scatter,x,z,ADD_VALUES,SCATTER_FORWARD);
73: VecScatterEnd(scatter->scatter,x,z,ADD_VALUES,SCATTER_FORWARD);
74: return(0);
75: }
77: PetscErrorCode MatMultTranspose_Scatter(Mat A,Vec x,Vec y)
78: {
79: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
83: if (!scatter->scatter) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
84: VecZeroEntries(y);
85: VecScatterBegin(scatter->scatter,x,y,ADD_VALUES,SCATTER_REVERSE);
86: VecScatterEnd(scatter->scatter,x,y,ADD_VALUES,SCATTER_REVERSE);
87: return(0);
88: }
90: PetscErrorCode MatMultTransposeAdd_Scatter(Mat A,Vec x,Vec y,Vec z)
91: {
92: Mat_Scatter *scatter = (Mat_Scatter*)A->data;
96: if (!scatter->scatter) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
97: if (z != y) {VecCopy(y,z);}
98: VecScatterBegin(scatter->scatter,x,z,ADD_VALUES,SCATTER_REVERSE);
99: VecScatterEnd(scatter->scatter,x,z,ADD_VALUES,SCATTER_REVERSE);
100: return(0);
101: }
103: static struct _MatOps MatOps_Values = {0,
104: 0,
105: 0,
106: MatMult_Scatter,
107: /* 4*/ MatMultAdd_Scatter,
108: MatMultTranspose_Scatter,
109: MatMultTransposeAdd_Scatter,
110: 0,
111: 0,
112: 0,
113: /* 10*/ 0,
114: 0,
115: 0,
116: 0,
117: 0,
118: /* 15*/ 0,
119: 0,
120: 0,
121: 0,
122: 0,
123: /* 20*/ 0,
124: 0,
125: 0,
126: 0,
127: /* 24*/ 0,
128: 0,
129: 0,
130: 0,
131: 0,
132: /* 29*/ 0,
133: 0,
134: 0,
135: 0,
136: 0,
137: /* 34*/ 0,
138: 0,
139: 0,
140: 0,
141: 0,
142: /* 39*/ 0,
143: 0,
144: 0,
145: 0,
146: 0,
147: /* 44*/ 0,
148: 0,
149: MatShift_Basic,
150: 0,
151: 0,
152: /* 49*/ 0,
153: 0,
154: 0,
155: 0,
156: 0,
157: /* 54*/ 0,
158: 0,
159: 0,
160: 0,
161: 0,
162: /* 59*/ 0,
163: MatDestroy_Scatter,
164: 0,
165: 0,
166: 0,
167: /* 64*/ 0,
168: 0,
169: 0,
170: 0,
171: 0,
172: /* 69*/ 0,
173: 0,
174: 0,
175: 0,
176: 0,
177: /* 74*/ 0,
178: 0,
179: 0,
180: 0,
181: 0,
182: /* 79*/ 0,
183: 0,
184: 0,
185: 0,
186: 0,
187: /* 84*/ 0,
188: 0,
189: 0,
190: 0,
191: 0,
192: /* 89*/ 0,
193: 0,
194: 0,
195: 0,
196: 0,
197: /* 94*/ 0,
198: 0,
199: 0,
200: 0,
201: 0,
202: /*99*/ 0,
203: 0,
204: 0,
205: 0,
206: 0,
207: /*104*/ 0,
208: 0,
209: 0,
210: 0,
211: 0,
212: /*109*/ 0,
213: 0,
214: 0,
215: 0,
216: 0,
217: /*114*/ 0,
218: 0,
219: 0,
220: 0,
221: 0,
222: /*119*/ 0,
223: 0,
224: 0,
225: 0,
226: 0,
227: /*124*/ 0,
228: 0,
229: 0,
230: 0,
231: 0,
232: /*129*/ 0,
233: 0,
234: 0,
235: 0,
236: 0,
237: /*134*/ 0,
238: 0,
239: 0,
240: 0,
241: 0,
242: /*139*/ 0,
243: 0,
244: 0
245: };
247: /*MC
248: MATSCATTER - MATSCATTER = "scatter" - A matrix type that simply applies a VecScatterBegin/End()
250: Level: advanced
252: .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MatScatterGetVecScatter()
254: M*/
256: PETSC_EXTERN PetscErrorCode MatCreate_Scatter(Mat A)
257: {
258: Mat_Scatter *b;
262: PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));
263: PetscNewLog(A,&b);
265: A->data = (void*)b;
267: PetscLayoutSetUp(A->rmap);
268: PetscLayoutSetUp(A->cmap);
270: A->assembled = PETSC_TRUE;
271: A->preallocated = PETSC_FALSE;
273: PetscObjectChangeTypeName((PetscObject)A,MATSCATTER);
274: return(0);
275: }
277: #include <petsc/private/vecscatterimpl.h>
278: /*@C
279: MatCreateScatter - Creates a new matrix based on a VecScatter
281: Collective
283: Input Parameters:
284: + comm - MPI communicator
285: - scatter - a VecScatterContext
287: Output Parameter:
288: . A - the matrix
290: Level: intermediate
292: PETSc requires that matrices and vectors being used for certain
293: operations are partitioned accordingly. For example, when
294: creating a scatter matrix, A, that supports parallel matrix-vector
295: products using MatMult(A,x,y) the user should set the number
296: of local matrix rows to be the number of local elements of the
297: corresponding result vector, y. Note that this is information is
298: required for use of the matrix interface routines, even though
299: the scatter matrix may not actually be physically partitioned.
301: Developer Notes: This directly accesses information inside the VecScatter associated with the matrix-vector product
302: for this matrix. This is not desirable..
305: .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER
306: @*/
307: PetscErrorCode MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A)
308: {
312: MatCreate(comm,A);
313: MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);
314: MatSetType(*A,MATSCATTER);
315: MatScatterSetVecScatter(*A,scatter);
316: MatSetUp(*A);
317: return(0);
318: }
320: /*@
321: MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator
323: Collective on Mat
325: Input Parameters:
326: + mat - the scatter matrix
327: - scatter - the scatter context create with VecScatterCreate()
329: Level: advanced
332: .seealso: MatCreateScatter(), MATSCATTER
333: @*/
334: PetscErrorCode MatScatterSetVecScatter(Mat mat,VecScatter scatter)
335: {
336: Mat_Scatter *mscatter = (Mat_Scatter*)mat->data;
343: 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);
344: 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);
346: PetscObjectReference((PetscObject)scatter);
347: VecScatterDestroy(&mscatter->scatter);
349: mscatter->scatter = scatter;
350: return(0);
351: }