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