Actual source code: mscatter.c
1: /*
2: This provides a matrix that applies a VecScatter to a vector.
3: */
5: #include <petsc/private/matimpl.h>
6: #include <petsc/private/vecimpl.h>
8: typedef struct {
9: VecScatter scatter;
10: } Mat_Scatter;
12: /*@
13: MatScatterGetVecScatter - Returns the user-provided scatter set with `MatScatterSetVecScatter()` in a `MATSCATTER` matrix
15: Logically Collective
17: Input Parameter:
18: . mat - the matrix, should have been created with MatCreateScatter() or have type `MATSCATTER`
20: Output Parameter:
21: . scatter - the scatter context
23: Level: intermediate
25: .seealso: [](ch_matrices), `Mat`, `MATSCATTER`, `MatCreateScatter()`, `MatScatterSetVecScatter()`
26: @*/
27: PetscErrorCode MatScatterGetVecScatter(Mat mat, VecScatter *scatter)
28: {
29: Mat_Scatter *mscatter;
31: PetscFunctionBegin;
33: PetscAssertPointer(scatter, 2);
34: mscatter = (Mat_Scatter *)mat->data;
35: *scatter = mscatter->scatter;
36: PetscFunctionReturn(PETSC_SUCCESS);
37: }
39: static PetscErrorCode MatDestroy_Scatter(Mat mat)
40: {
41: Mat_Scatter *scatter = (Mat_Scatter *)mat->data;
43: PetscFunctionBegin;
44: PetscCall(VecScatterDestroy(&scatter->scatter));
45: PetscCall(PetscFree(mat->data));
46: PetscFunctionReturn(PETSC_SUCCESS);
47: }
49: static PetscErrorCode MatMult_Scatter(Mat A, Vec x, Vec y)
50: {
51: Mat_Scatter *scatter = (Mat_Scatter *)A->data;
53: PetscFunctionBegin;
54: PetscCheck(scatter->scatter, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Need to first call MatScatterSetScatter()");
55: PetscCall(VecZeroEntries(y));
56: PetscCall(VecScatterBegin(scatter->scatter, x, y, ADD_VALUES, SCATTER_FORWARD));
57: PetscCall(VecScatterEnd(scatter->scatter, x, y, ADD_VALUES, SCATTER_FORWARD));
58: PetscFunctionReturn(PETSC_SUCCESS);
59: }
61: static PetscErrorCode MatMultAdd_Scatter(Mat A, Vec x, Vec y, Vec z)
62: {
63: Mat_Scatter *scatter = (Mat_Scatter *)A->data;
65: PetscFunctionBegin;
66: PetscCheck(scatter->scatter, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Need to first call MatScatterSetScatter()");
67: if (z != y) PetscCall(VecCopy(y, z));
68: PetscCall(VecScatterBegin(scatter->scatter, x, z, ADD_VALUES, SCATTER_FORWARD));
69: PetscCall(VecScatterEnd(scatter->scatter, x, z, ADD_VALUES, SCATTER_FORWARD));
70: PetscFunctionReturn(PETSC_SUCCESS);
71: }
73: static PetscErrorCode MatMultTranspose_Scatter(Mat A, Vec x, Vec y)
74: {
75: Mat_Scatter *scatter = (Mat_Scatter *)A->data;
77: PetscFunctionBegin;
78: PetscCheck(scatter->scatter, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Need to first call MatScatterSetScatter()");
79: PetscCall(VecZeroEntries(y));
80: PetscCall(VecScatterBegin(scatter->scatter, x, y, ADD_VALUES, SCATTER_REVERSE));
81: PetscCall(VecScatterEnd(scatter->scatter, x, y, ADD_VALUES, SCATTER_REVERSE));
82: PetscFunctionReturn(PETSC_SUCCESS);
83: }
85: static PetscErrorCode MatMultTransposeAdd_Scatter(Mat A, Vec x, Vec y, Vec z)
86: {
87: Mat_Scatter *scatter = (Mat_Scatter *)A->data;
89: PetscFunctionBegin;
90: PetscCheck(scatter->scatter, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Need to first call MatScatterSetScatter()");
91: if (z != y) PetscCall(VecCopy(y, z));
92: PetscCall(VecScatterBegin(scatter->scatter, x, z, ADD_VALUES, SCATTER_REVERSE));
93: PetscCall(VecScatterEnd(scatter->scatter, x, z, ADD_VALUES, SCATTER_REVERSE));
94: PetscFunctionReturn(PETSC_SUCCESS);
95: }
97: static struct _MatOps MatOps_Values = {NULL,
98: NULL,
99: NULL,
100: MatMult_Scatter,
101: /* 4*/ MatMultAdd_Scatter,
102: MatMultTranspose_Scatter,
103: MatMultTransposeAdd_Scatter,
104: NULL,
105: NULL,
106: NULL,
107: /* 10*/ NULL,
108: NULL,
109: NULL,
110: NULL,
111: NULL,
112: /* 15*/ NULL,
113: NULL,
114: NULL,
115: NULL,
116: NULL,
117: /* 20*/ NULL,
118: NULL,
119: NULL,
120: NULL,
121: /* 24*/ NULL,
122: NULL,
123: NULL,
124: NULL,
125: NULL,
126: /* 29*/ NULL,
127: NULL,
128: NULL,
129: NULL,
130: NULL,
131: /* 34*/ NULL,
132: NULL,
133: NULL,
134: NULL,
135: NULL,
136: /* 39*/ NULL,
137: NULL,
138: NULL,
139: NULL,
140: NULL,
141: /* 44*/ NULL,
142: NULL,
143: MatShift_Basic,
144: NULL,
145: NULL,
146: /* 49*/ NULL,
147: NULL,
148: NULL,
149: NULL,
150: NULL,
151: /* 54*/ NULL,
152: NULL,
153: NULL,
154: NULL,
155: NULL,
156: /* 59*/ NULL,
157: MatDestroy_Scatter,
158: NULL,
159: NULL,
160: NULL,
161: /* 64*/ NULL,
162: NULL,
163: NULL,
164: NULL,
165: NULL,
166: /* 69*/ NULL,
167: NULL,
168: NULL,
169: NULL,
170: NULL,
171: /* 74*/ NULL,
172: NULL,
173: NULL,
174: NULL,
175: NULL,
176: /* 79*/ NULL,
177: NULL,
178: NULL,
179: NULL,
180: NULL,
181: /* 84*/ NULL,
182: NULL,
183: NULL,
184: NULL,
185: NULL,
186: /* 89*/ NULL,
187: NULL,
188: NULL,
189: NULL,
190: NULL,
191: /* 94*/ NULL,
192: NULL,
193: NULL,
194: NULL,
195: NULL,
196: /*99*/ NULL,
197: NULL,
198: NULL,
199: NULL,
200: NULL,
201: /*104*/ NULL,
202: NULL,
203: NULL,
204: NULL,
205: NULL,
206: /*109*/ NULL,
207: NULL,
208: NULL,
209: NULL,
210: NULL,
211: /*114*/ NULL,
212: NULL,
213: NULL,
214: NULL,
215: NULL,
216: /*119*/ NULL,
217: NULL,
218: NULL,
219: NULL,
220: NULL,
221: /*124*/ NULL,
222: NULL,
223: NULL,
224: NULL,
225: NULL,
226: /*129*/ NULL,
227: NULL,
228: NULL,
229: NULL,
230: NULL,
231: /*134*/ NULL,
232: NULL,
233: NULL,
234: NULL,
235: NULL,
236: /*139*/ NULL,
237: NULL,
238: NULL,
239: NULL,
240: NULL,
241: /*144*/ NULL,
242: NULL,
243: NULL,
244: NULL,
245: NULL,
246: NULL,
247: /*150*/ NULL,
248: NULL,
249: NULL};
251: /*MC
252: MATSCATTER - "scatter" - A matrix type that simply applies a `VecScatterBegin()` and `VecScatterEnd()` to perform `MatMult()`
254: Level: advanced
256: .seealso: [](ch_matrices), `Mat`, `MATSCATTER`, MatCreateScatter()`, `MatScatterSetVecScatter()`, `MatScatterGetVecScatter()`
257: M*/
259: PETSC_EXTERN PetscErrorCode MatCreate_Scatter(Mat A)
260: {
261: Mat_Scatter *b;
263: PetscFunctionBegin;
264: A->ops[0] = MatOps_Values;
265: PetscCall(PetscNew(&b));
267: A->data = (void *)b;
269: PetscCall(PetscLayoutSetUp(A->rmap));
270: PetscCall(PetscLayoutSetUp(A->cmap));
272: A->assembled = PETSC_TRUE;
273: A->preallocated = PETSC_FALSE;
275: PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATSCATTER));
276: PetscFunctionReturn(PETSC_SUCCESS);
277: }
279: #include <petsc/private/sfimpl.h>
280: /*@C
281: MatCreateScatter - Creates a new matrix of `MatType` `MATSCATTER`, based on a VecScatter
283: Collective
285: Input Parameters:
286: + comm - MPI communicator
287: - scatter - a `VecScatter`
289: Output Parameter:
290: . A - the matrix
292: Level: intermediate
294: Notes:
295: PETSc requires that matrices and vectors being used for certain
296: operations are partitioned accordingly. For example, when
297: creating a scatter matrix, A, that supports parallel matrix-vector
298: products using `MatMult`(A,x,y) the user should set the number
299: of local matrix rows to be the number of local elements of the
300: corresponding result vector, y. Note that this is information is
301: required for use of the matrix interface routines, even though
302: the scatter matrix may not actually be physically partitioned.
304: Developer Notes:
305: This directly accesses information inside the `VecScatter` associated with the matrix-vector product
306: for this matrix. This is not desirable..
308: .seealso: [](ch_matrices), `Mat`, `MatScatterSetVecScatter()`, `MatScatterGetVecScatter()`, `MATSCATTER`
309: @*/
310: PetscErrorCode MatCreateScatter(MPI_Comm comm, VecScatter scatter, Mat *A)
311: {
312: PetscFunctionBegin;
313: PetscCall(MatCreate(comm, A));
314: PetscCall(MatSetSizes(*A, scatter->vscat.to_n, scatter->vscat.from_n, PETSC_DETERMINE, PETSC_DETERMINE));
315: PetscCall(MatSetType(*A, MATSCATTER));
316: PetscCall(MatScatterSetVecScatter(*A, scatter));
317: PetscCall(MatSetUp(*A));
318: PetscFunctionReturn(PETSC_SUCCESS);
319: }
321: /*@
322: MatScatterSetVecScatter - sets the scatter that the matrix is to apply as its linear operator in a `MATSCATTER`
324: Logically Collective
326: Input Parameters:
327: + mat - the `MATSCATTER` matrix
328: - scatter - the scatter context create with `VecScatterCreate()`
330: Level: advanced
332: .seealso: [](ch_matrices), `Mat`, `MATSCATTER`, `MatCreateScatter()`
333: @*/
334: PetscErrorCode MatScatterSetVecScatter(Mat mat, VecScatter scatter)
335: {
336: Mat_Scatter *mscatter = (Mat_Scatter *)mat->data;
338: PetscFunctionBegin;
341: PetscCheckSameComm((PetscObject)scatter, 2, (PetscObject)mat, 1);
342: PetscCheck(mat->rmap->n == scatter->vscat.to_n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local rows in matrix %" PetscInt_FMT " not equal local scatter size %" PetscInt_FMT, mat->rmap->n, scatter->vscat.to_n);
343: PetscCheck(mat->cmap->n == scatter->vscat.from_n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local columns in matrix %" PetscInt_FMT " not equal local scatter size %" PetscInt_FMT, mat->cmap->n, scatter->vscat.from_n);
345: PetscCall(PetscObjectReference((PetscObject)scatter));
346: PetscCall(VecScatterDestroy(&mscatter->scatter));
348: mscatter->scatter = scatter;
349: PetscFunctionReturn(PETSC_SUCCESS);
350: }