xref: /petsc/src/mat/impls/scatter/mscatter.c (revision 2a6744eb01855f5aa328eb8fdf4b0d01e72ad151)
1 #define PETSCMAT_DLL
2 
3 /*
4    This provides a matrix that applies a VecScatter to a vector.
5 */
6 
7 #include "src/mat/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 = VecScatterBegin(x,y,INSERT_VALUES,SCATTER_FORWARD,scatter->scatter);CHKERRQ(ierr);
68   ierr = VecScatterEnd(x,y,INSERT_VALUES,SCATTER_FORWARD,scatter->scatter);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(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
81   if (z != y) {ierr = VecCopy(y,z);CHKERRQ(ierr);}
82   ierr = VecScatterBegin(x,z,ADD_VALUES,SCATTER_FORWARD,scatter->scatter);CHKERRQ(ierr);
83   ierr = VecScatterEnd(x,z,ADD_VALUES,SCATTER_FORWARD,scatter->scatter);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(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
96   ierr = VecScatterBegin(x,y,INSERT_VALUES,SCATTER_REVERSE,scatter->scatter);CHKERRQ(ierr);
97   ierr = VecScatterEnd(x,y,INSERT_VALUES,SCATTER_REVERSE,scatter->scatter);CHKERRQ(ierr);
98   PetscFunctionReturn(0);
99 }
100 
101 #undef __FUNCT__
102 #define __FUNCT__ "MatMultTransposeAdd_Scatter"
103 PetscErrorCode MatMultTransposeAdd_Scatter(Mat A,Vec x,Vec y,Vec z)
104 {
105   Mat_Scatter    *scatter = (Mat_Scatter*)A->data;
106   PetscErrorCode ierr;
107 
108   PetscFunctionBegin;
109   if (!scatter->scatter) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()");
110   if (z != y) {ierr = VecCopy(y,z);CHKERRQ(ierr);}
111   ierr = VecScatterBegin(x,z,ADD_VALUES,SCATTER_REVERSE,scatter->scatter);CHKERRQ(ierr);
112   ierr = VecScatterEnd(x,z,ADD_VALUES,SCATTER_REVERSE,scatter->scatter);CHKERRQ(ierr);
113   PetscFunctionReturn(0);
114 }
115 
116 static struct _MatOps MatOps_Values = {0,
117        0,
118        0,
119        MatMult_Scatter,
120 /* 4*/ MatMultAdd_Scatter,
121        MatMultTranspose_Scatter,
122        MatMultTransposeAdd_Scatter,
123        0,
124        0,
125        0,
126 /*10*/ 0,
127        0,
128        0,
129        0,
130        0,
131 /*15*/ 0,
132        0,
133        0,
134        0,
135        0,
136 /*20*/ 0,
137        0,
138        0,
139        0,
140        0,
141 /*25*/ 0,
142        0,
143        0,
144        0,
145        0,
146 /*30*/ 0,
147        0,
148        0,
149        0,
150        0,
151 /*35*/ 0,
152        0,
153        0,
154        0,
155        0,
156 /*40*/ 0,
157        0,
158        0,
159        0,
160        0,
161 /*45*/ 0,
162        0,
163        0,
164        0,
165        0,
166 /*50*/ 0,
167        0,
168        0,
169        0,
170        0,
171 /*55*/ 0,
172        0,
173        0,
174        0,
175        0,
176 /*60*/ 0,
177        MatDestroy_Scatter,
178        0,
179        0,
180        0,
181 /*65*/ 0,
182        0,
183        0,
184        0,
185        0,
186 /*70*/ 0,
187        0,
188        0,
189        0,
190        0,
191 /*75*/ 0,
192        0,
193        0,
194        0,
195        0,
196 /*80*/ 0,
197        0,
198        0,
199        0,
200        0,
201 /*85*/ 0,
202        0,
203        0,
204        0,
205        0,
206 /*90*/ 0,
207        0,
208        0,
209        0,
210        0,
211 /*95*/ 0,
212        0,
213        0,
214        0};
215 
216 /*MC
217    MATSCATTER - MATSCATTER = "scatter" - A matrix type to be used to define your own matrix type -- perhaps matrix free.
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 PETSCMAT_DLLEXPORT 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 = PetscNew(Mat_Scatter,&b);CHKERRQ(ierr);
236 
237   A->data = (void*)b;
238 
239   ierr = PetscMapInitialize(A->comm,&A->rmap);CHKERRQ(ierr);
240   ierr = PetscMapInitialize(A->comm,&A->cmap);CHKERRQ(ierr);
241 
242   A->assembled     = PETSC_TRUE;
243   A->preallocated  = PETSC_FALSE;
244   PetscFunctionReturn(0);
245 }
246 EXTERN_C_END
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    For example,
273 
274 .keywords: matrix, scatter, create
275 
276 .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER
277 @*/
278 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A)
279 {
280   PetscErrorCode ierr;
281 
282   PetscFunctionBegin;
283   ierr = MatCreate(comm,A);CHKERRQ(ierr);
284   ierr = MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
285   ierr = MatSetType(*A,MATSCATTER);CHKERRQ(ierr);
286   ierr = MatScatterSetVecScatter(*A,scatter);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 PETSCMAT_DLLEXPORT MatScatterSetVecScatter(Mat mat,VecScatter scatter)
307 {
308   Mat_Scatter    *mscatter = (Mat_Scatter*)mat->data;
309   PetscErrorCode ierr;
310 
311   PetscFunctionBegin;
312   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
313   PetscValidHeaderSpecific(scatter,VEC_SCATTER_COOKIE,2);
314   PetscCheckSameComm((PetscObject)scatter,(PetscObject)mat,1,2);
315   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);
316   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);
317 
318   if (mscatter->scatter) {ierr = VecScatterDestroy(mscatter->scatter);CHKERRQ(ierr);}
319   mscatter->scatter = scatter;
320   ierr = PetscObjectReference((PetscObject)scatter);CHKERRQ(ierr);
321   PetscFunctionReturn(0);
322 }
323 
324 
325