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: NULL};
243: /*MC
244: MATSCATTER - "scatter" - A matrix type that simply applies a `VecScatterBegin()` and `VecScatterEnd()` to perform `MatMult()`
246: Level: advanced
248: .seealso: [](ch_matrices), `Mat`, `MATSCATTER`, MatCreateScatter()`, `MatScatterSetVecScatter()`, `MatScatterGetVecScatter()`
249: M*/
251: PETSC_EXTERN PetscErrorCode MatCreate_Scatter(Mat A)
252: {
253: Mat_Scatter *b;
255: PetscFunctionBegin;
256: A->ops[0] = MatOps_Values;
257: PetscCall(PetscNew(&b));
259: A->data = (void *)b;
261: PetscCall(PetscLayoutSetUp(A->rmap));
262: PetscCall(PetscLayoutSetUp(A->cmap));
264: A->assembled = PETSC_TRUE;
265: A->preallocated = PETSC_FALSE;
267: PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATSCATTER));
268: PetscFunctionReturn(PETSC_SUCCESS);
269: }
271: #include <petsc/private/sfimpl.h>
272: /*@
273: MatCreateScatter - Creates a new matrix of `MatType` `MATSCATTER`, based on a VecScatter
275: Collective
277: Input Parameters:
278: + comm - MPI communicator
279: - scatter - a `VecScatter`
281: Output Parameter:
282: . A - the matrix
284: Level: intermediate
286: Notes:
287: PETSc requires that matrices and vectors being used for certain
288: operations are partitioned accordingly. For example, when
289: creating a scatter matrix, A, that supports parallel matrix-vector
290: products using `MatMult`(A,x,y) the user should set the number
291: of local matrix rows to be the number of local elements of the
292: corresponding result vector, y. Note that this is information is
293: required for use of the matrix interface routines, even though
294: the scatter matrix may not actually be physically partitioned.
296: Developer Notes:
297: This directly accesses information inside the `VecScatter` associated with the matrix-vector product
298: for this matrix. This is not desirable..
300: .seealso: [](ch_matrices), `Mat`, `MatScatterSetVecScatter()`, `MatScatterGetVecScatter()`, `MATSCATTER`
301: @*/
302: PetscErrorCode MatCreateScatter(MPI_Comm comm, VecScatter scatter, Mat *A)
303: {
304: PetscFunctionBegin;
305: PetscCall(MatCreate(comm, A));
306: PetscCall(MatSetSizes(*A, scatter->vscat.to_n, scatter->vscat.from_n, PETSC_DETERMINE, PETSC_DETERMINE));
307: PetscCall(MatSetType(*A, MATSCATTER));
308: PetscCall(MatScatterSetVecScatter(*A, scatter));
309: PetscCall(MatSetUp(*A));
310: PetscFunctionReturn(PETSC_SUCCESS);
311: }
313: /*@
314: MatScatterSetVecScatter - sets the scatter that the matrix is to apply as its linear operator in a `MATSCATTER`
316: Logically Collective
318: Input Parameters:
319: + mat - the `MATSCATTER` matrix
320: - scatter - the scatter context create with `VecScatterCreate()`
322: Level: advanced
324: .seealso: [](ch_matrices), `Mat`, `MATSCATTER`, `MatCreateScatter()`
325: @*/
326: PetscErrorCode MatScatterSetVecScatter(Mat mat, VecScatter scatter)
327: {
328: Mat_Scatter *mscatter = (Mat_Scatter *)mat->data;
330: PetscFunctionBegin;
333: PetscCheckSameComm(scatter, 2, mat, 1);
334: 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);
335: 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);
337: PetscCall(PetscObjectReference((PetscObject)scatter));
338: PetscCall(VecScatterDestroy(&mscatter->scatter));
340: mscatter->scatter = scatter;
341: PetscFunctionReturn(PETSC_SUCCESS);
342: }