Actual source code: mscatter.c
petsc-3.14.6 2021-03-30
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 = {NULL,
104: NULL,
105: NULL,
106: MatMult_Scatter,
107: /* 4*/ MatMultAdd_Scatter,
108: MatMultTranspose_Scatter,
109: MatMultTransposeAdd_Scatter,
110: NULL,
111: NULL,
112: NULL,
113: /* 10*/ NULL,
114: NULL,
115: NULL,
116: NULL,
117: NULL,
118: /* 15*/ NULL,
119: NULL,
120: NULL,
121: NULL,
122: NULL,
123: /* 20*/ NULL,
124: NULL,
125: NULL,
126: NULL,
127: /* 24*/ NULL,
128: NULL,
129: NULL,
130: NULL,
131: NULL,
132: /* 29*/ NULL,
133: NULL,
134: NULL,
135: NULL,
136: NULL,
137: /* 34*/ NULL,
138: NULL,
139: NULL,
140: NULL,
141: NULL,
142: /* 39*/ NULL,
143: NULL,
144: NULL,
145: NULL,
146: NULL,
147: /* 44*/ NULL,
148: NULL,
149: MatShift_Basic,
150: NULL,
151: NULL,
152: /* 49*/ NULL,
153: NULL,
154: NULL,
155: NULL,
156: NULL,
157: /* 54*/ NULL,
158: NULL,
159: NULL,
160: NULL,
161: NULL,
162: /* 59*/ NULL,
163: MatDestroy_Scatter,
164: NULL,
165: NULL,
166: NULL,
167: /* 64*/ NULL,
168: NULL,
169: NULL,
170: NULL,
171: NULL,
172: /* 69*/ NULL,
173: NULL,
174: NULL,
175: NULL,
176: NULL,
177: /* 74*/ NULL,
178: NULL,
179: NULL,
180: NULL,
181: NULL,
182: /* 79*/ NULL,
183: NULL,
184: NULL,
185: NULL,
186: NULL,
187: /* 84*/ NULL,
188: NULL,
189: NULL,
190: NULL,
191: NULL,
192: /* 89*/ NULL,
193: NULL,
194: NULL,
195: NULL,
196: NULL,
197: /* 94*/ NULL,
198: NULL,
199: NULL,
200: NULL,
201: NULL,
202: /*99*/ NULL,
203: NULL,
204: NULL,
205: NULL,
206: NULL,
207: /*104*/ NULL,
208: NULL,
209: NULL,
210: NULL,
211: NULL,
212: /*109*/ NULL,
213: NULL,
214: NULL,
215: NULL,
216: NULL,
217: /*114*/ NULL,
218: NULL,
219: NULL,
220: NULL,
221: NULL,
222: /*119*/ NULL,
223: NULL,
224: NULL,
225: NULL,
226: NULL,
227: /*124*/ NULL,
228: NULL,
229: NULL,
230: NULL,
231: NULL,
232: /*129*/ NULL,
233: NULL,
234: NULL,
235: NULL,
236: NULL,
237: /*134*/ NULL,
238: NULL,
239: NULL,
240: NULL,
241: NULL,
242: /*139*/ NULL,
243: NULL,
244: NULL
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: }