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