xref: /petsc/src/vec/is/utils/pmap.c (revision f97672e55eacc8688507b9471cd7ec2664d7f203) !
1 
2 /*
3    This file contains routines for basic map object implementation.
4 */
5 
6 #include <petsc/private/isimpl.h> /*I "petscis.h" I*/
7 
8 /*@
9   PetscLayoutCreate - Allocates PetscLayout space and sets the PetscLayout contents to the default.
10 
11   Collective
12 
13   Input Parameters:
14 . comm - the MPI communicator
15 
16   Output Parameters:
17 . map - the new PetscLayout
18 
19   Level: advanced
20 
21   Notes:
22   Typical calling sequence
23 .vb
24        PetscLayoutCreate(MPI_Comm,PetscLayout *);
25        PetscLayoutSetBlockSize(PetscLayout,bs);
26        PetscLayoutSetSize(PetscLayout,N); // or PetscLayoutSetLocalSize(PetscLayout,n);
27        PetscLayoutSetUp(PetscLayout);
28 .ve
29   Alternatively,
30 .vb
31       PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
32 .ve
33 
34   Optionally use any of the following
35 .vb
36   PetscLayoutGetSize(PetscLayout,PetscInt *);
37   PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
38   PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
39   PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
40   PetscLayoutDestroy(PetscLayout*);
41 .ve
42 
43   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is often not needed in
44   user codes unless you really gain something in their use.
45 
46 .seealso: `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
47           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`,
48           `PetscLayoutCreateFromSizes()`
49 
50 @*/
51 PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
52 {
53   PetscFunctionBegin;
54   PetscCall(PetscNew(map));
55   PetscCallMPI(MPI_Comm_size(comm, &(*map)->size));
56   (*map)->comm        = comm;
57   (*map)->bs          = -1;
58   (*map)->n           = -1;
59   (*map)->N           = -1;
60   (*map)->range       = NULL;
61   (*map)->range_alloc = PETSC_TRUE;
62   (*map)->rstart      = 0;
63   (*map)->rend        = 0;
64   (*map)->setupcalled = PETSC_FALSE;
65   (*map)->oldn        = -1;
66   (*map)->oldN        = -1;
67   (*map)->oldbs       = -1;
68   PetscFunctionReturn(0);
69 }
70 
71 /*@
72   PetscLayoutCreateFromSizes - Allocates PetscLayout space, sets the layout sizes, and sets the layout up.
73 
74   Collective
75 
76   Input Parameters:
77 + comm  - the MPI communicator
78 . n     - the local size (or PETSC_DECIDE)
79 . N     - the global size (or PETSC_DECIDE)
80 - bs    - the block size (or PETSC_DECIDE)
81 
82   Output Parameters:
83 . map - the new PetscLayout
84 
85   Level: advanced
86 
87   Notes:
88 $ PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
89   is a shorthand for
90 .vb
91   PetscLayoutCreate(comm,&layout);
92   PetscLayoutSetLocalSize(layout,n);
93   PetscLayoutSetSize(layout,N);
94   PetscLayoutSetBlockSize(layout,bs);
95   PetscLayoutSetUp(layout);
96 .ve
97 
98 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
99           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromRanges()`
100 
101 @*/
102 PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm,PetscInt n,PetscInt N,PetscInt bs,PetscLayout *map)
103 {
104   PetscFunctionBegin;
105   PetscCall(PetscLayoutCreate(comm, map));
106   PetscCall(PetscLayoutSetLocalSize(*map, n));
107   PetscCall(PetscLayoutSetSize(*map, N));
108   PetscCall(PetscLayoutSetBlockSize(*map, bs));
109   PetscCall(PetscLayoutSetUp(*map));
110   PetscFunctionReturn(0);
111 }
112 
113 /*@
114   PetscLayoutDestroy - Frees a map object and frees its range if that exists.
115 
116   Collective
117 
118   Input Parameters:
119 . map - the PetscLayout
120 
121   Level: developer
122 
123   Note:
124   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
125   recommended they not be used in user codes unless you really gain something in their use.
126 
127 .seealso: `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutCreate()`,
128           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`
129 
130 @*/
131 PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
132 {
133   PetscFunctionBegin;
134   if (!*map) PetscFunctionReturn(0);
135   if (!(*map)->refcnt--) {
136     if ((*map)->range_alloc) PetscCall(PetscFree((*map)->range));
137     PetscCall(ISLocalToGlobalMappingDestroy(&(*map)->mapping));
138     PetscCall(PetscFree((*map)));
139   }
140   *map = NULL;
141   PetscFunctionReturn(0);
142 }
143 
144 /*@
145   PetscLayoutCreateFromRanges - Creates a new PetscLayout with the given ownership ranges and sets it up.
146 
147   Collective
148 
149   Input Parameters:
150 + comm  - the MPI communicator
151 . range - the array of ownership ranges for each rank with length commsize+1
152 . mode  - the copy mode for range
153 - bs    - the block size (or PETSC_DECIDE)
154 
155   Output Parameters:
156 . newmap - the new PetscLayout
157 
158   Level: developer
159 
160 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
161           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromSizes()`
162 
163 @*/
164 PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm,const PetscInt range[],PetscCopyMode mode,PetscInt bs,PetscLayout *newmap)
165 {
166   PetscLayout    map;
167   PetscMPIInt    rank;
168 
169   PetscFunctionBegin;
170   PetscCallMPI(MPI_Comm_rank(comm, &rank));
171   PetscCall(PetscLayoutCreate(comm, &map));
172   PetscCall(PetscLayoutSetBlockSize(map, bs));
173   switch (mode) {
174     case PETSC_COPY_VALUES:
175       PetscCall(PetscMalloc1(map->size+1, &map->range));
176       PetscCall(PetscArraycpy(map->range, range, map->size+1));
177       break;
178     case PETSC_USE_POINTER:
179       map->range_alloc = PETSC_FALSE;
180     default:
181       map->range = (PetscInt*) range;
182       break;
183   }
184   map->rstart = map->range[rank];
185   map->rend   = map->range[rank+1];
186   map->n      = map->rend - map->rstart;
187   map->N      = map->range[map->size];
188   if (PetscDefined(USE_DEBUG)) {  /* just check that n, N and bs are consistent */
189     PetscInt tmp;
190     PetscCall(MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm));
191     PetscCheck(tmp == map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Sum of local lengths %" PetscInt_FMT " does not equal global length %" PetscInt_FMT ", my local length %" PetscInt_FMT ".\nThe provided PetscLayout is wrong.",tmp,map->N,map->n);
192     if (map->bs > 1) {
193       PetscCheck(map->n % map->bs == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT,map->n,map->bs);
194     }
195     if (map->bs > 1) {
196       PetscCheck(map->N % map->bs == 0,map->comm,PETSC_ERR_PLIB,"Global size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT,map->N,map->bs);
197     }
198   }
199   /* lock the layout */
200   map->setupcalled = PETSC_TRUE;
201   map->oldn = map->n;
202   map->oldN = map->N;
203   map->oldbs = map->bs;
204   *newmap = map;
205   PetscFunctionReturn(0);
206 }
207 
208 /*@
209   PetscLayoutSetUp - given a map where you have set either the global or local
210                      size sets up the map so that it may be used.
211 
212   Collective
213 
214   Input Parameters:
215 . map - pointer to the map
216 
217   Level: developer
218 
219   Notes:
220     Typical calling sequence
221 $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
222 $ PetscLayoutSetBlockSize(PetscLayout,1);
223 $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
224 $ PetscLayoutSetUp(PetscLayout);
225 $ PetscLayoutGetSize(PetscLayout,PetscInt *);
226 
227   If range exists, and local size is not set, everything gets computed from the range.
228 
229   If the local size, global size are already set and range exists then this does nothing.
230 
231 .seealso: `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
232           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`
233 @*/
234 PetscErrorCode PetscLayoutSetUp(PetscLayout map)
235 {
236   PetscMPIInt    rank;
237   PetscInt       p;
238 
239   PetscFunctionBegin;
240   PetscCheck(!map->setupcalled || !(map->n != map->oldn || map->N != map->oldN),map->comm,PETSC_ERR_ARG_WRONGSTATE,"Layout is already setup with (local=%" PetscInt_FMT ",global=%" PetscInt_FMT "), cannot call setup again with (local=%" PetscInt_FMT ",global=%" PetscInt_FMT ")", map->oldn, map->oldN, map->n, map->N);
241   if (map->setupcalled) PetscFunctionReturn(0);
242 
243   if (map->n > 0 && map->bs > 1) {
244     PetscCheck(map->n % map->bs == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT,map->n,map->bs);
245   }
246   if (map->N > 0 && map->bs > 1) {
247     PetscCheck(map->N % map->bs == 0,map->comm,PETSC_ERR_PLIB,"Global size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT,map->N,map->bs);
248   }
249 
250   PetscCallMPI(MPI_Comm_rank(map->comm, &rank));
251   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
252   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
253   PetscCall(PetscSplitOwnership(map->comm,&map->n,&map->N));
254   map->n = map->n*PetscAbs(map->bs);
255   map->N = map->N*PetscAbs(map->bs);
256   if (!map->range) {
257     PetscCall(PetscMalloc1(map->size+1, &map->range));
258   }
259   PetscCallMPI(MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm));
260 
261   map->range[0] = 0;
262   for (p = 2; p <= map->size; p++) map->range[p] += map->range[p-1];
263 
264   map->rstart = map->range[rank];
265   map->rend   = map->range[rank+1];
266 
267   /* lock the layout */
268   map->setupcalled = PETSC_TRUE;
269   map->oldn = map->n;
270   map->oldN = map->N;
271   map->oldbs = map->bs;
272   PetscFunctionReturn(0);
273 }
274 
275 /*@
276   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
277 
278   Collective on PetscLayout
279 
280   Input Parameter:
281 . in - input PetscLayout to be duplicated
282 
283   Output Parameter:
284 . out - the copy
285 
286   Level: developer
287 
288   Notes:
289     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
290 
291 .seealso: `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()`
292 @*/
293 PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
294 {
295   MPI_Comm       comm = in->comm;
296 
297   PetscFunctionBegin;
298   PetscCall(PetscLayoutDestroy(out));
299   PetscCall(PetscLayoutCreate(comm,out));
300   PetscCall(PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout)));
301   if (in->range) {
302     PetscCall(PetscMalloc1((*out)->size+1,&(*out)->range));
303     PetscCall(PetscArraycpy((*out)->range,in->range,(*out)->size+1));
304   }
305   (*out)->refcnt = 0;
306   PetscFunctionReturn(0);
307 }
308 
309 /*@
310   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
311 
312   Collective on PetscLayout
313 
314   Input Parameter:
315 . in - input PetscLayout to be copied
316 
317   Output Parameter:
318 . out - the reference location
319 
320   Level: developer
321 
322   Notes:
323     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
324 
325   If the out location already contains a PetscLayout it is destroyed
326 
327 .seealso: `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
328 @*/
329 PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
330 {
331   PetscFunctionBegin;
332   in->refcnt++;
333   PetscCall(PetscLayoutDestroy(out));
334   *out = in;
335   PetscFunctionReturn(0);
336 }
337 
338 /*@
339   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
340 
341   Collective on PetscLayout
342 
343   Input Parameters:
344 + in - input PetscLayout
345 - ltog - the local to global mapping
346 
347   Level: developer
348 
349   Notes:
350     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
351 
352   If the ltog location already contains a PetscLayout it is destroyed
353 
354 .seealso: `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
355 @*/
356 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
357 {
358   PetscFunctionBegin;
359   if (ltog) {
360     PetscInt bs;
361 
362     PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog,&bs));
363     PetscCheck(in->bs <= 0 || bs == 1 || in->bs == bs,in->comm,PETSC_ERR_PLIB,"Blocksize of layout %" PetscInt_FMT " must match that of mapping %" PetscInt_FMT " (or the latter must be 1)",in->bs,bs);
364     PetscCall(PetscObjectReference((PetscObject)ltog));
365   }
366   PetscCall(ISLocalToGlobalMappingDestroy(&in->mapping));
367   in->mapping = ltog;
368   PetscFunctionReturn(0);
369 }
370 
371 /*@
372   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
373 
374   Collective on PetscLayout
375 
376   Input Parameters:
377 + map - pointer to the map
378 - n - the local size
379 
380   Level: developer
381 
382   Notes:
383   Call this after the call to PetscLayoutCreate()
384 
385 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
386           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
387 @*/
388 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
389 {
390   PetscFunctionBegin;
391   PetscCheck(map->bs <= 1 || (n % map->bs) == 0,map->comm,PETSC_ERR_ARG_INCOMP,"Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT,n,map->bs);
392   map->n = n;
393   PetscFunctionReturn(0);
394 }
395 
396 /*@C
397      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
398 
399     Not Collective
400 
401    Input Parameters:
402 .    map - pointer to the map
403 
404    Output Parameters:
405 .    n - the local size
406 
407    Level: developer
408 
409     Notes:
410        Call this after the call to PetscLayoutSetUp()
411 
412     Fortran Notes:
413       Not available from Fortran
414 
415 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
416           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
417 
418 @*/
419 PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
420 {
421   PetscFunctionBegin;
422   *n = map->n;
423   PetscFunctionReturn(0);
424 }
425 
426 /*@
427   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
428 
429   Logically Collective on PetscLayout
430 
431   Input Parameters:
432 + map - pointer to the map
433 - n - the global size
434 
435   Level: developer
436 
437   Notes:
438   Call this after the call to PetscLayoutCreate()
439 
440 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
441           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
442 @*/
443 PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
444 {
445   PetscFunctionBegin;
446   map->N = n;
447   PetscFunctionReturn(0);
448 }
449 
450 /*@
451   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
452 
453   Not Collective
454 
455   Input Parameters:
456 . map - pointer to the map
457 
458   Output Parameters:
459 . n - the global size
460 
461   Level: developer
462 
463   Notes:
464   Call this after the call to PetscLayoutSetUp()
465 
466 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
467           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
468 @*/
469 PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
470 {
471   PetscFunctionBegin;
472   *n = map->N;
473   PetscFunctionReturn(0);
474 }
475 
476 /*@
477   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
478 
479   Logically Collective on PetscLayout
480 
481   Input Parameters:
482 + map - pointer to the map
483 - bs - the size
484 
485   Level: developer
486 
487   Notes:
488   Call this after the call to PetscLayoutCreate()
489 
490 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
491           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
492 @*/
493 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
494 {
495   PetscFunctionBegin;
496   if (bs < 0) PetscFunctionReturn(0);
497   PetscCheck(map->n <= 0 || (map->n % bs) == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT,map->n,bs);
498   if (map->mapping) {
499     PetscInt       obs;
500 
501     PetscCall(ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs));
502     if (obs > 1) {
503       PetscCall(ISLocalToGlobalMappingSetBlockSize(map->mapping,bs));
504     }
505   }
506   map->bs = bs;
507   PetscFunctionReturn(0);
508 }
509 
510 /*@
511   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
512 
513   Not Collective
514 
515   Input Parameters:
516 . map - pointer to the map
517 
518   Output Parameters:
519 . bs - the size
520 
521   Level: developer
522 
523   Notes:
524   Call this after the call to PetscLayoutSetUp()
525 
526 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
527           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`
528 @*/
529 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
530 {
531   PetscFunctionBegin;
532   *bs = PetscAbs(map->bs);
533   PetscFunctionReturn(0);
534 }
535 
536 /*@
537   PetscLayoutGetRange - gets the range of values owned by this process
538 
539   Not Collective
540 
541   Input Parameter:
542 . map - pointer to the map
543 
544   Output Parameters:
545 + rstart - first index owned by this process
546 - rend   - one more than the last index owned by this process
547 
548   Level: developer
549 
550   Notes:
551   Call this after the call to PetscLayoutSetUp()
552 
553 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
554           `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
555 @*/
556 PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
557 {
558   PetscFunctionBegin;
559   if (rstart) *rstart = map->rstart;
560   if (rend)   *rend   = map->rend;
561   PetscFunctionReturn(0);
562 }
563 
564 /*@C
565      PetscLayoutGetRanges - gets the range of values owned by all processes
566 
567     Not Collective
568 
569    Input Parameters:
570 .    map - pointer to the map
571 
572    Output Parameters:
573 .    range - start of each processors range of indices (the final entry is one more then the
574              last index on the last process)
575 
576    Level: developer
577 
578     Notes:
579        Call this after the call to PetscLayoutSetUp()
580 
581     Fortran Notes:
582       Not available from Fortran
583 
584 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
585           `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
586 
587 @*/
588 PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
589 {
590   PetscFunctionBegin;
591   *range = map->range;
592   PetscFunctionReturn(0);
593 }
594 
595 /*@
596   PetscLayoutCompare - Compares two layouts
597 
598   Not Collective
599 
600   Input Parameters:
601 + mapa - pointer to the first map
602 - mapb - pointer to the second map
603 
604   Output Parameters:
605 . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
606 
607   Level: beginner
608 
609   Notes:
610 
611 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
612           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
613 @*/
614 PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
615 {
616   PetscFunctionBegin;
617   *congruent = PETSC_FALSE;
618   if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) {
619     PetscCall(PetscArraycmp(mapa->range,mapb->range,mapa->size+1,congruent));
620   }
621   PetscFunctionReturn(0);
622 }
623