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