xref: /petsc/src/vec/is/is/impls/block/block.c (revision d5be86a547222b014b8beee3956fb9da37d6ba20)
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) min = max = idx[0];
437   else   min = max = 0;
438   for (i=1; i<n; i++) {
439     if (idx[i] < min) min = idx[i];
440     if (idx[i] > max) max = idx[i];
441   }
442   if (mode == PETSC_COPY_VALUES) {
443     ierr = PetscMalloc1(n,&sub->idx);CHKERRQ(ierr);
444     ierr = PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));CHKERRQ(ierr);
445     ierr = PetscMemcpy(sub->idx,idx,n*sizeof(PetscInt));CHKERRQ(ierr);
446   } else if (mode == PETSC_OWN_POINTER) {
447     sub->idx = (PetscInt*) idx;
448     ierr = PetscLogObjectMemory((PetscObject)is,n*sizeof(PetscInt));CHKERRQ(ierr);
449   } else if (mode == PETSC_USE_POINTER) {
450     sub->idx = (PetscInt*) idx;
451     sub->borrowed_indices = PETSC_TRUE;
452   }
453 
454   sub->sorted = sorted;
455   is->min     = bs*min;
456   is->max     = bs*max+bs-1;
457   is->data    = (void*)sub;
458   ierr = PetscMemcpy(is->ops,&myops,sizeof(myops));CHKERRQ(ierr);
459   is->isperm  = PETSC_FALSE;
460   PetscFunctionReturn(0);
461 }
462 
463 #undef __FUNCT__
464 #define __FUNCT__ "ISCreateBlock"
465 /*@
466    ISCreateBlock - Creates a data structure for an index set containing
467    a list of integers. The indices are relative to entries, not blocks.
468 
469    Collective on MPI_Comm
470 
471    Input Parameters:
472 +  comm - the MPI communicator
473 .  bs - number of elements in each block
474 .  n - the length of the index set (the number of blocks)
475 .  idx - the list of integers, one for each block and count of block not indices
476 -  mode - see PetscCopyMode, only PETSC_COPY_VALUES and PETSC_OWN_POINTER are supported in this routine
477 
478    Output Parameter:
479 .  is - the new index set
480 
481    Notes:
482    When the communicator is not MPI_COMM_SELF, the operations on the
483    index sets, IS, are NOT conceptually the same as MPI_Group operations.
484    The index sets are then distributed sets of indices and thus certain operations
485    on them are collective.
486 
487    Example:
488    If you wish to index the values {0,1,6,7}, then use
489    a block size of 2 and idx of {0,3}.
490 
491    Level: beginner
492 
493   Concepts: IS^block
494   Concepts: index sets^block
495   Concepts: block^index set
496 
497 .seealso: ISCreateStride(), ISCreateGeneral(), ISAllGather()
498 @*/
499 PetscErrorCode  ISCreateBlock(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt idx[],PetscCopyMode mode,IS *is)
500 {
501   PetscErrorCode ierr;
502 
503   PetscFunctionBegin;
504   PetscValidPointer(is,5);
505   if (n < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"length < 0");
506   if (n) PetscValidIntPointer(idx,4);
507 
508   ierr = ISCreate(comm,is);CHKERRQ(ierr);
509   ierr = ISSetType(*is,ISBLOCK);CHKERRQ(ierr);
510   ierr = ISBlockSetIndices(*is,bs,n,idx,mode);CHKERRQ(ierr);
511   PetscFunctionReturn(0);
512 }
513 
514 #undef __FUNCT__
515 #define __FUNCT__ "ISBlockGetIndices_Block"
516 static PetscErrorCode  ISBlockGetIndices_Block(IS is,const PetscInt *idx[])
517 {
518   IS_Block *sub = (IS_Block*)is->data;
519 
520   PetscFunctionBegin;
521   *idx = sub->idx;
522   PetscFunctionReturn(0);
523 }
524 
525 #undef __FUNCT__
526 #define __FUNCT__ "ISBlockRestoreIndices_Block"
527 static PetscErrorCode  ISBlockRestoreIndices_Block(IS is,const PetscInt *idx[])
528 {
529   PetscFunctionBegin;
530   PetscFunctionReturn(0);
531 }
532 
533 #undef __FUNCT__
534 #define __FUNCT__ "ISBlockGetIndices"
535 /*@C
536    ISBlockGetIndices - Gets the indices associated with each block.
537 
538    Not Collective
539 
540    Input Parameter:
541 .  is - the index set
542 
543    Output Parameter:
544 .  idx - the integer indices, one for each block and count of block not indices
545 
546    Level: intermediate
547 
548    Concepts: IS^block
549    Concepts: index sets^getting indices
550    Concepts: index sets^block
551 
552 .seealso: ISGetIndices(), ISBlockRestoreIndices()
553 @*/
554 PetscErrorCode  ISBlockGetIndices(IS is,const PetscInt *idx[])
555 {
556   PetscErrorCode ierr;
557 
558   PetscFunctionBegin;
559   ierr = PetscUseMethod(is,"ISBlockGetIndices_C",(IS,const PetscInt*[]),(is,idx));CHKERRQ(ierr);
560   PetscFunctionReturn(0);
561 }
562 
563 #undef __FUNCT__
564 #define __FUNCT__ "ISBlockRestoreIndices"
565 /*@C
566    ISBlockRestoreIndices - Restores the indices associated with each block.
567 
568    Not Collective
569 
570    Input Parameter:
571 .  is - the index set
572 
573    Output Parameter:
574 .  idx - the integer indices
575 
576    Level: intermediate
577 
578    Concepts: IS^block
579    Concepts: index sets^getting indices
580    Concepts: index sets^block
581 
582 .seealso: ISRestoreIndices(), ISBlockGetIndices()
583 @*/
584 PetscErrorCode  ISBlockRestoreIndices(IS is,const PetscInt *idx[])
585 {
586   PetscErrorCode ierr;
587 
588   PetscFunctionBegin;
589   ierr = PetscUseMethod(is,"ISBlockRestoreIndices_C",(IS,const PetscInt*[]),(is,idx));CHKERRQ(ierr);
590   PetscFunctionReturn(0);
591 }
592 
593 #undef __FUNCT__
594 #define __FUNCT__ "ISBlockGetLocalSize"
595 /*@
596    ISBlockGetLocalSize - Returns the local number of blocks in the index set.
597 
598    Not Collective
599 
600    Input Parameter:
601 .  is - the index set
602 
603    Output Parameter:
604 .  size - the local number of blocks
605 
606    Level: intermediate
607 
608    Concepts: IS^block sizes
609    Concepts: index sets^block sizes
610 
611 .seealso: ISGetBlockSize(), ISBlockGetSize(), ISGetSize(), ISCreateBlock()
612 @*/
613 PetscErrorCode  ISBlockGetLocalSize(IS is,PetscInt *size)
614 {
615   PetscErrorCode ierr;
616 
617   PetscFunctionBegin;
618   ierr = PetscUseMethod(is,"ISBlockGetLocalSize_C",(IS,PetscInt*),(is,size));CHKERRQ(ierr);
619   PetscFunctionReturn(0);
620 }
621 
622 #undef __FUNCT__
623 #define __FUNCT__ "ISBlockGetLocalSize_Block"
624 static PetscErrorCode  ISBlockGetLocalSize_Block(IS is,PetscInt *size)
625 {
626   PetscInt       bs, n;
627   PetscErrorCode ierr;
628 
629   PetscFunctionBegin;
630   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
631   ierr = PetscLayoutGetLocalSize(is->map, &n);CHKERRQ(ierr);
632   *size = n/bs;
633   PetscFunctionReturn(0);
634 }
635 
636 #undef __FUNCT__
637 #define __FUNCT__ "ISBlockGetSize"
638 /*@
639    ISBlockGetSize - Returns the global number of blocks in the index set.
640 
641    Not Collective
642 
643    Input Parameter:
644 .  is - the index set
645 
646    Output Parameter:
647 .  size - the global number of blocks
648 
649    Level: intermediate
650 
651    Concepts: IS^block sizes
652    Concepts: index sets^block sizes
653 
654 .seealso: ISGetBlockSize(), ISBlockGetLocalSize(), ISGetSize(), ISCreateBlock()
655 @*/
656 PetscErrorCode  ISBlockGetSize(IS is,PetscInt *size)
657 {
658   PetscErrorCode ierr;
659 
660   PetscFunctionBegin;
661   ierr = PetscUseMethod(is,"ISBlockGetSize_C",(IS,PetscInt*),(is,size));CHKERRQ(ierr);
662   PetscFunctionReturn(0);
663 }
664 
665 #undef __FUNCT__
666 #define __FUNCT__ "ISBlockGetSize_Block"
667 static PetscErrorCode  ISBlockGetSize_Block(IS is,PetscInt *size)
668 {
669   PetscInt       bs, N;
670   PetscErrorCode ierr;
671 
672   PetscFunctionBegin;
673   ierr = PetscLayoutGetBlockSize(is->map, &bs);CHKERRQ(ierr);
674   ierr = PetscLayoutGetSize(is->map, &N);CHKERRQ(ierr);
675   *size = N/bs;
676   PetscFunctionReturn(0);
677 }
678 
679 #undef __FUNCT__
680 #define __FUNCT__ "ISCreate_Block"
681 PETSC_EXTERN PetscErrorCode ISCreate_Block(IS is)
682 {
683   PetscErrorCode ierr;
684   IS_Block       *sub;
685 
686   PetscFunctionBegin;
687   ierr = PetscNewLog(is,&sub);CHKERRQ(ierr);
688   is->data = sub;
689   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockSetIndices_C",ISBlockSetIndices_Block);CHKERRQ(ierr);
690   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockGetIndices_C",ISBlockGetIndices_Block);CHKERRQ(ierr);
691   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockRestoreIndices_C",ISBlockRestoreIndices_Block);CHKERRQ(ierr);
692   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockGetSize_C",ISBlockGetSize_Block);CHKERRQ(ierr);
693   ierr = PetscObjectComposeFunction((PetscObject)is,"ISBlockGetLocalSize_C",ISBlockGetLocalSize_Block);CHKERRQ(ierr);
694   PetscFunctionReturn(0);
695 }
696