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