xref: /petsc/src/mat/impls/is/matis.c (revision a790c00499656cdc34e95ec8f15f35cf5f4cdcbb)
1 
2 /*
3     Creates a matrix class for using the Neumann-Neumann type preconditioners.
4    This stores the matrices in globally unassembled form. Each processor
5    assembles only its local Neumann problem and the parallel matrix vector
6    product is handled "implicitly".
7 
8      We provide:
9          MatMult()
10 
11     Currently this allows for only one subdomain per processor.
12 
13 */
14 
15 #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
16 
17 #undef __FUNCT__
18 #define __FUNCT__ "MatDestroy_IS"
19 PetscErrorCode MatDestroy_IS(Mat A)
20 {
21   PetscErrorCode ierr;
22   Mat_IS         *b = (Mat_IS*)A->data;
23 
24   PetscFunctionBegin;
25   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
26   ierr = VecScatterDestroy(&b->ctx);CHKERRQ(ierr);
27   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
28   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
29   ierr = ISLocalToGlobalMappingDestroy(&b->mapping);CHKERRQ(ierr);
30   ierr = PetscFree(A->data);CHKERRQ(ierr);
31   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
32   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C","",PETSC_NULL);CHKERRQ(ierr);
33   PetscFunctionReturn(0);
34 }
35 
36 #undef __FUNCT__
37 #define __FUNCT__ "MatMult_IS"
38 PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
39 {
40   PetscErrorCode ierr;
41   Mat_IS         *is = (Mat_IS*)A->data;
42   PetscScalar    zero = 0.0;
43 
44   PetscFunctionBegin;
45   /*  scatter the global vector x into the local work vector */
46   ierr = VecScatterBegin(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47   ierr = VecScatterEnd(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
48 
49   /* multiply the local matrix */
50   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
51 
52   /* scatter product back into global memory */
53   ierr = VecSet(y,zero);CHKERRQ(ierr);
54   ierr = VecScatterBegin(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
55   ierr = VecScatterEnd(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
56 
57   PetscFunctionReturn(0);
58 }
59 
60 #undef __FUNCT__
61 #define __FUNCT__ "MatMultAdd_IS"
62 static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
63 {
64   PetscErrorCode ierr;
65   Mat_IS         *is = (Mat_IS*)A->data;
66 
67   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
68   /*  scatter the global vector v1 into the local work vector */
69   ierr = VecScatterBegin(is->ctx,v1,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
70   ierr = VecScatterEnd  (is->ctx,v1,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
71   ierr = VecScatterBegin(is->ctx,v2,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
72   ierr = VecScatterEnd  (is->ctx,v2,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
73 
74   /* multiply the local matrix */
75   ierr = MatMultAdd(is->A,is->x,is->y,is->y);CHKERRQ(ierr);
76 
77   /* scatter result back into global vector */
78   ierr = VecSet(v3,0);CHKERRQ(ierr);
79   ierr = VecScatterBegin(is->ctx,is->y,v3,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
80   ierr = VecScatterEnd  (is->ctx,is->y,v3,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
81   PetscFunctionReturn(0);
82 }
83 
84 #undef __FUNCT__
85 #define __FUNCT__ "MatMultTranspose_IS"
86 PetscErrorCode MatMultTranspose_IS(Mat A,Vec x,Vec y)
87 {
88   Mat_IS         *is = (Mat_IS*)A->data;
89   PetscErrorCode ierr;
90 
91   PetscFunctionBegin; /*  y = A' * x */
92   /*  scatter the global vector x into the local work vector */
93   ierr = VecScatterBegin(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
94   ierr = VecScatterEnd(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
95 
96   /* multiply the local matrix */
97   ierr = MatMultTranspose(is->A,is->x,is->y);CHKERRQ(ierr);
98 
99   /* scatter product back into global vector */
100   ierr = VecSet(y,0);CHKERRQ(ierr);
101   ierr = VecScatterBegin(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
102   ierr = VecScatterEnd(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
103   PetscFunctionReturn(0);
104 }
105 
106 #undef __FUNCT__
107 #define __FUNCT__ "MatMultTransposeAdd_IS"
108 PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
109 {
110   Mat_IS         *is = (Mat_IS*)A->data;
111   PetscErrorCode ierr;
112 
113   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
114   /*  scatter the global vectors v1 and v2  into the local work vectors */
115   ierr = VecScatterBegin(is->ctx,v1,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
116   ierr = VecScatterEnd  (is->ctx,v1,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
117   ierr = VecScatterBegin(is->ctx,v2,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
118   ierr = VecScatterEnd  (is->ctx,v2,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
119 
120   /* multiply the local matrix */
121   ierr = MatMultTransposeAdd(is->A,is->x,is->y,is->y);CHKERRQ(ierr);
122 
123   /* scatter result back into global vector */
124   ierr = VecSet(v3,0);CHKERRQ(ierr);
125   ierr = VecScatterBegin(is->ctx,is->y,v3,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
126   ierr = VecScatterEnd  (is->ctx,is->y,v3,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
127   PetscFunctionReturn(0);
128 }
129 
130 #undef __FUNCT__
131 #define __FUNCT__ "MatView_IS"
132 PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
133 {
134   Mat_IS         *a = (Mat_IS*)A->data;
135   PetscErrorCode ierr;
136   PetscViewer    sviewer;
137 
138   PetscFunctionBegin;
139   ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr);
140   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
141   ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr);
142   PetscFunctionReturn(0);
143 }
144 
145 #undef __FUNCT__
146 #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
147 PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
148 {
149   PetscErrorCode ierr;
150   PetscInt       n,bs;
151   Mat_IS         *is = (Mat_IS*)A->data;
152   IS             from,to;
153   Vec            global;
154 
155   PetscFunctionBegin;
156   if (is->mapping) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Mapping already set for matrix");
157   PetscCheckSameComm(A,1,rmapping,2);
158   if (rmapping != cmapping) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_INCOMP,"MATIS requires the row and column mappings to be identical");
159   ierr = PetscObjectReference((PetscObject)rmapping);CHKERRQ(ierr);
160   ierr = ISLocalToGlobalMappingDestroy(&is->mapping);CHKERRQ(ierr);
161   is->mapping = rmapping;
162 
163   /* Create the local matrix A */
164   ierr = ISLocalToGlobalMappingGetSize(rmapping,&n);CHKERRQ(ierr);
165   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
166   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
167   ierr = MatSetSizes(is->A,n,n,n,n);CHKERRQ(ierr);
168   ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr);
169   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
170   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
171   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
172 
173   /* Create the local work vectors */
174   ierr = VecCreate(PETSC_COMM_SELF,&is->x);CHKERRQ(ierr);
175   ierr = VecSetBlockSize(is->x,bs);CHKERRQ(ierr);
176   ierr = VecSetSizes(is->x,n,n);CHKERRQ(ierr);
177   ierr = VecSetOptionsPrefix(is->x,((PetscObject)A)->prefix);CHKERRQ(ierr);
178   ierr = VecAppendOptionsPrefix(is->x,"is_");CHKERRQ(ierr);
179   ierr = VecSetFromOptions(is->x);CHKERRQ(ierr);
180   ierr = VecDuplicate(is->x,&is->y);CHKERRQ(ierr);
181 
182   /* setup the global to local scatter */
183   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&to);CHKERRQ(ierr);
184   ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
185   ierr = MatGetVecs(A,&global,PETSC_NULL);CHKERRQ(ierr);
186   ierr = VecScatterCreate(global,from,is->x,to,&is->ctx);CHKERRQ(ierr);
187   ierr = VecDestroy(&global);CHKERRQ(ierr);
188   ierr = ISDestroy(&to);CHKERRQ(ierr);
189   ierr = ISDestroy(&from);CHKERRQ(ierr);
190   PetscFunctionReturn(0);
191 }
192 
193 #define ISG2LMapApply(mapping,n,in,out) 0;\
194   if (!(mapping)->globals) {\
195    PetscErrorCode _ierr = ISGlobalToLocalMappingApply((mapping),IS_GTOLM_MASK,0,0,0,0);CHKERRQ(_ierr);\
196   }\
197   {\
198     PetscInt _i,*_globals = (mapping)->globals,_start = (mapping)->globalstart,_end = (mapping)->globalend;\
199     for (_i=0; _i<n; _i++) {\
200       if (in[_i] < 0)           out[_i] = in[_i];\
201       else if (in[_i] < _start) out[_i] = -1;\
202       else if (in[_i] > _end)   out[_i] = -1;\
203       else                      out[_i] = _globals[in[_i] - _start];\
204     }\
205   }
206 
207 #undef __FUNCT__
208 #define __FUNCT__ "MatSetValues_IS"
209 PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
210 {
211   Mat_IS         *is = (Mat_IS*)mat->data;
212   PetscInt       rows_l[2048],cols_l[2048];
213   PetscErrorCode ierr;
214 
215   PetscFunctionBegin;
216 #if defined(PETSC_USE_DEBUG)
217   if (m > 2048 || n > 2048) {
218     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= 2048: they are %D %D",m,n);
219   }
220 #endif
221   ierr = ISG2LMapApply(is->mapping,m,rows,rows_l);CHKERRQ(ierr);
222   ierr = ISG2LMapApply(is->mapping,n,cols,cols_l);CHKERRQ(ierr);
223   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
224   PetscFunctionReturn(0);
225 }
226 
227 #undef ISG2LMapSetUp
228 #undef ISG2LMapApply
229 
230 #undef __FUNCT__
231 #define __FUNCT__ "MatSetValuesLocal_IS"
232 PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
233 {
234   PetscErrorCode ierr;
235   Mat_IS         *is = (Mat_IS*)A->data;
236 
237   PetscFunctionBegin;
238   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
239   PetscFunctionReturn(0);
240 }
241 
242 #undef __FUNCT__
243 #define __FUNCT__ "MatZeroRows_IS"
244 PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
245 {
246   Mat_IS         *is = (Mat_IS*)A->data;
247   PetscInt       n_l=0, *rows_l = PETSC_NULL;
248   PetscErrorCode ierr;
249 
250   PetscFunctionBegin;
251   if (x && b) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"No support");
252   if (n) {
253     ierr = PetscMalloc(n*sizeof(PetscInt),&rows_l);CHKERRQ(ierr);
254     ierr = ISGlobalToLocalMappingApply(is->mapping,IS_GTOLM_DROP,n,rows,&n_l,rows_l);CHKERRQ(ierr);
255   }
256   ierr = MatZeroRowsLocal(A,n_l,rows_l,diag,x,b);CHKERRQ(ierr);
257   ierr = PetscFree(rows_l);CHKERRQ(ierr);
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "MatZeroRowsLocal_IS"
263 PetscErrorCode MatZeroRowsLocal_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
264 {
265   Mat_IS         *is = (Mat_IS*)A->data;
266   PetscErrorCode ierr;
267   PetscInt       i;
268   PetscScalar    *array;
269 
270   PetscFunctionBegin;
271   if (x && b) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"No support");
272   {
273     /*
274        Set up is->x as a "counting vector". This is in order to MatMult_IS
275        work properly in the interface nodes.
276     */
277     Vec         counter;
278     PetscScalar one=1.0, zero=0.0;
279     ierr = MatGetVecs(A,&counter,PETSC_NULL);CHKERRQ(ierr);
280     ierr = VecSet(counter,zero);CHKERRQ(ierr);
281     ierr = VecSet(is->x,one);CHKERRQ(ierr);
282     ierr = VecScatterBegin(is->ctx,is->x,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
283     ierr = VecScatterEnd  (is->ctx,is->x,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
284     ierr = VecScatterBegin(is->ctx,counter,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
285     ierr = VecScatterEnd  (is->ctx,counter,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
286     ierr = VecDestroy(&counter);CHKERRQ(ierr);
287   }
288   if (!n) {
289     is->pure_neumann = PETSC_TRUE;
290   } else {
291     is->pure_neumann = PETSC_FALSE;
292     ierr = VecGetArray(is->x,&array);CHKERRQ(ierr);
293     ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
294     for (i=0; i<n; i++) {
295       ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
296     }
297     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
298     ierr = MatAssemblyEnd  (is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
299     ierr = VecRestoreArray(is->x,&array);CHKERRQ(ierr);
300   }
301 
302   PetscFunctionReturn(0);
303 }
304 
305 #undef __FUNCT__
306 #define __FUNCT__ "MatAssemblyBegin_IS"
307 PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
308 {
309   Mat_IS         *is = (Mat_IS*)A->data;
310   PetscErrorCode ierr;
311 
312   PetscFunctionBegin;
313   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
314   PetscFunctionReturn(0);
315 }
316 
317 #undef __FUNCT__
318 #define __FUNCT__ "MatAssemblyEnd_IS"
319 PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
320 {
321   Mat_IS         *is = (Mat_IS*)A->data;
322   PetscErrorCode ierr;
323 
324   PetscFunctionBegin;
325   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
326   PetscFunctionReturn(0);
327 }
328 
329 EXTERN_C_BEGIN
330 #undef __FUNCT__
331 #define __FUNCT__ "MatISGetLocalMat_IS"
332 PetscErrorCode  MatISGetLocalMat_IS(Mat mat,Mat *local)
333 {
334   Mat_IS *is = (Mat_IS *)mat->data;
335 
336   PetscFunctionBegin;
337   *local = is->A;
338   PetscFunctionReturn(0);
339 }
340 EXTERN_C_END
341 
342 #undef __FUNCT__
343 #define __FUNCT__ "MatISGetLocalMat"
344 /*@
345     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
346 
347   Input Parameter:
348 .  mat - the matrix
349 
350   Output Parameter:
351 .  local - the local matrix usually MATSEQAIJ
352 
353   Level: advanced
354 
355   Notes:
356     This can be called if you have precomputed the nonzero structure of the
357   matrix and want to provide it to the inner matrix object to improve the performance
358   of the MatSetValues() operation.
359 
360 .seealso: MATIS
361 @*/
362 PetscErrorCode  MatISGetLocalMat(Mat mat,Mat *local)
363 {
364   PetscErrorCode ierr;
365 
366   PetscFunctionBegin;
367   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
368   PetscValidPointer(local,2);
369   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat *),(mat,local));CHKERRQ(ierr);
370   PetscFunctionReturn(0);
371 }
372 
373 EXTERN_C_BEGIN
374 #undef __FUNCT__
375 #define __FUNCT__ "MatISSetLocalMat_IS"
376 PetscErrorCode  MatISSetLocalMat_IS(Mat mat,Mat local)
377 {
378   Mat_IS *is = (Mat_IS *)mat->data;
379   PetscInt nrows,ncols,orows,ocols;
380   PetscErrorCode ierr;
381 
382   PetscFunctionBegin;
383   if(is->A) {
384     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
385     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
386     if(orows != nrows || ocols != ncols ) {
387       SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %dx%d (you passed a %dx%d matrix)\n",orows,ocols,nrows,ncols);
388     }
389   }
390   ierr = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
391   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
392   is->A = local;
393 
394   PetscFunctionReturn(0);
395 }
396 EXTERN_C_END
397 
398 #undef __FUNCT__
399 #define __FUNCT__ "MatISSetLocalMat"
400 /*@
401     MatISSetLocalMat - Set the local matrix stored inside a MATIS matrix.
402 
403   Input Parameter:
404 .  mat - the matrix
405 .  local - the local matrix usually MATSEQAIJ
406 
407   Output Parameter:
408 
409   Level: advanced
410 
411   Notes:
412     This can be called if you have precomputed the local matrix and
413   want to provide it to the matrix object MATIS.
414 
415 .seealso: MATIS
416 @*/
417 PetscErrorCode  MatISSetLocalMat(Mat mat,Mat local)
418 {
419   PetscErrorCode ierr;
420 
421   PetscFunctionBegin;
422   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
423   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
424   PetscFunctionReturn(0);
425 }
426 
427 #undef __FUNCT__
428 #define __FUNCT__ "MatZeroEntries_IS"
429 PetscErrorCode MatZeroEntries_IS(Mat A)
430 {
431   Mat_IS         *a = (Mat_IS*)A->data;
432   PetscErrorCode ierr;
433 
434   PetscFunctionBegin;
435   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
436   PetscFunctionReturn(0);
437 }
438 
439 #undef __FUNCT__
440 #define __FUNCT__ "MatScale_IS"
441 PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
442 {
443   Mat_IS         *is = (Mat_IS*)A->data;
444   PetscErrorCode ierr;
445 
446   PetscFunctionBegin;
447   ierr = MatScale(is->A,a);CHKERRQ(ierr);
448   PetscFunctionReturn(0);
449 }
450 
451 #undef __FUNCT__
452 #define __FUNCT__ "MatGetDiagonal_IS"
453 PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
454 {
455   Mat_IS         *is = (Mat_IS*)A->data;
456   PetscErrorCode ierr;
457 
458   PetscFunctionBegin;
459   /* get diagonal of the local matrix */
460   ierr = MatGetDiagonal(is->A,is->x);CHKERRQ(ierr);
461 
462   /* scatter diagonal back into global vector */
463   ierr = VecSet(v,0);CHKERRQ(ierr);
464   ierr = VecScatterBegin(is->ctx,is->x,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
465   ierr = VecScatterEnd  (is->ctx,is->x,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
466   PetscFunctionReturn(0);
467 }
468 
469 #undef __FUNCT__
470 #define __FUNCT__ "MatSetOption_IS"
471 PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool  flg)
472 {
473   Mat_IS         *a = (Mat_IS*)A->data;
474   PetscErrorCode ierr;
475 
476   PetscFunctionBegin;
477   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
478   PetscFunctionReturn(0);
479 }
480 
481 #undef __FUNCT__
482 #define __FUNCT__ "MatCreateIS"
483 /*@
484     MatCreateIS - Creates a "process" unassmembled matrix, it is assembled on each
485        process but not across processes.
486 
487    Input Parameters:
488 +     comm - MPI communicator that will share the matrix
489 .     bs - local and global block size of the matrix
490 .     m,n,M,N - local and/or global sizes of the the left and right vector used in matrix vector products
491 -     map - mapping that defines the global number for each local number
492 
493    Output Parameter:
494 .    A - the resulting matrix
495 
496    Level: advanced
497 
498    Notes: See MATIS for more details
499           m and n are NOT related to the size of the map, they are the size of the part of the vector owned
500           by that process. m + nghosts (or n + nghosts) is the length of map since map maps all local points
501           plus the ghost points to global indices.
502 
503 .seealso: MATIS, MatSetLocalToGlobalMapping()
504 @*/
505 PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping map,Mat *A)
506 {
507   PetscErrorCode ierr;
508 
509   PetscFunctionBegin;
510   ierr = MatCreate(comm,A);CHKERRQ(ierr);
511   ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
512   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
513   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
514   ierr = MatSetUp(*A);CHKERRQ(ierr);
515   ierr = MatSetLocalToGlobalMapping(*A,map,map);CHKERRQ(ierr);
516   PetscFunctionReturn(0);
517 }
518 
519 /*MC
520    MATIS - MATIS = "is" - A matrix type to be used for using the Neumann-Neumann type preconditioners.
521    This stores the matrices in globally unassembled form. Each processor
522    assembles only its local Neumann problem and the parallel matrix vector
523    product is handled "implicitly".
524 
525    Operations Provided:
526 +  MatMult()
527 .  MatMultAdd()
528 .  MatMultTranspose()
529 .  MatMultTransposeAdd()
530 .  MatZeroEntries()
531 .  MatSetOption()
532 .  MatZeroRows()
533 .  MatZeroRowsLocal()
534 .  MatSetValues()
535 .  MatSetValuesLocal()
536 .  MatScale()
537 .  MatGetDiagonal()
538 -  MatSetLocalToGlobalMapping()
539 
540    Options Database Keys:
541 . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
542 
543    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
544 
545           You must call MatSetLocalToGlobalMapping() before using this matrix type.
546 
547           You can do matrix preallocation on the local matrix after you obtain it with
548           MatISGetLocalMat()
549 
550   Level: advanced
551 
552 .seealso: PC, MatISGetLocalMat(), MatSetLocalToGlobalMapping()
553 
554 M*/
555 
556 EXTERN_C_BEGIN
557 #undef __FUNCT__
558 #define __FUNCT__ "MatCreate_IS"
559 PetscErrorCode  MatCreate_IS(Mat A)
560 {
561   PetscErrorCode ierr;
562   Mat_IS         *b;
563 
564   PetscFunctionBegin;
565   ierr                = PetscNewLog(A,Mat_IS,&b);CHKERRQ(ierr);
566   A->data             = (void*)b;
567   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
568 
569   A->ops->mult                    = MatMult_IS;
570   A->ops->multadd                 = MatMultAdd_IS;
571   A->ops->multtranspose           = MatMultTranspose_IS;
572   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
573   A->ops->destroy                 = MatDestroy_IS;
574   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
575   A->ops->setvalues               = MatSetValues_IS;
576   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
577   A->ops->zerorows                = MatZeroRows_IS;
578   A->ops->zerorowslocal           = MatZeroRowsLocal_IS;
579   A->ops->assemblybegin           = MatAssemblyBegin_IS;
580   A->ops->assemblyend             = MatAssemblyEnd_IS;
581   A->ops->view                    = MatView_IS;
582   A->ops->zeroentries             = MatZeroEntries_IS;
583   A->ops->scale                   = MatScale_IS;
584   A->ops->getdiagonal             = MatGetDiagonal_IS;
585   A->ops->setoption               = MatSetOption_IS;
586 
587   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
588   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
589 
590   b->A          = 0;
591   b->ctx        = 0;
592   b->x          = 0;
593   b->y          = 0;
594   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatISGetLocalMat_C","MatISGetLocalMat_IS",MatISGetLocalMat_IS);CHKERRQ(ierr);
595   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatISSetLocalMat_C","MatISSetLocalMat_IS",MatISSetLocalMat_IS);CHKERRQ(ierr);
596   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
597 
598   PetscFunctionReturn(0);
599 }
600 EXTERN_C_END
601