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: $ 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
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: }
111: /*@
112: PetscLayoutDestroy - Frees a `PetscLayout` object and frees its range if that exists.
114: Collective
116: Input Parameter:
117: . map - the `PetscLayout`
119: Level: developer
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: }
138: /*@
139: PetscLayoutCreateFromRanges - Creates a new `PetscLayout` with the given ownership ranges and sets it up.
141: Collective
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`)
149: Output Parameter:
150: . newmap - the new `PetscLayout`
152: Level: developer
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;
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: PetscCallMPI(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 ". The 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: }
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.
203: Collective
205: Input Parameter:
206: . map - pointer to the map
208: Level: developer
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
220: If range exists, and local size is not set, everything gets computed from the range.
222: If the local size, global size are already set and range exists then this does nothing.
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;
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);
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);
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));
250: map->range[0] = 0;
251: for (p = 2; p <= map->size; p++) map->range[p] += map->range[p - 1];
253: map->rstart = map->range[rank];
254: map->rend = map->range[rank + 1];
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: }
264: /*@
265: PetscLayoutDuplicate - creates a new `PetscLayout` with the same information as a given one. If the `PetscLayout` already exists it is destroyed first.
267: Collective
269: Input Parameter:
270: . in - input `PetscLayout` to be duplicated
272: Output Parameter:
273: . out - the copy
275: Level: developer
277: Note:
278: `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
280: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()`
281: @*/
282: PetscErrorCode PetscLayoutDuplicate(PetscLayout in, PetscLayout *out)
283: {
284: MPI_Comm comm = in->comm;
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: }
298: /*@
299: PetscLayoutReference - Causes a PETSc `Vec` or `Mat` to share a `PetscLayout` with one that already exists.
301: Collective
303: Input Parameter:
304: . in - input `PetscLayout` to be copied
306: Output Parameter:
307: . out - the reference location
309: Level: developer
311: Notes:
312: `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
314: If the out location already contains a `PetscLayout` it is destroyed
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: }
327: /*@
328: PetscLayoutSetISLocalToGlobalMapping - sets a `ISLocalGlobalMapping` into a `PetscLayout`
330: Collective
332: Input Parameters:
333: + in - input `PetscLayout`
334: - ltog - the local to global mapping
336: Level: developer
338: Notes:
339: `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
341: If the `PetscLayout` already contains a `ISLocalGlobalMapping` it is destroyed
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;
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: }
354: PetscCall(PetscObjectReference((PetscObject)ltog));
355: PetscCall(ISLocalToGlobalMappingDestroy(&in->mapping));
356: in->mapping = ltog;
357: PetscFunctionReturn(PETSC_SUCCESS);
358: }
360: /*@
361: PetscLayoutSetLocalSize - Sets the local size for a `PetscLayout` object.
363: Collective
365: Input Parameters:
366: + map - pointer to the map
367: - n - the local size
369: Level: developer
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: }
382: /*@
383: PetscLayoutGetLocalSize - Gets the local size for a `PetscLayout` object.
385: Not Collective
387: Input Parameter:
388: . map - pointer to the map
390: Output Parameter:
391: . n - the local size
393: Level: developer
395: Note:
396: Call this after the call to `PetscLayoutSetUp()`
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: }
408: /*@
409: PetscLayoutSetSize - Sets the global size for a `PetscLayout` object.
411: Logically Collective
413: Input Parameters:
414: + map - pointer to the map
415: - n - the global size
417: Level: developer
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: }
429: /*@
430: PetscLayoutGetSize - Gets the global size for a `PetscLayout` object.
432: Not Collective
434: Input Parameter:
435: . map - pointer to the map
437: Output Parameter:
438: . n - the global size
440: Level: developer
442: Note:
443: Call this after the call to `PetscLayoutSetUp()`
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: }
455: /*@
456: PetscLayoutSetBlockSize - Sets the block size for a `PetscLayout` object.
458: Logically Collective
460: Input Parameters:
461: + map - pointer to the map
462: - bs - the size
464: Level: developer
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;
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: }
484: /*@
485: PetscLayoutGetBlockSize - Gets the block size for a `PetscLayout` object.
487: Not Collective
489: Input Parameter:
490: . map - pointer to the map
492: Output Parameter:
493: . bs - the size
495: Level: developer
497: Notes:
498: Call this after the call to `PetscLayoutSetUp()`
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: }
510: /*@
511: PetscLayoutGetRange - gets the range of values owned by this process
513: Not Collective
515: Input Parameter:
516: . map - pointer to the map
518: Output Parameters:
519: + rstart - first index owned by this process
520: - rend - one more than the last index owned by this process
522: Level: developer
524: Note:
525: Call this after the call to `PetscLayoutSetUp()`
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: }
538: /*@C
539: PetscLayoutGetRanges - gets the ranges of values owned by all processes
541: Not Collective
543: Input Parameter:
544: . map - pointer to the map
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). The length of the array is one more than the number of processes in the MPI
549: communicator owned by `map`
551: Level: developer
553: Note:
554: Call this after the call to `PetscLayoutSetUp()`
556: Fortran Notes:
557: In Fortran, use PetscLayoutGetRangesF90()
559: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
560: `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `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: }
594: /*@
595: PetscLayoutFindOwner - Find the owning MPI process for a global index
597: Not Collective; No Fortran Support
599: Input Parameters:
600: + map - the layout
601: - idx - global index to find the owner of
603: Output Parameter:
604: . owner - the owning rank
606: Level: developer
608: .seealso: `PetscLayout`, `PetscLayoutFindOwnerIndex()`
609: @*/
610: PetscErrorCode PetscLayoutFindOwner(PetscLayout map, PetscInt idx, PetscMPIInt *owner)
611: {
612: PetscMPIInt lo = 0, hi, t;
614: PetscFunctionBegin;
615: *owner = -1; /* GCC erroneously issues warning about possibly uninitialized use when error condition */
616: PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first");
617: PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx);
618: hi = map->size;
619: while (hi - lo > 1) {
620: t = lo + (hi - lo) / 2;
621: if (idx < map->range[t]) hi = t;
622: else lo = t;
623: }
624: *owner = lo;
625: PetscFunctionReturn(PETSC_SUCCESS);
626: }
628: /*@
629: PetscLayoutFindOwnerIndex - Find the owning MPI process and the local index on that process for a global index
631: Not Collective; No Fortran Support
633: Input Parameters:
634: + map - the layout
635: - idx - global index to find the owner of
637: Output Parameters:
638: + owner - the owning rank
639: - lidx - local index used by the owner for `idx`
641: Level: developer
643: .seealso: `PetscLayout`, `PetscLayoutFindOwner()`
644: @*/
645: PetscErrorCode PetscLayoutFindOwnerIndex(PetscLayout map, PetscInt idx, PetscMPIInt *owner, PetscInt *lidx)
646: {
647: PetscMPIInt lo = 0, hi, t;
649: PetscFunctionBegin;
650: PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first");
651: PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx);
652: hi = map->size;
653: while (hi - lo > 1) {
654: t = lo + (hi - lo) / 2;
655: if (idx < map->range[t]) hi = t;
656: else lo = t;
657: }
658: if (owner) *owner = lo;
659: if (lidx) *lidx = idx - map->range[lo];
660: PetscFunctionReturn(PETSC_SUCCESS);
661: }