Actual source code: pmap.c


  2: /*
  3:    This file contains routines for basic map object implementation.
  4: */

  6: #include <petsc/private/isimpl.h>

  8: /*@
  9:   PetscLayoutCreate - Allocates `PetscLayout` object

 11:   Collective

 13:   Input Parameter:
 14: . comm - the MPI communicator

 16:   Output Parameter:
 17: . map - the new `PetscLayout`

 19:   Level: advanced

 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

 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

 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.

 46: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
 47:           `PetscLayout`, `PetscLayoutDestroy()`,
 48:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`,
 49:           `PetscLayoutCreateFromSizes()`
 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(PETSC_SUCCESS);
 69: }

 71: /*@
 72:   PetscLayoutCreateFromSizes - Allocates `PetscLayout` object and sets the layout sizes, and sets the layout up.

 74:   Collective

 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`)

 82:   Output Parameter:
 83: . map - the new `PetscLayout`

 85:   Level: advanced

 87:   Note:
 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

 98: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
 99:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromRanges()`
100: @*/
101: PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm, PetscInt n, PetscInt N, PetscInt bs, PetscLayout *map)
102: {
103:   PetscFunctionBegin;
104:   PetscCall(PetscLayoutCreate(comm, map));
105:   PetscCall(PetscLayoutSetLocalSize(*map, n));
106:   PetscCall(PetscLayoutSetSize(*map, N));
107:   PetscCall(PetscLayoutSetBlockSize(*map, bs));
108:   PetscCall(PetscLayoutSetUp(*map));
109:   PetscFunctionReturn(PETSC_SUCCESS);
110: }

112: /*@
113:   PetscLayoutDestroy - Frees a `PetscLayout` object and frees its range if that exists.

115:   Collective

117:   Input Parameter:
118: . map - the `PetscLayout`

120:   Level: developer

122: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
123:           `PetscLayout`, `PetscLayoutCreate()`,
124:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`
125: @*/
126: PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
127: {
128:   PetscFunctionBegin;
129:   if (!*map) PetscFunctionReturn(PETSC_SUCCESS);
130:   if (!(*map)->refcnt--) {
131:     if ((*map)->range_alloc) PetscCall(PetscFree((*map)->range));
132:     PetscCall(ISLocalToGlobalMappingDestroy(&(*map)->mapping));
133:     PetscCall(PetscFree((*map)));
134:   }
135:   *map = NULL;
136:   PetscFunctionReturn(PETSC_SUCCESS);
137: }

139: /*@
140:   PetscLayoutCreateFromRanges - Creates a new `PetscLayout` with the given ownership ranges and sets it up.

142:   Collective

144:   Input Parameters:
145: + comm  - the MPI communicator
146: . range - the array of ownership ranges for each rank with length commsize+1
147: . mode  - the copy mode for range
148: - bs    - the block size (or `PETSC_DECIDE`)

150:   Output Parameter:
151: . newmap - the new `PetscLayout`

153:   Level: developer

155: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`,
156:           `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
157:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromSizes()`
158: @*/
159: PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm, const PetscInt range[], PetscCopyMode mode, PetscInt bs, PetscLayout *newmap)
160: {
161:   PetscLayout map;
162:   PetscMPIInt rank;

164:   PetscFunctionBegin;
165:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
166:   PetscCall(PetscLayoutCreate(comm, &map));
167:   PetscCall(PetscLayoutSetBlockSize(map, bs));
168:   switch (mode) {
169:   case PETSC_COPY_VALUES:
170:     PetscCall(PetscMalloc1(map->size + 1, &map->range));
171:     PetscCall(PetscArraycpy(map->range, range, map->size + 1));
172:     break;
173:   case PETSC_USE_POINTER:
174:     map->range_alloc = PETSC_FALSE;
175:     break;
176:   default:
177:     map->range = (PetscInt *)range;
178:     break;
179:   }
180:   map->rstart = map->range[rank];
181:   map->rend   = map->range[rank + 1];
182:   map->n      = map->rend - map->rstart;
183:   map->N      = map->range[map->size];
184:   if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */
185:     PetscInt tmp;
186:     PetscCall(MPIU_Allreduce(&map->n, &tmp, 1, MPIU_INT, MPI_SUM, map->comm));
187:     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);
188:     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);
189:     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);
190:   }
191:   /* lock the layout */
192:   map->setupcalled = PETSC_TRUE;
193:   map->oldn        = map->n;
194:   map->oldN        = map->N;
195:   map->oldbs       = map->bs;
196:   *newmap          = map;
197:   PetscFunctionReturn(PETSC_SUCCESS);
198: }

200: /*@
201:   PetscLayoutSetUp - given a map where you have set either the global or local
202:                      size sets up the map so that it may be used.

204:   Collective

206:   Input Parameter:
207: . map - pointer to the map

209:   Level: developer

211:   Notes:
212:     Typical calling sequence
213: .vb
214:   PetscLayoutCreate(MPI_Comm,PetscLayout *);
215:   PetscLayoutSetBlockSize(PetscLayout,1);
216:   PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
217:   PetscLayoutSetUp(PetscLayout);
218:   PetscLayoutGetSize(PetscLayout,PetscInt *);
219: .ve

221:   If range exists, and local size is not set, everything gets computed from the range.

223:   If the local size, global size are already set and range exists then this does nothing.

225: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
226:           `PetscLayout`, `PetscLayoutDestroy()`,
227:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`, `PetscSplitOwnership()`
228: @*/
229: PetscErrorCode PetscLayoutSetUp(PetscLayout map)
230: {
231:   PetscMPIInt rank;
232:   PetscInt    p;

234:   PetscFunctionBegin;
235:   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 ")",
236:              map->oldn, map->oldN, map->n, map->N);
237:   if (map->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);

239:   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);
240:   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);

242:   PetscCallMPI(MPI_Comm_rank(map->comm, &rank));
243:   if (map->n > 0) map->n = map->n / PetscAbs(map->bs);
244:   if (map->N > 0) map->N = map->N / PetscAbs(map->bs);
245:   PetscCall(PetscSplitOwnership(map->comm, &map->n, &map->N));
246:   map->n = map->n * PetscAbs(map->bs);
247:   map->N = map->N * PetscAbs(map->bs);
248:   if (!map->range) PetscCall(PetscMalloc1(map->size + 1, &map->range));
249:   PetscCallMPI(MPI_Allgather(&map->n, 1, MPIU_INT, map->range + 1, 1, MPIU_INT, map->comm));

251:   map->range[0] = 0;
252:   for (p = 2; p <= map->size; p++) map->range[p] += map->range[p - 1];

254:   map->rstart = map->range[rank];
255:   map->rend   = map->range[rank + 1];

257:   /* lock the layout */
258:   map->setupcalled = PETSC_TRUE;
259:   map->oldn        = map->n;
260:   map->oldN        = map->N;
261:   map->oldbs       = map->bs;
262:   PetscFunctionReturn(PETSC_SUCCESS);
263: }

265: /*@
266:   PetscLayoutDuplicate - creates a new `PetscLayout` with the same information as a given one. If the `PetscLayout` already exists it is destroyed first.

268:   Collective

270:   Input Parameter:
271: . in - input `PetscLayout` to be duplicated

273:   Output Parameter:
274: . out - the copy

276:   Level: developer

278:   Note:
279:     `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`

281: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()`
282: @*/
283: PetscErrorCode PetscLayoutDuplicate(PetscLayout in, PetscLayout *out)
284: {
285:   MPI_Comm comm = in->comm;

287:   PetscFunctionBegin;
288:   PetscCall(PetscLayoutDestroy(out));
289:   PetscCall(PetscLayoutCreate(comm, out));
290:   PetscCall(PetscMemcpy(*out, in, sizeof(struct _n_PetscLayout)));
291:   if (in->range) {
292:     PetscCall(PetscMalloc1((*out)->size + 1, &(*out)->range));
293:     PetscCall(PetscArraycpy((*out)->range, in->range, (*out)->size + 1));
294:   }
295:   (*out)->refcnt = 0;
296:   PetscFunctionReturn(PETSC_SUCCESS);
297: }

299: /*@
300:   PetscLayoutReference - Causes a PETSc `Vec` or `Mat` to share a `PetscLayout` with one that already exists.

302:   Collective

304:   Input Parameter:
305: . in - input `PetscLayout` to be copied

307:   Output Parameter:
308: . out - the reference location

310:   Level: developer

312:   Notes:
313:   `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`

315:   If the out location already contains a `PetscLayout` it is destroyed

317: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
318: @*/
319: PetscErrorCode PetscLayoutReference(PetscLayout in, PetscLayout *out)
320: {
321:   PetscFunctionBegin;
322:   in->refcnt++;
323:   PetscCall(PetscLayoutDestroy(out));
324:   *out = in;
325:   PetscFunctionReturn(PETSC_SUCCESS);
326: }

328: /*@
329:   PetscLayoutSetISLocalToGlobalMapping - sets a `ISLocalGlobalMapping` into a `PetscLayout`

331:   Collective

333:   Input Parameters:
334: + in - input `PetscLayout`
335: - ltog - the local to global mapping

337:   Level: developer

339:   Notes:
340:   `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`

342:   If the `PetscLayout` already contains a `ISLocalGlobalMapping` it is destroyed

344: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
345: @*/
346: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in, ISLocalToGlobalMapping ltog)
347: {
348:   PetscFunctionBegin;
349:   if (ltog) {
350:     PetscInt bs;

352:     PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog, &bs));
353:     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);
354:     PetscCall(PetscObjectReference((PetscObject)ltog));
355:   }
356:   PetscCall(ISLocalToGlobalMappingDestroy(&in->mapping));
357:   in->mapping = ltog;
358:   PetscFunctionReturn(PETSC_SUCCESS);
359: }

361: /*@
362:   PetscLayoutSetLocalSize - Sets the local size for a `PetscLayout` object.

364:   Collective

366:   Input Parameters:
367: + map - pointer to the map
368: - n - the local size

370:   Level: developer

372: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
373:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
374: @*/
375: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map, PetscInt n)
376: {
377:   PetscFunctionBegin;
378:   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);
379:   map->n = n;
380:   PetscFunctionReturn(PETSC_SUCCESS);
381: }

383: /*@
384:      PetscLayoutGetLocalSize - Gets the local size for a `PetscLayout` object.

386:     Not Collective

388:    Input Parameter:
389: .    map - pointer to the map

391:    Output Parameter:
392: .    n - the local size

394:    Level: developer

396:     Note:
397:     Call this after the call to `PetscLayoutSetUp()`

399: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
400:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
401: @*/
402: PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map, PetscInt *n)
403: {
404:   PetscFunctionBegin;
405:   *n = map->n;
406:   PetscFunctionReturn(PETSC_SUCCESS);
407: }

409: /*@
410:   PetscLayoutSetSize - Sets the global size for a `PetscLayout` object.

412:   Logically Collective

414:   Input Parameters:
415: + map - pointer to the map
416: - n - the global size

418:   Level: developer

420: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
421:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
422: @*/
423: PetscErrorCode PetscLayoutSetSize(PetscLayout map, PetscInt n)
424: {
425:   PetscFunctionBegin;
426:   map->N = n;
427:   PetscFunctionReturn(PETSC_SUCCESS);
428: }

430: /*@
431:   PetscLayoutGetSize - Gets the global size for a `PetscLayout` object.

433:   Not Collective

435:   Input Parameter:
436: . map - pointer to the map

438:   Output Parameter:
439: . n - the global size

441:   Level: developer

443:   Note:
444:   Call this after the call to `PetscLayoutSetUp()`

446: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
447:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
448: @*/
449: PetscErrorCode PetscLayoutGetSize(PetscLayout map, PetscInt *n)
450: {
451:   PetscFunctionBegin;
452:   *n = map->N;
453:   PetscFunctionReturn(PETSC_SUCCESS);
454: }

456: /*@
457:   PetscLayoutSetBlockSize - Sets the block size for a `PetscLayout` object.

459:   Logically Collective

461:   Input Parameters:
462: + map - pointer to the map
463: - bs - the size

465:   Level: developer

467: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
468:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
469: @*/
470: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map, PetscInt bs)
471: {
472:   PetscFunctionBegin;
473:   if (bs < 0) PetscFunctionReturn(PETSC_SUCCESS);
474:   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);
475:   if (map->mapping) {
476:     PetscInt obs;

478:     PetscCall(ISLocalToGlobalMappingGetBlockSize(map->mapping, &obs));
479:     if (obs > 1) PetscCall(ISLocalToGlobalMappingSetBlockSize(map->mapping, bs));
480:   }
481:   map->bs = bs;
482:   PetscFunctionReturn(PETSC_SUCCESS);
483: }

485: /*@
486:   PetscLayoutGetBlockSize - Gets the block size for a `PetscLayout` object.

488:   Not Collective

490:   Input Parameter:
491: . map - pointer to the map

493:   Output Parameter:
494: . bs - the size

496:   Level: developer

498:   Notes:
499:   Call this after the call to `PetscLayoutSetUp()`

501: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
502:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`
503: @*/
504: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map, PetscInt *bs)
505: {
506:   PetscFunctionBegin;
507:   *bs = PetscAbs(map->bs);
508:   PetscFunctionReturn(PETSC_SUCCESS);
509: }

511: /*@
512:   PetscLayoutGetRange - gets the range of values owned by this process

514:   Not Collective

516:   Input Parameter:
517: . map - pointer to the map

519:   Output Parameters:
520: + rstart - first index owned by this process
521: - rend   - one more than the last index owned by this process

523:   Level: developer

525:   Note:
526:   Call this after the call to `PetscLayoutSetUp()`

528: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
529:           `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
530: @*/
531: PetscErrorCode PetscLayoutGetRange(PetscLayout map, PetscInt *rstart, PetscInt *rend)
532: {
533:   PetscFunctionBegin;
534:   if (rstart) *rstart = map->rstart;
535:   if (rend) *rend = map->rend;
536:   PetscFunctionReturn(PETSC_SUCCESS);
537: }

539: /*@C
540:      PetscLayoutGetRanges - gets the ranges of values owned by all processes

542:     Not Collective

544:    Input Parameter:
545: .    map - pointer to the map

547:    Output Parameter:
548: .    range - start of each processors range of indices (the final entry is one more than the
549:              last index on the last process)

551:    Level: developer

553:     Note:
554:     Call this after the call to `PetscLayoutSetUp()`

556:     Fortran Note:
557:     In Fortran, use PetscLayoutGetRangesF90()

559: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
560:           `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
561: @*/
562: PetscErrorCode PetscLayoutGetRanges(PetscLayout map, const PetscInt *range[])
563: {
564:   PetscFunctionBegin;
565:   *range = map->range;
566:   PetscFunctionReturn(PETSC_SUCCESS);
567: }

569: /*@
570:   PetscLayoutCompare - Compares two layouts

572:   Not Collective

574:   Input Parameters:
575: + mapa - pointer to the first map
576: - mapb - pointer to the second map

578:   Output Parameter:
579: . congruent - `PETSC_TRUE` if the two layouts are congruent, `PETSC_FALSE` otherwise

581:   Level: beginner

583: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
584:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
585: @*/
586: PetscErrorCode PetscLayoutCompare(PetscLayout mapa, PetscLayout mapb, PetscBool *congruent)
587: {
588:   PetscFunctionBegin;
589:   *congruent = PETSC_FALSE;
590:   if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) PetscCall(PetscArraycmp(mapa->range, mapb->range, mapa->size + 1, congruent));
591:   PetscFunctionReturn(PETSC_SUCCESS);
592: }