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