xref: /petsc/src/mat/impls/is/matis.c (revision 8ee2e534e188dd1b8ca1bcd65428d4df7139f0a3)
1 #define PETSCMAT_DLL
2 
3 /*
4     Creates a matrix class for using the Neumann-Neumann type preconditioners.
5    This stores the matrices in globally unassembled form. Each processor
6    assembles only its local Neumann problem and the parallel matrix vector
7    product is handled "implicitly".
8 
9      We provide:
10          MatMult()
11 
12     Currently this allows for only one subdomain per processor.
13 
14 */
15 
16 #include "src/mat/impls/is/matis.h"      /*I "petscmat.h" I*/
17 
18 #undef __FUNCT__
19 #define __FUNCT__ "MatDestroy_IS"
20 PetscErrorCode MatDestroy_IS(Mat A)
21 {
22   PetscErrorCode ierr;
23   Mat_IS         *b = (Mat_IS*)A->data;
24 
25   PetscFunctionBegin;
26   if (b->A) {
27     ierr = MatDestroy(b->A);CHKERRQ(ierr);
28   }
29   if (b->ctx) {
30     ierr = VecScatterDestroy(b->ctx);CHKERRQ(ierr);
31   }
32   if (b->x) {
33     ierr = VecDestroy(b->x);CHKERRQ(ierr);
34   }
35   if (b->y) {
36     ierr = VecDestroy(b->y);CHKERRQ(ierr);
37   }
38   if (b->mapping) {
39     ierr = ISLocalToGlobalMappingDestroy(b->mapping);CHKERRQ(ierr);
40   }
41   ierr = PetscFree(b);CHKERRQ(ierr);
42   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
43   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C","",PETSC_NULL);CHKERRQ(ierr);
44   PetscFunctionReturn(0);
45 }
46 
47 #undef __FUNCT__
48 #define __FUNCT__ "MatMult_IS"
49 PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
50 {
51   PetscErrorCode ierr;
52   Mat_IS         *is = (Mat_IS*)A->data;
53   PetscScalar    zero = 0.0;
54 
55   PetscFunctionBegin;
56   /*  scatter the global vector x into the local work vector */
57   ierr = VecScatterBegin(x,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);CHKERRQ(ierr);
58   ierr = VecScatterEnd(x,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);CHKERRQ(ierr);
59 
60   /* multiply the local matrix */
61   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
62 
63   /* scatter product back into global memory */
64   ierr = VecSet(y,zero);CHKERRQ(ierr);
65   ierr = VecScatterBegin(is->y,y,ADD_VALUES,SCATTER_REVERSE,is->ctx);CHKERRQ(ierr);
66   ierr = VecScatterEnd(is->y,y,ADD_VALUES,SCATTER_REVERSE,is->ctx);CHKERRQ(ierr);
67 
68   PetscFunctionReturn(0);
69 }
70 
71 #undef __FUNCT__
72 #define __FUNCT__ "MatView_IS"
73 PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
74 {
75   Mat_IS         *a = (Mat_IS*)A->data;
76   PetscErrorCode ierr;
77   PetscViewer    sviewer;
78 
79   PetscFunctionBegin;
80   ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr);
81   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
82   ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr);
83   PetscFunctionReturn(0);
84 }
85 
86 #undef __FUNCT__
87 #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
88 PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping mapping)
89 {
90   PetscErrorCode ierr;
91   PetscInt       n;
92   Mat_IS         *is = (Mat_IS*)A->data;
93   IS             from,to;
94   Vec            global;
95 
96   PetscFunctionBegin;
97   is->mapping = mapping;
98   ierr = PetscObjectReference((PetscObject)mapping);CHKERRQ(ierr);
99 
100   /* Create the local matrix A */
101   ierr = ISLocalToGlobalMappingGetSize(mapping,&n);CHKERRQ(ierr);
102   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
103   ierr = MatSetSizes(is->A,n,n,n,n);CHKERRQ(ierr);
104   ierr = PetscObjectSetOptionsPrefix((PetscObject)is->A,"is");CHKERRQ(ierr);
105   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
106 
107   /* Create the local work vectors */
108   ierr = VecCreateSeq(PETSC_COMM_SELF,n,&is->x);CHKERRQ(ierr);
109   ierr = VecDuplicate(is->x,&is->y);CHKERRQ(ierr);
110 
111   /* setup the global to local scatter */
112   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&to);CHKERRQ(ierr);
113   ierr = ISLocalToGlobalMappingApplyIS(mapping,to,&from);CHKERRQ(ierr);
114   ierr = VecCreateMPI(A->comm,A->cmap.n,A->cmap.N,&global);CHKERRQ(ierr);
115   ierr = VecScatterCreate(global,from,is->x,to,&is->ctx);CHKERRQ(ierr);
116   ierr = VecDestroy(global);CHKERRQ(ierr);
117   ierr = ISDestroy(to);CHKERRQ(ierr);
118   ierr = ISDestroy(from);CHKERRQ(ierr);
119   PetscFunctionReturn(0);
120 }
121 
122 
123 #undef __FUNCT__
124 #define __FUNCT__ "MatSetValuesLocal_IS"
125 PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
126 {
127   PetscErrorCode ierr;
128   Mat_IS         *is = (Mat_IS*)A->data;
129 
130   PetscFunctionBegin;
131   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
132   PetscFunctionReturn(0);
133 }
134 
135 #undef __FUNCT__
136 #define __FUNCT__ "MatZeroRowsLocal_IS"
137 PetscErrorCode MatZeroRowsLocal_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag)
138 {
139   Mat_IS         *is = (Mat_IS*)A->data;
140   PetscErrorCode ierr;
141   PetscInt       i;
142   PetscScalar    *array;
143 
144   PetscFunctionBegin;
145   {
146     /*
147        Set up is->x as a "counting vector". This is in order to MatMult_IS
148        work properly in the interface nodes.
149     */
150     Vec         counter;
151     PetscScalar one=1.0, zero=0.0;
152     ierr = VecCreateMPI(A->comm,A->cmap.n,A->cmap.N,&counter);CHKERRQ(ierr);
153     ierr = VecSet(counter,zero);CHKERRQ(ierr);
154     ierr = VecSet(is->x,one);CHKERRQ(ierr);
155     ierr = VecScatterBegin(is->x,counter,ADD_VALUES,SCATTER_REVERSE,is->ctx);CHKERRQ(ierr);
156     ierr = VecScatterEnd  (is->x,counter,ADD_VALUES,SCATTER_REVERSE,is->ctx);CHKERRQ(ierr);
157     ierr = VecScatterBegin(counter,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);CHKERRQ(ierr);
158     ierr = VecScatterEnd  (counter,is->x,INSERT_VALUES,SCATTER_FORWARD,is->ctx);CHKERRQ(ierr);
159     ierr = VecDestroy(counter);CHKERRQ(ierr);
160   }
161   if (!n) {
162     is->pure_neumann = PETSC_TRUE;
163   } else {
164     is->pure_neumann = PETSC_FALSE;
165     ierr = VecGetArray(is->x,&array);CHKERRQ(ierr);
166     ierr = MatZeroRows(is->A,n,rows,diag);CHKERRQ(ierr);
167     for (i=0; i<n; i++) {
168       ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
169     }
170     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
171     ierr = MatAssemblyEnd  (is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
172     ierr = VecRestoreArray(is->x,&array);CHKERRQ(ierr);
173   }
174 
175   PetscFunctionReturn(0);
176 }
177 
178 #undef __FUNCT__
179 #define __FUNCT__ "MatAssemblyBegin_IS"
180 PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
181 {
182   Mat_IS         *is = (Mat_IS*)A->data;
183   PetscErrorCode ierr;
184 
185   PetscFunctionBegin;
186   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
187   PetscFunctionReturn(0);
188 }
189 
190 #undef __FUNCT__
191 #define __FUNCT__ "MatAssemblyEnd_IS"
192 PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
193 {
194   Mat_IS         *is = (Mat_IS*)A->data;
195   PetscErrorCode ierr;
196 
197   PetscFunctionBegin;
198   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
199   PetscFunctionReturn(0);
200 }
201 
202 EXTERN_C_BEGIN
203 #undef __FUNCT__
204 #define __FUNCT__ "MatISGetLocalMat_IS"
205 PetscErrorCode PETSCMAT_DLLEXPORT MatISGetLocalMat_IS(Mat mat,Mat *local)
206 {
207   Mat_IS *is = (Mat_IS *)mat->data;
208 
209   PetscFunctionBegin;
210   *local = is->A;
211   PetscFunctionReturn(0);
212 }
213 EXTERN_C_END
214 
215 #undef __FUNCT__
216 #define __FUNCT__ "MatISGetLocalMat"
217 /*@
218     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
219 
220   Input Parameter:
221 .  mat - the matrix
222 
223   Output Parameter:
224 .  local - the local matrix usually MATSEQAIJ
225 
226   Level: advanced
227 
228   Notes:
229     This can be called if you have precomputed the nonzero structure of the
230   matrix and want to provide it to the inner matrix object to improve the performance
231   of the MatSetValues() operation.
232 
233 .seealso: MATIS
234 @*/
235 PetscErrorCode PETSCMAT_DLLEXPORT MatISGetLocalMat(Mat mat,Mat *local)
236 {
237   PetscErrorCode ierr,(*f)(Mat,Mat *);
238 
239   PetscFunctionBegin;
240   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
241   PetscValidPointer(local,2);
242   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatISGetLocalMat_C",(void (**)(void))&f);CHKERRQ(ierr);
243   if (f) {
244     ierr = (*f)(mat,local);CHKERRQ(ierr);
245   } else {
246     local = 0;
247   }
248   PetscFunctionReturn(0);
249 }
250 
251 #undef __FUNCT__
252 #define __FUNCT__ "MatZeroEntries_IS"
253 PetscErrorCode MatZeroEntries_IS(Mat A)
254 {
255   Mat_IS         *a = (Mat_IS*)A->data;
256   PetscErrorCode ierr;
257 
258   PetscFunctionBegin;
259   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
260   PetscFunctionReturn(0);
261 }
262 
263 #undef __FUNCT__
264 #define __FUNCT__ "MatSetOption_IS"
265 PetscErrorCode MatSetOption_IS(Mat A,MatOption op)
266 {
267   Mat_IS         *a = (Mat_IS*)A->data;
268   PetscErrorCode ierr;
269 
270   PetscFunctionBegin;
271   ierr = MatSetOption(a->A,op);CHKERRQ(ierr);
272   PetscFunctionReturn(0);
273 }
274 
275 #undef __FUNCT__
276 #define __FUNCT__ "MatCreateIS"
277 /*@
278     MatCreateIS - Creates a "process" unassmembled matrix, it is assembled on each
279        process but not across processes.
280 
281    Input Parameters:
282 +     comm - MPI communicator that will share the matrix
283 .     m,n,M,N - local and/or global sizes of the the left and right vector used in matrix vector products
284 -     map - mapping that defines the global number for each local number
285 
286    Output Parameter:
287 .    A - the resulting matrix
288 
289    Level: advanced
290 
291    Notes: See MATIS for more details
292           m and n are NOT related to the size of the map
293 
294 .seealso: MATIS, MatSetLocalToGlobalMapping()
295 @*/
296 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateIS(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping map,Mat *A)
297 {
298   PetscErrorCode ierr;
299 
300   PetscFunctionBegin;
301   ierr = MatCreate(comm,A);CHKERRQ(ierr);
302   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
303   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
304   ierr = MatSetLocalToGlobalMapping(*A,map);CHKERRQ(ierr);
305   PetscFunctionReturn(0);
306 }
307 
308 /*MC
309    MATIS - MATIS = "is" - A matrix type to be used for using the Neumann-Neumann type preconditioners.
310    This stores the matrices in globally unassembled form. Each processor
311    assembles only its local Neumann problem and the parallel matrix vector
312    product is handled "implicitly".
313 
314    Operations Provided:
315 +  MatMult()
316 .  MatZeroEntries()
317 .  MatSetOption()
318 .  MatZeroRowsLocal()
319 .  MatSetValuesLocal()
320 -  MatSetLocalToGlobalMapping()
321 
322    Options Database Keys:
323 . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
324 
325    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
326 
327           You must call MatSetLocalToGlobalMapping() before using this matrix type.
328 
329           You can do matrix preallocation on the local matrix after you obtain it with
330           MatISGetLocalMat()
331 
332   Level: advanced
333 
334 .seealso: PC, MatISGetLocalMat(), MatSetLocalToGlobalMapping()
335 
336 M*/
337 
338 EXTERN_C_BEGIN
339 #undef __FUNCT__
340 #define __FUNCT__ "MatCreate_IS"
341 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_IS(Mat A)
342 {
343   PetscErrorCode ierr;
344   Mat_IS         *b;
345 
346   PetscFunctionBegin;
347   ierr                = PetscNew(Mat_IS,&b);CHKERRQ(ierr);
348   A->data             = (void*)b;
349   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
350   A->factor           = 0;
351   A->mapping          = 0;
352 
353   A->ops->mult                    = MatMult_IS;
354   A->ops->destroy                 = MatDestroy_IS;
355   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
356   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
357   A->ops->zerorowslocal           = MatZeroRowsLocal_IS;
358   A->ops->assemblybegin           = MatAssemblyBegin_IS;
359   A->ops->assemblyend             = MatAssemblyEnd_IS;
360   A->ops->view                    = MatView_IS;
361   A->ops->zeroentries             = MatZeroEntries_IS;
362   A->ops->setoption               = MatSetOption_IS;
363 
364   ierr = PetscMapInitialize(A->comm,&A->rmap);CHKERRQ(ierr);
365   ierr = PetscMapInitialize(A->comm,&A->cmap);CHKERRQ(ierr);
366 
367   b->A          = 0;
368   b->ctx        = 0;
369   b->x          = 0;
370   b->y          = 0;
371   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatISGetLocalMat_C","MatISGetLocalMat_IS",MatISGetLocalMat_IS);CHKERRQ(ierr);
372   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
373 
374   PetscFunctionReturn(0);
375 }
376 EXTERN_C_END
377 
378 
379 
380 
381 
382 
383 
384 
385 
386 
387 
388 
389 
390