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