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