xref: /petsc/src/mat/impls/scatter/mscatter.c (revision 0d04baf89eca684847eb03c0d4ee6b8dfe3c620a)
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   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 = 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 
277 .keywords: matrix, scatter, create
278 
279 .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER
280 @*/
281 PetscErrorCode  MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A)
282 {
283   PetscErrorCode ierr;
284 
285   PetscFunctionBegin;
286   ierr = MatCreate(comm,A);CHKERRQ(ierr);
287   ierr = MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
288   ierr = MatSetType(*A,MATSCATTER);CHKERRQ(ierr);
289   ierr = MatScatterSetVecScatter(*A,scatter);CHKERRQ(ierr);
290   PetscFunctionReturn(0);
291 }
292 
293 #undef __FUNCT__
294 #define __FUNCT__ "MatScatterSetVecScatter"
295 /*@
296     MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator
297 
298    Collective on Mat
299 
300     Input Parameters:
301 +   mat - the scatter matrix
302 -   scatter - the scatter context create with VecScatterCreate()
303 
304    Level: advanced
305 
306 
307 .seealso: MatCreateScatter(), MATSCATTER
308 @*/
309 PetscErrorCode  MatScatterSetVecScatter(Mat mat,VecScatter scatter)
310 {
311   Mat_Scatter    *mscatter = (Mat_Scatter*)mat->data;
312   PetscErrorCode ierr;
313 
314   PetscFunctionBegin;
315   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
316   PetscValidHeaderSpecific(scatter,VEC_SCATTER_CLASSID,2);
317   PetscCheckSameComm((PetscObject)scatter,1,(PetscObject)mat,2);
318   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);
319   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);
320 
321   ierr = PetscObjectReference((PetscObject)scatter);CHKERRQ(ierr);
322   ierr = VecScatterDestroy(&mscatter->scatter);CHKERRQ(ierr);
323   mscatter->scatter = scatter;
324   PetscFunctionReturn(0);
325 }
326 
327 
328