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