xref: /petsc/src/vec/is/is/impls/block/block.c (revision ffb7e86ce04a759bf35c9adf63a5002355bf1185)
1 
2 /*
3      Provides the functions for index sets (IS) defined by a list of integers.
4    These are for blocks of data, each block is indicated with a single integer.
5 */
6 #include <petsc-private/isimpl.h>               /*I  "petscis.h"     I*/
7 #include <petscvec.h>
8 #include <petscviewer.h>
9 
10 typedef struct {
11   PetscBool sorted;             /* are the blocks sorted? */
12   PetscInt  *idx;
13 } IS_Block;
14 
15 #undef __FUNCT__
16 #define __FUNCT__ "ISDestroy_Block"
17 PetscErrorCode ISDestroy_Block(IS is)
18 {
19   IS_Block       *is_block = (IS_Block*)is->data;
20   PetscErrorCode ierr;
21 
22   PetscFunctionBegin;
23   ierr = PetscFree(is_block->idx);CHKERRQ(ierr);
24   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockSetIndices_C",0);CHKERRQ(ierr);
25   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockGetIndices_C",0);CHKERRQ(ierr);
26   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockRestoreIndices_C",0);CHKERRQ(ierr);
27   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockGetSize_C",0);CHKERRQ(ierr);
28   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockGetLocalSize_C",0);CHKERRQ(ierr);
29   ierr = PetscFree(is->data);CHKERRQ(ierr);
30   PetscFunctionReturn(0);
31 }
32 
33 #undef __FUNCT__
34 #define __FUNCT__ "ISGetIndices_Block"
35 PetscErrorCode ISGetIndices_Block(IS in,const PetscInt *idx[])
36 {
37   IS_Block       *sub = (IS_Block*)in->data;
38   PetscErrorCode ierr;
39   PetscInt       i,j,k,bs,n,*ii,*jj;
40 
41   PetscFunctionBegin;
42   ierr = PetscLayoutGetBlockSize(in->map, &bs);CHKERRQ(ierr);
43   ierr = PetscLayoutGetLocalSize(in->map, &n);CHKERRQ(ierr);
44   n   /= bs;
45   if (bs == 1) *idx = sub->idx;
46   else {
47     ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr);
48     *idx = jj;
49     k    = 0;
50     ii   = sub->idx;
51     for (i=0; i<n; i++)
52       for (j=0; j<bs; j++)
53         jj[k++] = bs*ii[i] + j;
54   }
55   PetscFunctionReturn(0);
56 }
57 
58 #undef __FUNCT__
59 #define __FUNCT__ "ISRestoreIndices_Block"
60 PetscErrorCode ISRestoreIndices_Block(IS is,const PetscInt *idx[])
61 {
62   IS_Block       *sub = (IS_Block*)is->data;
63   PetscInt       bs;
64   PetscErrorCode ierr;
65 
66   PetscFunctionBegin;
67   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
68   if (bs != 1) {
69     ierr = PetscFree(*(void**)idx);CHKERRQ(ierr);
70   } else {
71     if (*idx != sub->idx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must restore with value from ISGetIndices()");
72   }
73   PetscFunctionReturn(0);
74 }
75 
76 #undef __FUNCT__
77 #define __FUNCT__ "ISGetSize_Block"
78 PetscErrorCode ISGetSize_Block(IS is,PetscInt *size)
79 {
80   PetscErrorCode ierr;
81 
82   PetscFunctionBegin;
83   ierr = PetscLayoutGetSize(is->map, size);CHKERRQ(ierr);
84   PetscFunctionReturn(0);
85 }
86 
87 #undef __FUNCT__
88 #define __FUNCT__ "ISGetLocalSize_Block"
89 PetscErrorCode ISGetLocalSize_Block(IS is,PetscInt *size)
90 {
91   PetscErrorCode ierr;
92 
93   PetscFunctionBegin;
94   ierr = PetscLayoutGetLocalSize(is->map, size);CHKERRQ(ierr);
95   PetscFunctionReturn(0);
96 }
97 
98 #undef __FUNCT__
99 #define __FUNCT__ "ISInvertPermutation_Block"
100 PetscErrorCode ISInvertPermutation_Block(IS is,PetscInt nlocal,IS *isout)
101 {
102   IS_Block       *sub = (IS_Block*)is->data;
103   PetscInt       i,*ii,bs,n,*idx = sub->idx;
104   PetscMPIInt    size;
105   PetscErrorCode ierr;
106 
107   PetscFunctionBegin;
108   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)is),&size);CHKERRQ(ierr);
109   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
110   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
111   n   /= bs;
112   if (size == 1) {
113     ierr = PetscMalloc1(n,&ii);CHKERRQ(ierr);
114     for (i=0; i<n; i++) ii[idx[i]] = i;
115     ierr = ISCreateBlock(PETSC_COMM_SELF,bs,n,ii,PETSC_OWN_POINTER,isout);CHKERRQ(ierr);
116     ierr = ISSetPermutation(*isout);CHKERRQ(ierr);
117   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No inversion written yet for block IS");
118   PetscFunctionReturn(0);
119 }
120 
121 #undef __FUNCT__
122 #define __FUNCT__ "ISView_Block"
123 PetscErrorCode ISView_Block(IS is, PetscViewer viewer)
124 {
125   IS_Block       *sub = (IS_Block*)is->data;
126   PetscErrorCode ierr;
127   PetscInt       i,bs,n,*idx = sub->idx;
128   PetscBool      iascii;
129 
130   PetscFunctionBegin;
131   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
132   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
133   n   /= bs;
134   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
135   if (iascii) {
136     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
137     if (is->isperm) {
138       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Block Index set is permutation\n");CHKERRQ(ierr);
139     }
140     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Block size %D\n",bs);CHKERRQ(ierr);
141     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Number of block indices in set %D\n",n);CHKERRQ(ierr);
142     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"The first indices of each block are\n");CHKERRQ(ierr);
143     for (i=0; i<n; i++) {
144       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Block %D Index %D\n",i,idx[i]);CHKERRQ(ierr);
145     }
146     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
147     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
148   }
149   PetscFunctionReturn(0);
150 }
151 
152 #undef __FUNCT__
153 #define __FUNCT__ "ISSort_Block"
154 PetscErrorCode ISSort_Block(IS is)
155 {
156   IS_Block       *sub = (IS_Block*)is->data;
157   PetscInt       bs, n;
158   PetscErrorCode ierr;
159 
160   PetscFunctionBegin;
161   if (sub->sorted) PetscFunctionReturn(0);
162   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
163   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
164   ierr = PetscSortInt(n/bs,sub->idx);CHKERRQ(ierr);
165   sub->sorted = PETSC_TRUE;
166   PetscFunctionReturn(0);
167 }
168 
169 #undef __FUNCT__
170 #define __FUNCT__ "ISSortRemoveDups_Block"
171 PetscErrorCode ISSortRemoveDups_Block(IS is)
172 {
173   IS_Block       *sub = (IS_Block*)is->data;
174   PetscInt       bs, n, nb;
175   PetscErrorCode ierr;
176 
177   PetscFunctionBegin;
178   if (sub->sorted) PetscFunctionReturn(0);
179   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
180   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
181   nb   = n/bs;
182   ierr = PetscSortRemoveDupsInt(&nb,sub->idx);CHKERRQ(ierr);
183   ierr = PetscLayoutSetLocalSize(is->map, nb*bs);CHKERRQ(ierr);
184   sub->sorted = PETSC_TRUE;
185   PetscFunctionReturn(0);
186 }
187 
188 #undef __FUNCT__
189 #define __FUNCT__ "ISSorted_Block"
190 PetscErrorCode ISSorted_Block(IS is,PetscBool  *flg)
191 {
192   IS_Block *sub = (IS_Block*)is->data;
193 
194   PetscFunctionBegin;
195   *flg = sub->sorted;
196   PetscFunctionReturn(0);
197 }
198 
199 #undef __FUNCT__
200 #define __FUNCT__ "ISDuplicate_Block"
201 PetscErrorCode ISDuplicate_Block(IS is,IS *newIS)
202 {
203   PetscErrorCode ierr;
204   IS_Block       *sub = (IS_Block*)is->data;
205   PetscInt        bs, n;
206 
207   PetscFunctionBegin;
208   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
209   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
210   n   /= bs;
211   ierr = ISCreateBlock(PetscObjectComm((PetscObject)is),bs,n,sub->idx,PETSC_COPY_VALUES,newIS);CHKERRQ(ierr);
212   PetscFunctionReturn(0);
213 }
214 
215 #undef __FUNCT__
216 #define __FUNCT__ "ISIdentity_Block"
217 PetscErrorCode ISIdentity_Block(IS is,PetscBool  *ident)
218 {
219   IS_Block      *is_block = (IS_Block*)is->data;
220   PetscInt       i,bs,n,*idx = is_block->idx;
221   PetscErrorCode ierr;
222 
223   PetscFunctionBegin;
224   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
225   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
226   n   /= bs;
227   is->isidentity = PETSC_TRUE;
228   *ident         = PETSC_TRUE;
229   for (i=0; i<n; i++) {
230     if (idx[i] != bs*i) {
231       is->isidentity = PETSC_FALSE;
232       *ident         = PETSC_FALSE;
233       PetscFunctionReturn(0);
234     }
235   }
236   PetscFunctionReturn(0);
237 }
238 
239 #undef __FUNCT__
240 #define __FUNCT__ "ISCopy_Block"
241 static PetscErrorCode ISCopy_Block(IS is,IS isy)
242 {
243   IS_Block       *is_block = (IS_Block*)is->data,*isy_block = (IS_Block*)isy->data;
244   PetscInt       bs, n, N, bsy, ny, Ny;
245   PetscErrorCode ierr;
246 
247   PetscFunctionBegin;
248   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
249   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
250   ierr = PetscLayoutGetSize(is->map, &N);CHKERRQ(ierr);
251   ierr = PetscLayoutGetBlockSize(isy->map, &bsy);CHKERRQ(ierr);
252   ierr = PetscLayoutGetLocalSize(isy->map, &ny);CHKERRQ(ierr);
253   ierr = PetscLayoutGetSize(isy->map, &Ny);CHKERRQ(ierr);
254   if (n != ny || N != Ny || bs != bsy) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Index sets incompatible");
255   isy_block->sorted = is_block->sorted;
256   ierr = PetscMemcpy(isy_block->idx,is_block->idx,(n/bs)*sizeof(PetscInt));CHKERRQ(ierr);
257   PetscFunctionReturn(0);
258 }
259 
260 #undef __FUNCT__
261 #define __FUNCT__ "ISOnComm_Block"
262 static PetscErrorCode ISOnComm_Block(IS is,MPI_Comm comm,PetscCopyMode mode,IS *newis)
263 {
264   PetscErrorCode ierr;
265   IS_Block       *sub = (IS_Block*)is->data;
266   PetscInt       bs, n;
267 
268   PetscFunctionBegin;
269   if (mode == PETSC_OWN_POINTER) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Cannot use PETSC_OWN_POINTER");
270   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
271   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
272   ierr = ISCreateBlock(comm,bs,n/bs,sub->idx,mode,newis);CHKERRQ(ierr);
273   PetscFunctionReturn(0);
274 }
275 
276 #undef __FUNCT__
277 #define __FUNCT__ "ISSetBlockSize_Block"
278 static PetscErrorCode ISSetBlockSize_Block(IS is,PetscInt bs)
279 {
280   PetscErrorCode ierr;
281 
282   PetscFunctionBegin;
283   ierr = PetscLayoutSetBlockSize(is->map, bs);CHKERRQ(ierr);
284   PetscFunctionReturn(0);
285 }
286 
287 
288 static struct _ISOps myops = { ISGetSize_Block,
289                                ISGetLocalSize_Block,
290                                ISGetIndices_Block,
291                                ISRestoreIndices_Block,
292                                ISInvertPermutation_Block,
293                                ISSort_Block,
294                                ISSortRemoveDups_Block,
295                                ISSorted_Block,
296                                ISDuplicate_Block,
297                                ISDestroy_Block,
298                                ISView_Block,
299                                ISLoad_Default,
300                                ISIdentity_Block,
301                                ISCopy_Block,
302                                0,
303                                ISOnComm_Block,
304                                ISSetBlockSize_Block,
305                                0};
306 
307 #undef __FUNCT__
308 #define __FUNCT__ "ISBlockSetIndices"
309 /*@
310    ISBlockSetIndices - The indices are relative to entries, not blocks.
311 
312    Collective on IS
313 
314    Input Parameters:
315 +  is - the index set
316 .  bs - number of elements in each block, one for each block and count of block not indices
317 .   n - the length of the index set (the number of blocks)
318 .  idx - the list of integers, these are by block, not by location
319 +  mode - see PetscCopyMode, only PETSC_COPY_VALUES and PETSC_OWN_POINTER are supported
320 
321 
322    Notes:
323    When the communicator is not MPI_COMM_SELF, the operations on the
324    index sets, IS, are NOT conceptually the same as MPI_Group operations.
325    The index sets are then distributed sets of indices and thus certain operations
326    on them are collective.
327 
328    Example:
329    If you wish to index the values {0,1,4,5}, then use
330    a block size of 2 and idx of {0,2}.
331 
332    Level: beginner
333 
334   Concepts: IS^block
335   Concepts: index sets^block
336   Concepts: block^index set
337 
338 .seealso: ISCreateStride(), ISCreateGeneral(), ISAllGather()
339 @*/
340 PetscErrorCode  ISBlockSetIndices(IS is,PetscInt bs,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
341 {
342   PetscErrorCode ierr;
343 
344   PetscFunctionBegin;
345   ierr = PetscUseMethod(is,"ISBlockSetIndices_C",(IS,PetscInt,PetscInt,const PetscInt[],PetscCopyMode),(is,bs,n,idx,mode));CHKERRQ(ierr);
346   PetscFunctionReturn(0);
347 }
348 
349 #undef __FUNCT__
350 #define __FUNCT__ "ISBlockSetIndices_Block"
351 PetscErrorCode  ISBlockSetIndices_Block(IS is,PetscInt bs,PetscInt n,const PetscInt idx[],PetscCopyMode mode)
352 {
353   PetscErrorCode ierr;
354   PetscInt       i,min,max;
355   IS_Block       *sub   = (IS_Block*)is->data;
356   PetscBool      sorted = PETSC_TRUE;
357 
358   PetscFunctionBegin;
359   ierr = PetscFree(sub->idx);CHKERRQ(ierr);
360   ierr = PetscLayoutSetLocalSize(is->map, n*bs);CHKERRQ(ierr);
361   ierr = PetscLayoutSetBlockSize(is->map, bs);CHKERRQ(ierr);
362   ierr = PetscLayoutSetUp(is->map);CHKERRQ(ierr);
363   for (i=1; i<n; i++) {
364     if (idx[i] < idx[i-1]) {sorted = PETSC_FALSE; break;}
365   }
366   if (n) min = max = idx[0];
367   else   min = max = 0;
368   for (i=1; i<n; i++) {
369     if (idx[i] < min) min = idx[i];
370     if (idx[i] > max) max = idx[i];
371   }
372   if (mode == PETSC_COPY_VALUES) {
373     ierr = PetscMalloc1(n,&sub->idx);CHKERRQ(ierr);
374     ierr = PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));CHKERRQ(ierr);
375     ierr = PetscMemcpy(sub->idx,idx,n*sizeof(PetscInt));CHKERRQ(ierr);
376   } else if (mode == PETSC_OWN_POINTER) sub->idx = (PetscInt*) idx;
377   else SETERRQ(PetscObjectComm((PetscObject)is),PETSC_ERR_SUP,"Only supports PETSC_COPY_VALUES and PETSC_OWN_POINTER");
378 
379   sub->sorted = sorted;
380   is->min     = bs*min;
381   is->max     = bs*max+bs-1;
382   is->data    = (void*)sub;
383   ierr = PetscMemcpy(is->ops,&myops,sizeof(myops));CHKERRQ(ierr);
384   is->isperm  = PETSC_FALSE;
385   PetscFunctionReturn(0);
386 }
387 
388 #undef __FUNCT__
389 #define __FUNCT__ "ISCreateBlock"
390 /*@
391    ISCreateBlock - Creates a data structure for an index set containing
392    a list of integers. The indices are relative to entries, not blocks.
393 
394    Collective on MPI_Comm
395 
396    Input Parameters:
397 +  comm - the MPI communicator
398 .  bs - number of elements in each block
399 .  n - the length of the index set (the number of blocks)
400 .  idx - the list of integers, one for each block and count of block not indices
401 -  mode - see PetscCopyMode, only PETSC_COPY_VALUES and PETSC_OWN_POINTER are supported in this routine
402 
403    Output Parameter:
404 .  is - the new index set
405 
406    Notes:
407    When the communicator is not MPI_COMM_SELF, the operations on the
408    index sets, IS, are NOT conceptually the same as MPI_Group operations.
409    The index sets are then distributed sets of indices and thus certain operations
410    on them are collective.
411 
412    Example:
413    If you wish to index the values {0,1,6,7}, then use
414    a block size of 2 and idx of {0,3}.
415 
416    Level: beginner
417 
418   Concepts: IS^block
419   Concepts: index sets^block
420   Concepts: block^index set
421 
422 .seealso: ISCreateStride(), ISCreateGeneral(), ISAllGather()
423 @*/
424 PetscErrorCode  ISCreateBlock(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt idx[],PetscCopyMode mode,IS *is)
425 {
426   PetscErrorCode ierr;
427 
428   PetscFunctionBegin;
429   PetscValidPointer(is,5);
430   if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
431   if (n) PetscValidIntPointer(idx,4);
432 
433   ierr = ISCreate(comm,is);CHKERRQ(ierr);
434   ierr = ISSetType(*is,ISBLOCK);CHKERRQ(ierr);
435   ierr = ISBlockSetIndices(*is,bs,n,idx,mode);CHKERRQ(ierr);
436   PetscFunctionReturn(0);
437 }
438 
439 #undef __FUNCT__
440 #define __FUNCT__ "ISBlockGetIndices_Block"
441 PetscErrorCode  ISBlockGetIndices_Block(IS is,const PetscInt *idx[])
442 {
443   IS_Block *sub = (IS_Block*)is->data;
444 
445   PetscFunctionBegin;
446   *idx = sub->idx;
447   PetscFunctionReturn(0);
448 }
449 
450 #undef __FUNCT__
451 #define __FUNCT__ "ISBlockRestoreIndices_Block"
452 PetscErrorCode  ISBlockRestoreIndices_Block(IS is,const PetscInt *idx[])
453 {
454   PetscFunctionBegin;
455   PetscFunctionReturn(0);
456 }
457 
458 #undef __FUNCT__
459 #define __FUNCT__ "ISBlockGetIndices"
460 /*@C
461    ISBlockGetIndices - Gets the indices associated with each block.
462 
463    Not Collective
464 
465    Input Parameter:
466 .  is - the index set
467 
468    Output Parameter:
469 .  idx - the integer indices, one for each block and count of block not indices
470 
471    Level: intermediate
472 
473    Concepts: IS^block
474    Concepts: index sets^getting indices
475    Concepts: index sets^block
476 
477 .seealso: ISGetIndices(), ISBlockRestoreIndices()
478 @*/
479 PetscErrorCode  ISBlockGetIndices(IS is,const PetscInt *idx[])
480 {
481   PetscErrorCode ierr;
482 
483   PetscFunctionBegin;
484   ierr = PetscUseMethod(is,"ISBlockGetIndices_C",(IS,const PetscInt*[]),(is,idx));CHKERRQ(ierr);
485   PetscFunctionReturn(0);
486 }
487 
488 #undef __FUNCT__
489 #define __FUNCT__ "ISBlockRestoreIndices"
490 /*@C
491    ISBlockRestoreIndices - Restores the indices associated with each block.
492 
493    Not Collective
494 
495    Input Parameter:
496 .  is - the index set
497 
498    Output Parameter:
499 .  idx - the integer indices
500 
501    Level: intermediate
502 
503    Concepts: IS^block
504    Concepts: index sets^getting indices
505    Concepts: index sets^block
506 
507 .seealso: ISRestoreIndices(), ISBlockGetIndices()
508 @*/
509 PetscErrorCode  ISBlockRestoreIndices(IS is,const PetscInt *idx[])
510 {
511   PetscErrorCode ierr;
512 
513   PetscFunctionBegin;
514   ierr = PetscUseMethod(is,"ISBlockRestoreIndices_C",(IS,const PetscInt*[]),(is,idx));CHKERRQ(ierr);
515   PetscFunctionReturn(0);
516 }
517 
518 #undef __FUNCT__
519 #define __FUNCT__ "ISBlockGetLocalSize"
520 /*@
521    ISBlockGetLocalSize - Returns the local number of blocks in the index set.
522 
523    Not Collective
524 
525    Input Parameter:
526 .  is - the index set
527 
528    Output Parameter:
529 .  size - the local number of blocks
530 
531    Level: intermediate
532 
533    Concepts: IS^block sizes
534    Concepts: index sets^block sizes
535 
536 .seealso: ISGetBlockSize(), ISBlockGetSize(), ISGetSize(), ISCreateBlock()
537 @*/
538 PetscErrorCode  ISBlockGetLocalSize(IS is,PetscInt *size)
539 {
540   PetscErrorCode ierr;
541 
542   PetscFunctionBegin;
543   ierr = PetscUseMethod(is,"ISBlockGetLocalSize_C",(IS,PetscInt*),(is,size));CHKERRQ(ierr);
544   PetscFunctionReturn(0);
545 }
546 
547 #undef __FUNCT__
548 #define __FUNCT__ "ISBlockGetLocalSize_Block"
549 PetscErrorCode  ISBlockGetLocalSize_Block(IS is,PetscInt *size)
550 {
551   PetscInt       bs, n;
552   PetscErrorCode ierr;
553 
554   PetscFunctionBegin;
555   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
556   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
557   *size = n/bs;
558   PetscFunctionReturn(0);
559 }
560 
561 #undef __FUNCT__
562 #define __FUNCT__ "ISBlockGetSize"
563 /*@
564    ISBlockGetSize - Returns the global number of blocks in the index set.
565 
566    Not Collective
567 
568    Input Parameter:
569 .  is - the index set
570 
571    Output Parameter:
572 .  size - the global number of blocks
573 
574    Level: intermediate
575 
576    Concepts: IS^block sizes
577    Concepts: index sets^block sizes
578 
579 .seealso: ISGetBlockSize(), ISBlockGetLocalSize(), ISGetSize(), ISCreateBlock()
580 @*/
581 PetscErrorCode  ISBlockGetSize(IS is,PetscInt *size)
582 {
583   PetscErrorCode ierr;
584 
585   PetscFunctionBegin;
586   ierr = PetscUseMethod(is,"ISBlockGetSize_C",(IS,PetscInt*),(is,size));CHKERRQ(ierr);
587   PetscFunctionReturn(0);
588 }
589 
590 #undef __FUNCT__
591 #define __FUNCT__ "ISBlockGetSize_Block"
592 PetscErrorCode  ISBlockGetSize_Block(IS is,PetscInt *size)
593 {
594   PetscInt       bs, N;
595   PetscErrorCode ierr;
596 
597   PetscFunctionBegin;
598   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
599   ierr = PetscLayoutGetSize(is->map, &N);CHKERRQ(ierr);
600   *size = N/bs;
601   PetscFunctionReturn(0);
602 }
603 
604 #undef __FUNCT__
605 #define __FUNCT__ "ISToGeneral_Block"
606 PetscErrorCode  ISToGeneral_Block(IS inis)
607 {
608   PetscErrorCode ierr;
609   const PetscInt *idx;
610   PetscInt       n;
611 
612   PetscFunctionBegin;
613   ierr = ISGetLocalSize(inis,&n);CHKERRQ(ierr);
614   ierr = ISGetIndices(inis,&idx);CHKERRQ(ierr);
615   ierr = ISSetType(inis,ISGENERAL);CHKERRQ(ierr);
616   ierr = ISGeneralSetIndices(inis,n,idx,PETSC_OWN_POINTER);CHKERRQ(ierr);
617   PetscFunctionReturn(0);
618 }
619 
620 #undef __FUNCT__
621 #define __FUNCT__ "ISCreate_Block"
622 PETSC_EXTERN PetscErrorCode ISCreate_Block(IS is)
623 {
624   PetscErrorCode ierr;
625   IS_Block       *sub;
626 
627   PetscFunctionBegin;
628   ierr = PetscNewLog(is,&sub);CHKERRQ(ierr);
629   is->data = sub;
630   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockSetIndices_C",ISBlockSetIndices_Block);CHKERRQ(ierr);
631   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockGetIndices_C",ISBlockGetIndices_Block);CHKERRQ(ierr);
632   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockRestoreIndices_C",ISBlockRestoreIndices_Block);CHKERRQ(ierr);
633   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockGetSize_C",ISBlockGetSize_Block);CHKERRQ(ierr);
634   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockGetLocalSize_C",ISBlockGetLocalSize_Block);CHKERRQ(ierr);
635   PetscFunctionReturn(0);
636 }
637