xref: /petsc/src/mat/impls/scatter/mscatter.c (revision 047240e14af00aad1ef65e96f6fface8924f7f7e)
1 
2 /*
3    This provides a matrix that applies a VecScatter to a vector.
4 */
5 
6 #include <petsc-private/matimpl.h>        /*I "petscmat.h" I*/
7 #include <petsc-private/vecimpl.h>
8 
9 typedef struct {
10   VecScatter scatter;
11 } Mat_Scatter;
12 
13 #undef __FUNCT__
14 #define __FUNCT__ "MatScatterGetVecScatter"
15 /*@
16     MatScatterGetVecScatter - Returns the user-provided scatter set with MatScatterSetVecScatter()
17 
18     Not Collective, but not cannot use scatter if not used collectively on Mat
19 
20     Input Parameter:
21 .   mat - the matrix, should have been created with MatCreateScatter() or have type MATSCATTER
22 
23     Output Parameter:
24 .   scatter - the scatter context
25 
26     Level: intermediate
27 
28 .keywords: matrix, scatter, get
29 
30 .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MATSCATTER
31 @*/
32 PetscErrorCode  MatScatterGetVecScatter(Mat mat,VecScatter *scatter)
33 {
34   Mat_Scatter *mscatter;
35 
36   PetscFunctionBegin;
37   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
38   PetscValidPointer(scatter,2);
39   mscatter = (Mat_Scatter*)mat->data;
40   *scatter = mscatter->scatter;
41   PetscFunctionReturn(0);
42 }
43 
44 #undef __FUNCT__
45 #define __FUNCT__ "MatDestroy_Scatter"
46 PetscErrorCode MatDestroy_Scatter(Mat mat)
47 {
48   PetscErrorCode ierr;
49   Mat_Scatter    *scatter = (Mat_Scatter*)mat->data;
50 
51   PetscFunctionBegin;
52   ierr = VecScatterDestroy(&scatter->scatter);CHKERRQ(ierr);
53   ierr = PetscFree(mat->data);CHKERRQ(ierr);
54   PetscFunctionReturn(0);
55 }
56 
57 #undef __FUNCT__
58 #define __FUNCT__ "MatMult_Scatter"
59 PetscErrorCode MatMult_Scatter(Mat A,Vec x,Vec y)
60 {
61   Mat_Scatter    *scatter = (Mat_Scatter*)A->data;
62   PetscErrorCode ierr;
63 
64   PetscFunctionBegin;
65   if (!scatter->scatter) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
66   ierr = VecZeroEntries(y);CHKERRQ(ierr);
67   ierr = VecScatterBegin(scatter->scatter,x,y,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
68   ierr = VecScatterEnd(scatter->scatter,x,y,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
69   PetscFunctionReturn(0);
70 }
71 
72 #undef __FUNCT__
73 #define __FUNCT__ "MatMultAdd_Scatter"
74 PetscErrorCode MatMultAdd_Scatter(Mat A,Vec x,Vec y,Vec z)
75 {
76   Mat_Scatter    *scatter = (Mat_Scatter*)A->data;
77   PetscErrorCode ierr;
78 
79   PetscFunctionBegin;
80   if (!scatter->scatter) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
81   if (z != y) {ierr = VecCopy(y,z);CHKERRQ(ierr);}
82   ierr = VecScatterBegin(scatter->scatter,x,z,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
83   ierr = VecScatterEnd(scatter->scatter,x,z,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
84   PetscFunctionReturn(0);
85 }
86 
87 #undef __FUNCT__
88 #define __FUNCT__ "MatMultTranspose_Scatter"
89 PetscErrorCode MatMultTranspose_Scatter(Mat A,Vec x,Vec y)
90 {
91   Mat_Scatter    *scatter = (Mat_Scatter*)A->data;
92   PetscErrorCode ierr;
93 
94   PetscFunctionBegin;
95   if (!scatter->scatter) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
96   ierr = VecZeroEntries(y);CHKERRQ(ierr);
97   ierr = VecScatterBegin(scatter->scatter,x,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
98   ierr = VecScatterEnd(scatter->scatter,x,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
99   PetscFunctionReturn(0);
100 }
101 
102 #undef __FUNCT__
103 #define __FUNCT__ "MatMultTransposeAdd_Scatter"
104 PetscErrorCode MatMultTransposeAdd_Scatter(Mat A,Vec x,Vec y,Vec z)
105 {
106   Mat_Scatter    *scatter = (Mat_Scatter*)A->data;
107   PetscErrorCode ierr;
108 
109   PetscFunctionBegin;
110   if (!scatter->scatter) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
111   if (z != y) {ierr = VecCopy(y,z);CHKERRQ(ierr);}
112   ierr = VecScatterBegin(scatter->scatter,x,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
113   ierr = VecScatterEnd(scatter->scatter,x,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
114   PetscFunctionReturn(0);
115 }
116 
117 static struct _MatOps MatOps_Values = {0,
118         0,
119         0,
120         MatMult_Scatter,
121 /*  4*/ MatMultAdd_Scatter,
122         MatMultTranspose_Scatter,
123         MatMultTransposeAdd_Scatter,
124         0,
125         0,
126         0,
127 /* 10*/ 0,
128         0,
129         0,
130         0,
131         0,
132 /* 15*/ 0,
133         0,
134         0,
135         0,
136         0,
137 /* 20*/ 0,
138         0,
139         0,
140         0,
141 /* 24*/ 0,
142         0,
143         0,
144         0,
145         0,
146 /* 29*/ 0,
147         0,
148         0,
149         0,
150         0,
151 /* 34*/ 0,
152         0,
153         0,
154         0,
155         0,
156 /* 39*/ 0,
157         0,
158         0,
159         0,
160         0,
161 /* 44*/ 0,
162         0,
163         0,
164         0,
165         0,
166 /* 49*/ 0,
167         0,
168         0,
169         0,
170         0,
171 /* 54*/ 0,
172         0,
173         0,
174         0,
175         0,
176 /* 59*/ 0,
177         MatDestroy_Scatter,
178         0,
179         0,
180         0,
181 /* 64*/ 0,
182         0,
183         0,
184         0,
185         0,
186 /* 69*/ 0,
187         0,
188         0,
189         0,
190         0,
191 /* 74*/ 0,
192         0,
193         0,
194         0,
195         0,
196 /* 79*/ 0,
197         0,
198         0,
199         0,
200         0,
201 /* 84*/ 0,
202         0,
203         0,
204         0,
205         0,
206 /* 89*/ 0,
207         0,
208         0,
209         0,
210         0,
211 /* 94*/ 0,
212         0,
213         0,
214         0};
215 
216 /*MC
217    MATSCATTER - MATSCATTER = "scatter" - A matrix type that simply applies a VecScatterBegin/End()
218 
219   Level: advanced
220 
221 .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MatScatterGetVecScatter()
222 
223 M*/
224 
225 EXTERN_C_BEGIN
226 #undef __FUNCT__
227 #define __FUNCT__ "MatCreate_Scatter"
228 PetscErrorCode  MatCreate_Scatter(Mat A)
229 {
230   Mat_Scatter    *b;
231   PetscErrorCode ierr;
232 
233   PetscFunctionBegin;
234   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
235   ierr = PetscNewLog(A,Mat_Scatter,&b);CHKERRQ(ierr);
236 
237   A->data = (void*)b;
238 
239   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
240   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
241 
242   A->assembled    = PETSC_TRUE;
243   A->preallocated = PETSC_FALSE;
244 
245   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSCATTER);CHKERRQ(ierr);
246   PetscFunctionReturn(0);
247 }
248 EXTERN_C_END
249 
250 #undef __FUNCT__
251 #define __FUNCT__ "MatCreateScatter"
252 /*@C
253    MatCreateScatter - Creates a new matrix based on a VecScatter
254 
255   Collective on MPI_Comm
256 
257    Input Parameters:
258 +  comm - MPI communicator
259 -  scatter - a VecScatterContext
260 
261    Output Parameter:
262 .  A - the matrix
263 
264    Level: intermediate
265 
266    PETSc requires that matrices and vectors being used for certain
267    operations are partitioned accordingly.  For example, when
268    creating a scatter matrix, A, that supports parallel matrix-vector
269    products using MatMult(A,x,y) the user should set the number
270    of local matrix rows to be the number of local elements of the
271    corresponding result vector, y. Note that this is information is
272    required for use of the matrix interface routines, even though
273    the scatter matrix may not actually be physically partitioned.
274 
275 .keywords: matrix, scatter, create
276 
277 .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER
278 @*/
279 PetscErrorCode  MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A)
280 {
281   PetscErrorCode ierr;
282 
283   PetscFunctionBegin;
284   ierr = MatCreate(comm,A);CHKERRQ(ierr);
285   ierr = MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
286   ierr = MatSetType(*A,MATSCATTER);CHKERRQ(ierr);
287   ierr = MatScatterSetVecScatter(*A,scatter);CHKERRQ(ierr);
288   ierr = MatSetUp(*A);CHKERRQ(ierr);
289   PetscFunctionReturn(0);
290 }
291 
292 #undef __FUNCT__
293 #define __FUNCT__ "MatScatterSetVecScatter"
294 /*@
295     MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator
296 
297    Collective on Mat
298 
299     Input Parameters:
300 +   mat - the scatter matrix
301 -   scatter - the scatter context create with VecScatterCreate()
302 
303    Level: advanced
304 
305 
306 .seealso: MatCreateScatter(), MATSCATTER
307 @*/
308 PetscErrorCode  MatScatterSetVecScatter(Mat mat,VecScatter scatter)
309 {
310   Mat_Scatter    *mscatter = (Mat_Scatter*)mat->data;
311   PetscErrorCode ierr;
312 
313   PetscFunctionBegin;
314   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
315   PetscValidHeaderSpecific(scatter,VEC_SCATTER_CLASSID,2);
316   PetscCheckSameComm((PetscObject)scatter,1,(PetscObject)mat,2);
317   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);
318   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);
319 
320   ierr = PetscObjectReference((PetscObject)scatter);CHKERRQ(ierr);
321   ierr = VecScatterDestroy(&mscatter->scatter);CHKERRQ(ierr);
322 
323   mscatter->scatter = scatter;
324   PetscFunctionReturn(0);
325 }
326 
327 
328