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