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