xref: /petsc/src/mat/impls/is/matis.c (revision 84df9cb40eca90ea9b18a456fab7a4ecc7f6c1a4)
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;
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 = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
166   ierr = MatSetSizes(is->A,n,n,n,n);CHKERRQ(ierr);
167   ierr = MatSetOptionsPrefix(is->A,"is");CHKERRQ(ierr);
168   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
169 
170   /* Create the local work vectors */
171   ierr = VecCreateSeq(PETSC_COMM_SELF,n,&is->x);CHKERRQ(ierr);
172   ierr = VecDuplicate(is->x,&is->y);CHKERRQ(ierr);
173 
174   /* setup the global to local scatter */
175   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&to);CHKERRQ(ierr);
176   ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
177   ierr = VecCreateMPIWithArray(((PetscObject)A)->comm,A->cmap->n,A->cmap->N,PETSC_NULL,&global);CHKERRQ(ierr);
178   ierr = VecScatterCreate(global,from,is->x,to,&is->ctx);CHKERRQ(ierr);
179   ierr = VecDestroy(&global);CHKERRQ(ierr);
180   ierr = ISDestroy(&to);CHKERRQ(ierr);
181   ierr = ISDestroy(&from);CHKERRQ(ierr);
182   PetscFunctionReturn(0);
183 }
184 
185 #define ISG2LMapApply(mapping,n,in,out) 0;\
186   if (!(mapping)->globals) {\
187    PetscErrorCode _ierr = ISGlobalToLocalMappingApply((mapping),IS_GTOLM_MASK,0,0,0,0);CHKERRQ(_ierr);\
188   }\
189   {\
190     PetscInt _i,*_globals = (mapping)->globals,_start = (mapping)->globalstart,_end = (mapping)->globalend;\
191     for (_i=0; _i<n; _i++) {\
192       if (in[_i] < 0)           out[_i] = in[_i];\
193       else if (in[_i] < _start) out[_i] = -1;\
194       else if (in[_i] > _end)   out[_i] = -1;\
195       else                      out[_i] = _globals[in[_i] - _start];\
196     }\
197   }
198 
199 #undef __FUNCT__
200 #define __FUNCT__ "MatSetValues_IS"
201 PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
202 {
203   Mat_IS         *is = (Mat_IS*)mat->data;
204   PetscInt       rows_l[2048],cols_l[2048];
205   PetscErrorCode ierr;
206 
207   PetscFunctionBegin;
208 #if defined(PETSC_USE_DEBUG)
209   if (m > 2048 || n > 2048) {
210     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= 2048: they are %D %D",m,n);
211   }
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 = PETSC_NULL;
240   PetscErrorCode ierr;
241 
242   PetscFunctionBegin;
243   if (x && b) SETERRQ(((PetscObject)A)->comm,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(((PetscObject)A)->comm,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 = VecCreateMPI(((PetscObject)A)->comm,A->cmap->n,A->cmap->N,&counter);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     ierr = VecGetArray(is->x,&array);CHKERRQ(ierr);
285     ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
286     for (i=0; i<n; i++) {
287       ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
288     }
289     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
290     ierr = MatAssemblyEnd  (is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
291     ierr = VecRestoreArray(is->x,&array);CHKERRQ(ierr);
292   }
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 #undef __FUNCT__
366 #define __FUNCT__ "MatZeroEntries_IS"
367 PetscErrorCode MatZeroEntries_IS(Mat A)
368 {
369   Mat_IS         *a = (Mat_IS*)A->data;
370   PetscErrorCode ierr;
371 
372   PetscFunctionBegin;
373   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
374   PetscFunctionReturn(0);
375 }
376 
377 #undef __FUNCT__
378 #define __FUNCT__ "MatScale_IS"
379 PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
380 {
381   Mat_IS         *is = (Mat_IS*)A->data;
382   PetscErrorCode ierr;
383 
384   PetscFunctionBegin;
385   ierr = MatScale(is->A,a);CHKERRQ(ierr);
386   PetscFunctionReturn(0);
387 }
388 
389 #undef __FUNCT__
390 #define __FUNCT__ "MatGetDiagonal_IS"
391 PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
392 {
393   Mat_IS         *is = (Mat_IS*)A->data;
394   PetscErrorCode ierr;
395 
396   PetscFunctionBegin;
397   /* get diagonal of the local matrix */
398   ierr = MatGetDiagonal(is->A,is->x);CHKERRQ(ierr);
399 
400   /* scatter diagonal back into global vector */
401   ierr = VecSet(v,0);CHKERRQ(ierr);
402   ierr = VecScatterBegin(is->ctx,is->x,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
403   ierr = VecScatterEnd  (is->ctx,is->x,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
404   PetscFunctionReturn(0);
405 }
406 
407 #undef __FUNCT__
408 #define __FUNCT__ "MatSetOption_IS"
409 PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool  flg)
410 {
411   Mat_IS         *a = (Mat_IS*)A->data;
412   PetscErrorCode ierr;
413 
414   PetscFunctionBegin;
415   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
416   PetscFunctionReturn(0);
417 }
418 
419 #undef __FUNCT__
420 #define __FUNCT__ "MatCreateIS"
421 /*@
422     MatCreateIS - Creates a "process" unassmembled matrix, it is assembled on each
423        process but not across processes.
424 
425    Input Parameters:
426 +     comm - MPI communicator that will share the matrix
427 .     m,n,M,N - local and/or global sizes of the the left and right vector used in matrix vector products
428 -     map - mapping that defines the global number for each local number
429 
430    Output Parameter:
431 .    A - the resulting matrix
432 
433    Level: advanced
434 
435    Notes: See MATIS for more details
436           m and n are NOT related to the size of the map, they are the size of the part of the vector owned
437           by that process. m + nghosts (or n + nghosts) is the length of map since map maps all local points
438           plus the ghost points to global indices.
439 
440 .seealso: MATIS, MatSetLocalToGlobalMapping()
441 @*/
442 PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping map,Mat *A)
443 {
444   PetscErrorCode ierr;
445 
446   PetscFunctionBegin;
447   ierr = MatCreate(comm,A);CHKERRQ(ierr);
448   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
449   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
450   ierr = MatSetLocalToGlobalMapping(*A,map,map);CHKERRQ(ierr);
451   PetscFunctionReturn(0);
452 }
453 
454 /*MC
455    MATIS - MATIS = "is" - A matrix type to be used for using the Neumann-Neumann type preconditioners.
456    This stores the matrices in globally unassembled form. Each processor
457    assembles only its local Neumann problem and the parallel matrix vector
458    product is handled "implicitly".
459 
460    Operations Provided:
461 +  MatMult()
462 .  MatMultAdd()
463 .  MatMultTranspose()
464 .  MatMultTransposeAdd()
465 .  MatZeroEntries()
466 .  MatSetOption()
467 .  MatZeroRows()
468 .  MatZeroRowsLocal()
469 .  MatSetValues()
470 .  MatSetValuesLocal()
471 .  MatScale()
472 .  MatGetDiagonal()
473 -  MatSetLocalToGlobalMapping()
474 
475    Options Database Keys:
476 . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
477 
478    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
479 
480           You must call MatSetLocalToGlobalMapping() before using this matrix type.
481 
482           You can do matrix preallocation on the local matrix after you obtain it with
483           MatISGetLocalMat()
484 
485   Level: advanced
486 
487 .seealso: PC, MatISGetLocalMat(), MatSetLocalToGlobalMapping()
488 
489 M*/
490 
491 EXTERN_C_BEGIN
492 #undef __FUNCT__
493 #define __FUNCT__ "MatCreate_IS"
494 PetscErrorCode  MatCreate_IS(Mat A)
495 {
496   PetscErrorCode ierr;
497   Mat_IS         *b;
498 
499   PetscFunctionBegin;
500   ierr                = PetscNewLog(A,Mat_IS,&b);CHKERRQ(ierr);
501   A->data             = (void*)b;
502   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
503 
504   A->ops->mult                    = MatMult_IS;
505   A->ops->multadd                 = MatMultAdd_IS;
506   A->ops->multtranspose           = MatMultTranspose_IS;
507   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
508   A->ops->destroy                 = MatDestroy_IS;
509   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
510   A->ops->setvalues               = MatSetValues_IS;
511   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
512   A->ops->zerorows                = MatZeroRows_IS;
513   A->ops->zerorowslocal           = MatZeroRowsLocal_IS;
514   A->ops->assemblybegin           = MatAssemblyBegin_IS;
515   A->ops->assemblyend             = MatAssemblyEnd_IS;
516   A->ops->view                    = MatView_IS;
517   A->ops->zeroentries             = MatZeroEntries_IS;
518   A->ops->scale                   = MatScale_IS;
519   A->ops->getdiagonal             = MatGetDiagonal_IS;
520   A->ops->setoption               = MatSetOption_IS;
521 
522   ierr = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr);
523   ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr);
524   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
525   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
526 
527   b->A          = 0;
528   b->ctx        = 0;
529   b->x          = 0;
530   b->y          = 0;
531   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatISGetLocalMat_C","MatISGetLocalMat_IS",MatISGetLocalMat_IS);CHKERRQ(ierr);
532   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
533 
534   PetscFunctionReturn(0);
535 }
536 EXTERN_C_END
537