xref: /petsc/src/mat/impls/scatter/mscatter.c (revision dc0b31ed242eb6637dca0468fbfa12899dc55c4b)
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_COOKIE,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(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(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(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(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        0,
143 /*25*/ 0,
144        0,
145        0,
146        0,
147        0,
148 /*30*/ 0,
149        0,
150        0,
151        0,
152        0,
153 /*35*/ 0,
154        0,
155        0,
156        0,
157        0,
158 /*40*/ 0,
159        0,
160        0,
161        0,
162        0,
163 /*45*/ 0,
164        0,
165        0,
166        0,
167        0,
168 /*50*/ 0,
169        0,
170        0,
171        0,
172        0,
173 /*55*/ 0,
174        0,
175        0,
176        0,
177        0,
178 /*60*/ 0,
179        MatDestroy_Scatter,
180        0,
181        0,
182        0,
183 /*65*/ 0,
184        0,
185        0,
186        0,
187        0,
188 /*70*/ 0,
189        0,
190        0,
191        0,
192        0,
193 /*75*/ 0,
194        0,
195        0,
196        0,
197        0,
198 /*80*/ 0,
199        0,
200        0,
201        0,
202        0,
203 /*85*/ 0,
204        0,
205        0,
206        0,
207        0,
208 /*90*/ 0,
209        0,
210        0,
211        0,
212        0,
213 /*95*/ 0,
214        0,
215        0,
216        0};
217 
218 /*MC
219    MATSCATTER - MATSCATTER = "scatter" - A matrix type that simply applies a VecScatterBegin/End()
220 
221   Level: advanced
222 
223 .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MatScatterGetVecScatter()
224 
225 M*/
226 
227 EXTERN_C_BEGIN
228 #undef __FUNCT__
229 #define __FUNCT__ "MatCreate_Scatter"
230 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_Scatter(Mat A)
231 {
232   Mat_Scatter    *b;
233   PetscErrorCode ierr;
234 
235   PetscFunctionBegin;
236   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
237   ierr = PetscNewLog(A,Mat_Scatter,&b);CHKERRQ(ierr);
238 
239   A->data = (void*)b;
240 
241   ierr = PetscMapSetBlockSize(A->rmap,1);CHKERRQ(ierr);
242   ierr = PetscMapSetBlockSize(A->cmap,1);CHKERRQ(ierr);
243   ierr = PetscMapSetUp(A->rmap);CHKERRQ(ierr);
244   ierr = PetscMapSetUp(A->cmap);CHKERRQ(ierr);
245 
246   A->assembled     = PETSC_TRUE;
247   A->preallocated  = PETSC_FALSE;
248 
249   ierr = PetscObjectChangeTypeName((PetscObject)A,MATSCATTER);CHKERRQ(ierr);
250   PetscFunctionReturn(0);
251 }
252 EXTERN_C_END
253 
254 #undef __FUNCT__
255 #define __FUNCT__ "MatCreateScatter"
256 /*@C
257    MatCreateScatter - Creates a new matrix based on a VecScatter
258 
259   Collective on MPI_Comm
260 
261    Input Parameters:
262 +  comm - MPI communicator
263 -  scatter - a VecScatterContext
264 
265    Output Parameter:
266 .  A - the matrix
267 
268    Level: intermediate
269 
270    PETSc requires that matrices and vectors being used for certain
271    operations are partitioned accordingly.  For example, when
272    creating a scatter matrix, A, that supports parallel matrix-vector
273    products using MatMult(A,x,y) the user should set the number
274    of local matrix rows to be the number of local elements of the
275    corresponding result vector, y. Note that this is information is
276    required for use of the matrix interface routines, even though
277    the scatter matrix may not actually be physically partitioned.
278    For example,
279 
280 .keywords: matrix, scatter, create
281 
282 .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER
283 @*/
284 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A)
285 {
286   PetscErrorCode ierr;
287 
288   PetscFunctionBegin;
289   ierr = MatCreate(comm,A);CHKERRQ(ierr);
290   ierr = MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
291   ierr = MatSetType(*A,MATSCATTER);CHKERRQ(ierr);
292   ierr = MatScatterSetVecScatter(*A,scatter);CHKERRQ(ierr);
293   PetscFunctionReturn(0);
294 }
295 
296 #undef __FUNCT__
297 #define __FUNCT__ "MatScatterSetVecScatter"
298 /*@
299     MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator
300 
301    Collective on Mat
302 
303     Input Parameters:
304 +   mat - the scatter matrix
305 -   scatter - the scatter context create with VecScatterCreate()
306 
307    Level: advanced
308 
309 
310 .seealso: MatCreateScatter(), MATSCATTER
311 @*/
312 PetscErrorCode PETSCMAT_DLLEXPORT MatScatterSetVecScatter(Mat mat,VecScatter scatter)
313 {
314   Mat_Scatter    *mscatter = (Mat_Scatter*)mat->data;
315   PetscErrorCode ierr;
316 
317   PetscFunctionBegin;
318   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
319   PetscValidHeaderSpecific(scatter,VEC_SCATTER_COOKIE,2);
320   PetscCheckSameComm((PetscObject)scatter,1,(PetscObject)mat,2);
321   if (mat->rmap->n != scatter->to_n) SETERRQ2(PETSC_ERR_ARG_SIZ,"Number of local rows in matrix %D not equal local scatter size %D",mat->rmap->n,scatter->to_n);
322   if (mat->cmap->n != scatter->from_n) SETERRQ2(PETSC_ERR_ARG_SIZ,"Number of local columns in matrix %D not equal local scatter size %D",mat->cmap->n,scatter->from_n);
323 
324   ierr = PetscObjectReference((PetscObject)scatter);CHKERRQ(ierr);
325   if (mscatter->scatter) {ierr = VecScatterDestroy(mscatter->scatter);CHKERRQ(ierr);}
326   mscatter->scatter = scatter;
327   PetscFunctionReturn(0);
328 }
329 
330 
331