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