Actual source code: pmap.c
1: /*
2: This file contains routines for basic map object implementation.
3: */
5: #include <petsc/private/isimpl.h>
7: /*@
8: PetscLayoutCreate - Allocates `PetscLayout` object
10: Collective
12: Input Parameter:
13: . comm - the MPI communicator
15: Output Parameter:
16: . map - the new `PetscLayout`
18: Level: advanced
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
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
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.
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: }
70: /*@
71: PetscLayoutCreateFromSizes - Allocates `PetscLayout` object and sets the layout sizes, and sets the layout up.
73: Collective
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`)
81: Output Parameter:
82: . map - the new `PetscLayout`
84: Level: advanced
86: Note:
87: .vb
88: PetscLayoutCreateFromSizes(comm, n, N, bs, &layout);
89: .ve
90: is a shorthand for
91: .vb
92: PetscLayoutCreate(comm, &layout);
93: PetscLayoutSetLocalSize(layout, n);
94: PetscLayoutSetSize(layout, N);
95: PetscLayoutSetBlockSize(layout, bs);
96: PetscLayoutSetUp(layout);
97: .ve
99: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
100: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromRanges()`
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(PETSC_SUCCESS);
111: }
113: /*@
114: PetscLayoutDestroy - Frees a `PetscLayout` object and frees its range if that exists.
116: Collective
118: Input Parameter:
119: . map - the `PetscLayout`
121: Level: developer
123: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
124: `PetscLayout`, `PetscLayoutCreate()`,
125: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`
126: @*/
127: PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
128: {
129: PetscFunctionBegin;
130: if (!*map) PetscFunctionReturn(PETSC_SUCCESS);
131: if (!(*map)->refcnt--) {
132: if ((*map)->range_alloc) PetscCall(PetscFree((*map)->range));
133: PetscCall(ISLocalToGlobalMappingDestroy(&(*map)->mapping));
134: PetscCall(PetscFree(*map));
135: }
136: *map = NULL;
137: PetscFunctionReturn(PETSC_SUCCESS);
138: }
140: /*@
141: PetscLayoutCreateFromRanges - Creates a new `PetscLayout` with the given ownership ranges and sets it up.
143: Collective
145: Input Parameters:
146: + comm - the MPI communicator
147: . range - the array of ownership ranges for each rank with length commsize+1
148: . mode - the copy mode for range
149: - bs - the block size (or `PETSC_DECIDE`)
151: Output Parameter:
152: . newmap - the new `PetscLayout`
154: Level: developer
156: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`,
157: `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
158: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromSizes()`
159: @*/
160: PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm, const PetscInt range[], PetscCopyMode mode, PetscInt bs, PetscLayout *newmap)
161: {
162: PetscLayout map;
163: PetscMPIInt rank;
165: PetscFunctionBegin;
166: PetscCallMPI(MPI_Comm_rank(comm, &rank));
167: PetscCall(PetscLayoutCreate(comm, &map));
168: PetscCall(PetscLayoutSetBlockSize(map, bs));
169: switch (mode) {
170: case PETSC_COPY_VALUES:
171: PetscCall(PetscMalloc1(map->size + 1, &map->range));
172: PetscCall(PetscArraycpy(map->range, range, map->size + 1));
173: break;
174: case PETSC_USE_POINTER:
175: map->range_alloc = PETSC_FALSE; /* fall through */
176: case PETSC_OWN_POINTER:
177: map->range = (PetscInt *)range;
178: break;
179: default:
180: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Received invalid PetscCopyMode somehow");
181: }
182: map->rstart = map->range[rank];
183: map->rend = map->range[rank + 1];
184: map->n = map->rend - map->rstart;
185: map->N = map->range[map->size] - map->range[0];
186: if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */
187: PetscInt tmp;
188: PetscCallMPI(MPIU_Allreduce(&map->n, &tmp, 1, MPIU_INT, MPI_SUM, map->comm));
189: 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 ". The provided PetscLayout is wrong.", tmp, map->N, map->n);
190: 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);
191: 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);
192: }
193: /* lock the layout */
194: map->setupcalled = PETSC_TRUE;
195: map->oldn = map->n;
196: map->oldN = map->N;
197: map->oldbs = map->bs;
198: *newmap = map;
199: PetscFunctionReturn(PETSC_SUCCESS);
200: }
202: /*@
203: PetscLayoutSetUp - given a map where you have set either the global or local
204: size sets up the map so that it may be used.
206: Collective
208: Input Parameter:
209: . map - pointer to the map
211: Level: developer
213: Notes:
214: Typical calling sequence
215: .vb
216: PetscLayoutCreate(MPI_Comm,PetscLayout *);
217: PetscLayoutSetBlockSize(PetscLayout,1);
218: PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
219: PetscLayoutSetUp(PetscLayout);
220: PetscLayoutGetSize(PetscLayout,PetscInt *);
221: .ve
223: If range exists, and local size is not set, everything gets computed from the range.
225: If the local size, global size are already set and range exists then this does nothing.
227: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
228: `PetscLayout`, `PetscLayoutDestroy()`,
229: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`, `PetscSplitOwnership()`
230: @*/
231: PetscErrorCode PetscLayoutSetUp(PetscLayout map)
232: {
233: PetscMPIInt rank;
235: PetscFunctionBegin;
236: 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 ")",
237: map->oldn, map->oldN, map->n, map->N);
238: if (map->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
240: PetscCheck(map->n < 0 || 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);
241: PetscCheck(map->N < 0 || 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: PetscCallMPI(MPI_Comm_rank(map->comm, &rank));
244: if (map->n > 0) map->n = map->n / map->bs;
245: if (map->N > 0) map->N = map->N / map->bs;
246: PetscCall(PetscSplitOwnership(map->comm, &map->n, &map->N));
247: map->n = map->n * map->bs;
248: map->N = map->N * map->bs;
249: if (!map->range) PetscCall(PetscMalloc1(map->size + 1, &map->range));
250: PetscCallMPI(MPI_Allgather(&map->n, 1, MPIU_INT, map->range + 1, 1, MPIU_INT, map->comm));
252: map->range[0] = 0;
253: for (PetscInt p = 2; p <= map->size; p++) map->range[p] += map->range[p - 1];
255: map->rstart = map->range[rank];
256: map->rend = map->range[rank + 1];
258: /* lock the layout */
259: map->setupcalled = PETSC_TRUE;
260: map->oldn = map->n;
261: map->oldN = map->N;
262: map->oldbs = map->bs;
263: PetscFunctionReturn(PETSC_SUCCESS);
264: }
266: /*@
267: PetscLayoutDuplicate - creates a new `PetscLayout` with the same information as a given one. If the `PetscLayout` already exists it is destroyed first.
269: Collective
271: Input Parameter:
272: . in - input `PetscLayout` to be duplicated
274: Output Parameter:
275: . out - the copy
277: Level: developer
279: Note:
280: `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
282: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()`
283: @*/
284: PetscErrorCode PetscLayoutDuplicate(PetscLayout in, PetscLayout *out)
285: {
286: MPI_Comm comm = in->comm;
288: PetscFunctionBegin;
289: PetscCall(PetscLayoutDestroy(out));
290: PetscCall(PetscLayoutCreate(comm, out));
291: PetscCall(PetscMemcpy(*out, in, sizeof(struct _n_PetscLayout)));
292: if (in->range) {
293: PetscCall(PetscMalloc1((*out)->size + 1, &(*out)->range));
294: PetscCall(PetscArraycpy((*out)->range, in->range, (*out)->size + 1));
295: }
296: (*out)->refcnt = 0;
297: PetscFunctionReturn(PETSC_SUCCESS);
298: }
300: /*@
301: PetscLayoutReference - Causes a PETSc `Vec` or `Mat` to share a `PetscLayout` with one that already exists.
303: Collective
305: Input Parameter:
306: . in - input `PetscLayout` to be copied
308: Output Parameter:
309: . out - the reference location
311: Level: developer
313: Notes:
314: `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
316: If the out location already contains a `PetscLayout` it is destroyed
318: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
319: @*/
320: PetscErrorCode PetscLayoutReference(PetscLayout in, PetscLayout *out)
321: {
322: PetscFunctionBegin;
323: in->refcnt++;
324: PetscCall(PetscLayoutDestroy(out));
325: *out = in;
326: PetscFunctionReturn(PETSC_SUCCESS);
327: }
329: /*@
330: PetscLayoutGetComm - Gets the MPI communicator associated with the layout.
332: Not Collective
334: Input Parameter:
335: . map - pointer to the map
337: Output Parameter:
338: . comm - the communicator
340: Level: developer
342: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`,
343: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
344: @*/
345: PetscErrorCode PetscLayoutGetComm(PetscLayout map, MPI_Comm *comm)
346: {
347: PetscFunctionBegin;
348: *comm = map->comm;
349: PetscFunctionReturn(PETSC_SUCCESS);
350: }
352: /*@
353: PetscLayoutSetISLocalToGlobalMapping - sets a `ISLocalGlobalMapping` into a `PetscLayout`
355: Collective
357: Input Parameters:
358: + in - input `PetscLayout`
359: - ltog - the local to global mapping
361: Level: developer
363: Notes:
364: `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
366: If the `PetscLayout` already contains a `ISLocalGlobalMapping` it is destroyed
368: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
369: @*/
370: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in, ISLocalToGlobalMapping ltog)
371: {
372: PetscFunctionBegin;
373: if (ltog) {
374: PetscInt bs;
376: PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog, &bs));
377: PetscCheck(in->bs == 1 || 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);
378: }
379: PetscCall(PetscObjectReference((PetscObject)ltog));
380: PetscCall(ISLocalToGlobalMappingDestroy(&in->mapping));
381: in->mapping = ltog;
382: PetscFunctionReturn(PETSC_SUCCESS);
383: }
385: /*@
386: PetscLayoutSetLocalSize - Sets the local size for a `PetscLayout` object.
388: Collective
390: Input Parameters:
391: + map - pointer to the map
392: - n - the local size, pass `PETSC_DECIDE` (the default) to have this value determined by the global size set with `PetscLayoutSetSize()`
394: Level: developer
396: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`,
397: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
398: @*/
399: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map, PetscInt n)
400: {
401: PetscFunctionBegin;
402: PetscCheck(n % map->bs == 0, map->comm, PETSC_ERR_ARG_INCOMP, "Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT, n, map->bs);
403: map->n = n;
404: PetscFunctionReturn(PETSC_SUCCESS);
405: }
407: /*@
408: PetscLayoutGetLocalSize - Gets the local size for a `PetscLayout` object.
410: Not Collective
412: Input Parameter:
413: . map - pointer to the map
415: Output Parameter:
416: . n - the local size
418: Level: developer
420: Note:
421: Call this after the call to `PetscLayoutSetUp()`
423: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`,
424: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
425: @*/
426: PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map, PetscInt *n)
427: {
428: PetscFunctionBegin;
429: *n = map->n;
430: PetscFunctionReturn(PETSC_SUCCESS);
431: }
433: /*@
434: PetscLayoutSetSize - Sets the global size for a `PetscLayout` object.
436: Logically Collective
438: Input Parameters:
439: + map - pointer to the map
440: - n - the global size, use `PETSC_DETERMINE` (the default) to have this value computed as the sum of the local sizes set with `PetscLayoutSetLocalSize()`
442: Level: developer
444: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`,
445: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
446: @*/
447: PetscErrorCode PetscLayoutSetSize(PetscLayout map, PetscInt n)
448: {
449: PetscFunctionBegin;
450: map->N = n;
451: PetscFunctionReturn(PETSC_SUCCESS);
452: }
454: /*@
455: PetscLayoutGetSize - Gets the global size for a `PetscLayout` object.
457: Not Collective
459: Input Parameter:
460: . map - pointer to the map
462: Output Parameter:
463: . n - the global size
465: Level: developer
467: Note:
468: Call this after the call to `PetscLayoutSetUp()`
470: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`,
471: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
472: @*/
473: PetscErrorCode PetscLayoutGetSize(PetscLayout map, PetscInt *n)
474: {
475: PetscFunctionBegin;
476: *n = map->N;
477: PetscFunctionReturn(PETSC_SUCCESS);
478: }
480: /*@
481: PetscLayoutSetBlockSize - Sets the block size for a `PetscLayout` object.
483: Logically Collective
485: Input Parameters:
486: + map - pointer to the map
487: - bs - the size
489: Level: developer
491: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
492: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
493: @*/
494: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map, PetscInt bs)
495: {
496: PetscFunctionBegin;
497: PetscCheck(bs > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Block size %" PetscInt_FMT " must be positive", bs);
498: 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);
499: if (map->mapping) {
500: PetscInt obs;
502: PetscCall(ISLocalToGlobalMappingGetBlockSize(map->mapping, &obs));
503: if (obs > 1) PetscCall(ISLocalToGlobalMappingSetBlockSize(map->mapping, bs));
504: }
505: map->bs = bs;
506: PetscFunctionReturn(PETSC_SUCCESS);
507: }
509: /*@
510: PetscLayoutGetBlockSize - Gets the block size for a `PetscLayout` object.
512: Not Collective
514: Input Parameter:
515: . map - pointer to the map
517: Output Parameter:
518: . bs - the size
520: Level: developer
522: Notes:
523: Call this after the call to `PetscLayoutSetUp()`
525: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`,
526: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`
527: @*/
528: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map, PetscInt *bs)
529: {
530: PetscFunctionBegin;
531: *bs = map->bs;
532: PetscFunctionReturn(PETSC_SUCCESS);
533: }
535: /*@
536: PetscLayoutGetRange - gets the range of values owned by this process
538: Not Collective
540: Input Parameter:
541: . map - pointer to the map
543: Output Parameters:
544: + rstart - first index owned by this process
545: - rend - one more than the last index owned by this process
547: Level: developer
549: Note:
550: Call this after the call to `PetscLayoutSetUp()`
552: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
553: `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()`
554: @*/
555: PetscErrorCode PetscLayoutGetRange(PetscLayout map, PetscInt *rstart, PetscInt *rend)
556: {
557: PetscFunctionBegin;
558: if (rstart) *rstart = map->rstart;
559: if (rend) *rend = map->rend;
560: PetscFunctionReturn(PETSC_SUCCESS);
561: }
563: /*@
564: PetscLayoutGetRanges - gets the ranges of values owned by all processes
566: Not Collective
568: Input Parameter:
569: . map - pointer to the map
571: Output Parameter:
572: . range - start of each processors range of indices (the final entry is one more than the
573: last index on the last process). The length of the array is one more than the number of processes in the MPI
574: communicator owned by `map`
576: Level: developer
578: Note:
579: Call this after the call to `PetscLayoutSetUp()`
581: Fortran Notes:
582: .vb
583: PetscInt, pointer :: range(:)
584: .ve
586: Call `PetscLayoutRestoreRanges()` when no longer needed.
588: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
589: `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()`
590: @*/
591: PetscErrorCode PetscLayoutGetRanges(PetscLayout map, const PetscInt *range[])
592: {
593: PetscFunctionBegin;
594: *range = map->range;
595: PetscFunctionReturn(PETSC_SUCCESS);
596: }
598: /*@
599: PetscLayoutCompare - Compares two layouts
601: Not Collective
603: Input Parameters:
604: + mapa - pointer to the first map
605: - mapb - pointer to the second map
607: Output Parameter:
608: . congruent - `PETSC_TRUE` if the two layouts are congruent, `PETSC_FALSE` otherwise
610: Level: beginner
612: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
613: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
614: @*/
615: PetscErrorCode PetscLayoutCompare(PetscLayout mapa, PetscLayout mapb, PetscBool *congruent)
616: {
617: PetscFunctionBegin;
618: *congruent = PETSC_FALSE;
619: if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) PetscCall(PetscArraycmp(mapa->range, mapb->range, mapa->size + 1, congruent));
620: PetscFunctionReturn(PETSC_SUCCESS);
621: }
623: /*@
624: PetscLayoutFindOwner - Find the owning MPI process for a global index
626: Not Collective; No Fortran Support
628: Input Parameters:
629: + map - the layout
630: - idx - global index to find the owner of
632: Output Parameter:
633: . owner - the owning rank
635: Level: developer
637: .seealso: `PetscLayout`, `PetscLayoutFindOwnerIndex()`
638: @*/
639: PetscErrorCode PetscLayoutFindOwner(PetscLayout map, PetscInt idx, PetscMPIInt *owner)
640: {
641: PetscMPIInt lo = 0, hi, t;
643: PetscFunctionBegin;
644: *owner = -1; /* GCC erroneously issues warning about possibly uninitialized use when error condition */
645: PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first");
646: PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx);
647: hi = map->size;
648: while (hi - lo > 1) {
649: t = lo + (hi - lo) / 2;
650: if (idx < map->range[t]) hi = t;
651: else lo = t;
652: }
653: *owner = lo;
654: PetscFunctionReturn(PETSC_SUCCESS);
655: }
657: /*@
658: PetscLayoutFindOwnerIndex - Find the owning MPI process and the local index on that process for a global index
660: Not Collective; No Fortran Support
662: Input Parameters:
663: + map - the layout
664: - idx - global index to find the owner of
666: Output Parameters:
667: + owner - the owning rank
668: - lidx - local index used by the owner for `idx`
670: Level: developer
672: .seealso: `PetscLayout`, `PetscLayoutFindOwner()`
673: @*/
674: PetscErrorCode PetscLayoutFindOwnerIndex(PetscLayout map, PetscInt idx, PetscMPIInt *owner, PetscInt *lidx)
675: {
676: PetscMPIInt lo = 0, hi, t;
678: PetscFunctionBegin;
679: PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first");
680: PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx);
681: hi = map->size;
682: while (hi - lo > 1) {
683: t = lo + (hi - lo) / 2;
684: if (idx < map->range[t]) hi = t;
685: else lo = t;
686: }
687: if (owner) *owner = lo;
688: if (lidx) *lidx = idx - map->range[lo];
689: PetscFunctionReturn(PETSC_SUCCESS);
690: }