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