xref: /petsc/src/mat/impls/scatter/mscatter.c (revision 7d0a6c19129e7069c8a40e210b34ed62989173db)
1 
2 /*
3    This provides a matrix that applies a VecScatter to a vector.
4 */
5 
6 #include "private/matimpl.h"        /*I "petscmat.h" I*/
7 #include "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   if (scatter->scatter) {ierr = VecScatterDestroy(scatter->scatter);CHKERRQ(ierr);}
53   ierr = PetscFree(scatter);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 = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr);
240   ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr);
241   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
242   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
243 
244   A->assembled     = PETSC_TRUE;
245   A->preallocated  = PETSC_FALSE;
246 
247   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSCATTER);CHKERRQ(ierr);
248   PetscFunctionReturn(0);
249 }
250 EXTERN_C_END
251 
252 #undef __FUNCT__
253 #define __FUNCT__ "MatCreateScatter"
254 /*@C
255    MatCreateScatter - Creates a new matrix based on a VecScatter
256 
257   Collective on MPI_Comm
258 
259    Input Parameters:
260 +  comm - MPI communicator
261 -  scatter - a VecScatterContext
262 
263    Output Parameter:
264 .  A - the matrix
265 
266    Level: intermediate
267 
268    PETSc requires that matrices and vectors being used for certain
269    operations are partitioned accordingly.  For example, when
270    creating a scatter matrix, A, that supports parallel matrix-vector
271    products using MatMult(A,x,y) the user should set the number
272    of local matrix rows to be the number of local elements of the
273    corresponding result vector, y. Note that this is information is
274    required for use of the matrix interface routines, even though
275    the scatter matrix may not actually be physically partitioned.
276    For example,
277 
278 .keywords: matrix, scatter, create
279 
280 .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER
281 @*/
282 PetscErrorCode  MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A)
283 {
284   PetscErrorCode ierr;
285 
286   PetscFunctionBegin;
287   ierr = MatCreate(comm,A);CHKERRQ(ierr);
288   ierr = MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
289   ierr = MatSetType(*A,MATSCATTER);CHKERRQ(ierr);
290   ierr = MatScatterSetVecScatter(*A,scatter);CHKERRQ(ierr);
291   PetscFunctionReturn(0);
292 }
293 
294 #undef __FUNCT__
295 #define __FUNCT__ "MatScatterSetVecScatter"
296 /*@
297     MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator
298 
299    Collective on Mat
300 
301     Input Parameters:
302 +   mat - the scatter matrix
303 -   scatter - the scatter context create with VecScatterCreate()
304 
305    Level: advanced
306 
307 
308 .seealso: MatCreateScatter(), MATSCATTER
309 @*/
310 PetscErrorCode  MatScatterSetVecScatter(Mat mat,VecScatter scatter)
311 {
312   Mat_Scatter    *mscatter = (Mat_Scatter*)mat->data;
313   PetscErrorCode ierr;
314 
315   PetscFunctionBegin;
316   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
317   PetscValidHeaderSpecific(scatter,VEC_SCATTER_CLASSID,2);
318   PetscCheckSameComm((PetscObject)scatter,1,(PetscObject)mat,2);
319   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);
320   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);
321 
322   ierr = PetscObjectReference((PetscObject)scatter);CHKERRQ(ierr);
323   if (mscatter->scatter) {ierr = VecScatterDestroy(mscatter->scatter);CHKERRQ(ierr);}
324   mscatter->scatter = scatter;
325   PetscFunctionReturn(0);
326 }
327 
328 
329