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