xref: /petsc/src/vec/is/utils/pmap.c (revision 89928cc5142e867cb7b0dd1ff74e0acffcd6b4b5)
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 implementations; 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 implementations; 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     break;
181   default:
182     map->range = (PetscInt *)range;
183     break;
184   }
185   map->rstart = map->range[rank];
186   map->rend   = map->range[rank + 1];
187   map->n      = map->rend - map->rstart;
188   map->N      = map->range[map->size];
189   if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */
190     PetscInt tmp;
191     PetscCall(MPIU_Allreduce(&map->n, &tmp, 1, MPIU_INT, MPI_SUM, map->comm));
192     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);
193     if (map->bs > 1) 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     if (map->bs > 1) 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);
195   }
196   /* lock the layout */
197   map->setupcalled = PETSC_TRUE;
198   map->oldn        = map->n;
199   map->oldN        = map->N;
200   map->oldbs       = map->bs;
201   *newmap          = map;
202   PetscFunctionReturn(0);
203 }
204 
205 /*@
206   PetscLayoutSetUp - given a map where you have set either the global or local
207                      size sets up the map so that it may be used.
208 
209   Collective
210 
211   Input Parameters:
212 . map - pointer to the map
213 
214   Level: developer
215 
216   Notes:
217     Typical calling sequence
218 $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
219 $ PetscLayoutSetBlockSize(PetscLayout,1);
220 $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
221 $ PetscLayoutSetUp(PetscLayout);
222 $ PetscLayoutGetSize(PetscLayout,PetscInt *);
223 
224   If range exists, and local size is not set, everything gets computed from the range.
225 
226   If the local size, global size are already set and range exists then this does nothing.
227 
228 .seealso: `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
229           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`, `PetscSplitOwnership()`
230 @*/
231 PetscErrorCode PetscLayoutSetUp(PetscLayout map)
232 {
233   PetscMPIInt rank;
234   PetscInt    p;
235 
236   PetscFunctionBegin;
237   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 ")",
238              map->oldn, map->oldN, map->n, map->N);
239   if (map->setupcalled) PetscFunctionReturn(0);
240 
241   if (map->n > 0 && map->bs > 1) 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);
242   if (map->N > 0 && map->bs > 1) 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);
243 
244   PetscCallMPI(MPI_Comm_rank(map->comm, &rank));
245   if (map->n > 0) map->n = map->n / PetscAbs(map->bs);
246   if (map->N > 0) map->N = map->N / PetscAbs(map->bs);
247   PetscCall(PetscSplitOwnership(map->comm, &map->n, &map->N));
248   map->n = map->n * PetscAbs(map->bs);
249   map->N = map->N * PetscAbs(map->bs);
250   if (!map->range) PetscCall(PetscMalloc1(map->size + 1, &map->range));
251   PetscCallMPI(MPI_Allgather(&map->n, 1, MPIU_INT, map->range + 1, 1, MPIU_INT, map->comm));
252 
253   map->range[0] = 0;
254   for (p = 2; p <= map->size; p++) map->range[p] += map->range[p - 1];
255 
256   map->rstart = map->range[rank];
257   map->rend   = map->range[rank + 1];
258 
259   /* lock the layout */
260   map->setupcalled = PETSC_TRUE;
261   map->oldn        = map->n;
262   map->oldN        = map->N;
263   map->oldbs       = map->bs;
264   PetscFunctionReturn(0);
265 }
266 
267 /*@
268   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
269 
270   Collective on PetscLayout
271 
272   Input Parameter:
273 . in - input PetscLayout to be duplicated
274 
275   Output Parameter:
276 . out - the copy
277 
278   Level: developer
279 
280   Notes:
281     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
282 
283 .seealso: `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()`
284 @*/
285 PetscErrorCode PetscLayoutDuplicate(PetscLayout in, PetscLayout *out)
286 {
287   MPI_Comm comm = in->comm;
288 
289   PetscFunctionBegin;
290   PetscCall(PetscLayoutDestroy(out));
291   PetscCall(PetscLayoutCreate(comm, out));
292   PetscCall(PetscMemcpy(*out, in, sizeof(struct _n_PetscLayout)));
293   if (in->range) {
294     PetscCall(PetscMalloc1((*out)->size + 1, &(*out)->range));
295     PetscCall(PetscArraycpy((*out)->range, in->range, (*out)->size + 1));
296   }
297   (*out)->refcnt = 0;
298   PetscFunctionReturn(0);
299 }
300 
301 /*@
302   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
303 
304   Collective on PetscLayout
305 
306   Input Parameter:
307 . in - input PetscLayout to be copied
308 
309   Output Parameter:
310 . out - the reference location
311 
312   Level: developer
313 
314   Notes:
315     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
316 
317   If the out location already contains a PetscLayout it is destroyed
318 
319 .seealso: `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
320 @*/
321 PetscErrorCode PetscLayoutReference(PetscLayout in, PetscLayout *out)
322 {
323   PetscFunctionBegin;
324   in->refcnt++;
325   PetscCall(PetscLayoutDestroy(out));
326   *out = in;
327   PetscFunctionReturn(0);
328 }
329 
330 /*@
331   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
332 
333   Collective on PetscLayout
334 
335   Input Parameters:
336 + in - input PetscLayout
337 - ltog - the local to global mapping
338 
339   Level: developer
340 
341   Notes:
342     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
343 
344   If the ltog location already contains a PetscLayout it is destroyed
345 
346 .seealso: `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
347 @*/
348 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in, ISLocalToGlobalMapping ltog)
349 {
350   PetscFunctionBegin;
351   if (ltog) {
352     PetscInt bs;
353 
354     PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog, &bs));
355     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);
356     PetscCall(PetscObjectReference((PetscObject)ltog));
357   }
358   PetscCall(ISLocalToGlobalMappingDestroy(&in->mapping));
359   in->mapping = ltog;
360   PetscFunctionReturn(0);
361 }
362 
363 /*@
364   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
365 
366   Collective on PetscLayout
367 
368   Input Parameters:
369 + map - pointer to the map
370 - n - the local size
371 
372   Level: developer
373 
374   Notes:
375   Call this after the call to PetscLayoutCreate()
376 
377 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
378           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
379 @*/
380 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map, PetscInt n)
381 {
382   PetscFunctionBegin;
383   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);
384   map->n = n;
385   PetscFunctionReturn(0);
386 }
387 
388 /*@
389      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
390 
391     Not Collective
392 
393    Input Parameters:
394 .    map - pointer to the map
395 
396    Output Parameters:
397 .    n - the local size
398 
399    Level: developer
400 
401     Notes:
402        Call this after the call to PetscLayoutSetUp()
403 
404     Fortran Notes:
405       Not available from Fortran
406 
407 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
408           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
409 
410 @*/
411 PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map, PetscInt *n)
412 {
413   PetscFunctionBegin;
414   *n = map->n;
415   PetscFunctionReturn(0);
416 }
417 
418 /*@
419   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
420 
421   Logically Collective on PetscLayout
422 
423   Input Parameters:
424 + map - pointer to the map
425 - n - the global size
426 
427   Level: developer
428 
429   Notes:
430   Call this after the call to PetscLayoutCreate()
431 
432 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
433           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
434 @*/
435 PetscErrorCode PetscLayoutSetSize(PetscLayout map, PetscInt n)
436 {
437   PetscFunctionBegin;
438   map->N = n;
439   PetscFunctionReturn(0);
440 }
441 
442 /*@
443   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
444 
445   Not Collective
446 
447   Input Parameters:
448 . map - pointer to the map
449 
450   Output Parameters:
451 . n - the global size
452 
453   Level: developer
454 
455   Notes:
456   Call this after the call to PetscLayoutSetUp()
457 
458 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
459           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
460 @*/
461 PetscErrorCode PetscLayoutGetSize(PetscLayout map, PetscInt *n)
462 {
463   PetscFunctionBegin;
464   *n = map->N;
465   PetscFunctionReturn(0);
466 }
467 
468 /*@
469   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
470 
471   Logically Collective on PetscLayout
472 
473   Input Parameters:
474 + map - pointer to the map
475 - bs - the size
476 
477   Level: developer
478 
479   Notes:
480   Call this after the call to PetscLayoutCreate()
481 
482 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
483           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
484 @*/
485 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map, PetscInt bs)
486 {
487   PetscFunctionBegin;
488   if (bs < 0) PetscFunctionReturn(0);
489   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);
490   if (map->mapping) {
491     PetscInt obs;
492 
493     PetscCall(ISLocalToGlobalMappingGetBlockSize(map->mapping, &obs));
494     if (obs > 1) PetscCall(ISLocalToGlobalMappingSetBlockSize(map->mapping, bs));
495   }
496   map->bs = bs;
497   PetscFunctionReturn(0);
498 }
499 
500 /*@
501   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
502 
503   Not Collective
504 
505   Input Parameters:
506 . map - pointer to the map
507 
508   Output Parameters:
509 . bs - the size
510 
511   Level: developer
512 
513   Notes:
514   Call this after the call to PetscLayoutSetUp()
515 
516 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
517           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`
518 @*/
519 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map, PetscInt *bs)
520 {
521   PetscFunctionBegin;
522   *bs = PetscAbs(map->bs);
523   PetscFunctionReturn(0);
524 }
525 
526 /*@
527   PetscLayoutGetRange - gets the range of values owned by this process
528 
529   Not Collective
530 
531   Input Parameter:
532 . map - pointer to the map
533 
534   Output Parameters:
535 + rstart - first index owned by this process
536 - rend   - one more than the last index owned by this process
537 
538   Level: developer
539 
540   Notes:
541   Call this after the call to PetscLayoutSetUp()
542 
543 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
544           `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
545 @*/
546 PetscErrorCode PetscLayoutGetRange(PetscLayout map, PetscInt *rstart, PetscInt *rend)
547 {
548   PetscFunctionBegin;
549   if (rstart) *rstart = map->rstart;
550   if (rend) *rend = map->rend;
551   PetscFunctionReturn(0);
552 }
553 
554 /*@C
555      PetscLayoutGetRanges - gets the range of values owned by all processes
556 
557     Not Collective
558 
559    Input Parameters:
560 .    map - pointer to the map
561 
562    Output Parameters:
563 .    range - start of each processors range of indices (the final entry is one more than the
564              last index on the last process)
565 
566    Level: developer
567 
568     Notes:
569        Call this after the call to PetscLayoutSetUp()
570 
571     Fortran Notes:
572       Not available from Fortran
573 
574 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
575           `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
576 
577 @*/
578 PetscErrorCode PetscLayoutGetRanges(PetscLayout map, const PetscInt *range[])
579 {
580   PetscFunctionBegin;
581   *range = map->range;
582   PetscFunctionReturn(0);
583 }
584 
585 /*@
586   PetscLayoutCompare - Compares two layouts
587 
588   Not Collective
589 
590   Input Parameters:
591 + mapa - pointer to the first map
592 - mapb - pointer to the second map
593 
594   Output Parameters:
595 . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
596 
597   Level: beginner
598 
599   Notes:
600 
601 .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
602           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
603 @*/
604 PetscErrorCode PetscLayoutCompare(PetscLayout mapa, PetscLayout mapb, PetscBool *congruent)
605 {
606   PetscFunctionBegin;
607   *congruent = PETSC_FALSE;
608   if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) PetscCall(PetscArraycmp(mapa->range, mapb->range, mapa->size + 1, congruent));
609   PetscFunctionReturn(0);
610 }
611