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 Parameters:
14: . comm - the MPI communicator
16: Output Parameters:
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: PetscNew(map);
54: 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: return 0;
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 Parameters:
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: PetscLayoutCreate(comm, map);
103: PetscLayoutSetLocalSize(*map, n);
104: PetscLayoutSetSize(*map, N);
105: PetscLayoutSetBlockSize(*map, bs);
106: PetscLayoutSetUp(*map);
107: return 0;
108: }
110: /*@
111: PetscLayoutDestroy - Frees a `PetscLayout` object and frees its range if that exists.
113: Collective
115: Input Parameters:
116: . map - the `PetscLayout`
118: Level: developer
120: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
121: `PetscLayout`, `PetscLayoutCreate()`,
122: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`
123: @*/
124: PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
125: {
126: if (!*map) return 0;
127: if (!(*map)->refcnt--) {
128: if ((*map)->range_alloc) PetscFree((*map)->range);
129: ISLocalToGlobalMappingDestroy(&(*map)->mapping);
130: PetscFree((*map));
131: }
132: *map = NULL;
133: return 0;
134: }
136: /*@
137: PetscLayoutCreateFromRanges - Creates a new `PetscLayout` with the given ownership ranges and sets it up.
139: Collective
141: Input Parameters:
142: + comm - the MPI communicator
143: . range - the array of ownership ranges for each rank with length commsize+1
144: . mode - the copy mode for range
145: - bs - the block size (or `PETSC_DECIDE`)
147: Output Parameters:
148: . newmap - the new `PetscLayout`
150: Level: developer
152: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`,
153: `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
154: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromSizes()`
155: @*/
156: PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm, const PetscInt range[], PetscCopyMode mode, PetscInt bs, PetscLayout *newmap)
157: {
158: PetscLayout map;
159: PetscMPIInt rank;
161: MPI_Comm_rank(comm, &rank);
162: PetscLayoutCreate(comm, &map);
163: PetscLayoutSetBlockSize(map, bs);
164: switch (mode) {
165: case PETSC_COPY_VALUES:
166: PetscMalloc1(map->size + 1, &map->range);
167: PetscArraycpy(map->range, range, map->size + 1);
168: break;
169: case PETSC_USE_POINTER:
170: map->range_alloc = PETSC_FALSE;
171: break;
172: default:
173: map->range = (PetscInt *)range;
174: break;
175: }
176: map->rstart = map->range[rank];
177: map->rend = map->range[rank + 1];
178: map->n = map->rend - map->rstart;
179: map->N = map->range[map->size];
180: if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */
181: PetscInt tmp;
182: MPIU_Allreduce(&map->n, &tmp, 1, MPIU_INT, MPI_SUM, map->comm);
186: }
187: /* lock the layout */
188: map->setupcalled = PETSC_TRUE;
189: map->oldn = map->n;
190: map->oldN = map->N;
191: map->oldbs = map->bs;
192: *newmap = map;
193: return 0;
194: }
196: /*@
197: PetscLayoutSetUp - given a map where you have set either the global or local
198: size sets up the map so that it may be used.
200: Collective
202: Input Parameters:
203: . map - pointer to the map
205: Level: developer
207: Notes:
208: Typical calling sequence
209: .vb
210: PetscLayoutCreate(MPI_Comm,PetscLayout *);
211: PetscLayoutSetBlockSize(PetscLayout,1);
212: PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
213: PetscLayoutSetUp(PetscLayout);
214: PetscLayoutGetSize(PetscLayout,PetscInt *);
215: .ve
217: If range exists, and local size is not set, everything gets computed from the range.
219: If the local size, global size are already set and range exists then this does nothing.
221: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
222: `PetscLayout`, `PetscLayoutDestroy()`,
223: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`, `PetscSplitOwnership()`
224: @*/
225: PetscErrorCode PetscLayoutSetUp(PetscLayout map)
226: {
227: PetscMPIInt rank;
228: PetscInt p;
231: map->oldn, map->oldN, map->n, map->N);
232: if (map->setupcalled) return 0;
237: MPI_Comm_rank(map->comm, &rank);
238: if (map->n > 0) map->n = map->n / PetscAbs(map->bs);
239: if (map->N > 0) map->N = map->N / PetscAbs(map->bs);
240: PetscSplitOwnership(map->comm, &map->n, &map->N);
241: map->n = map->n * PetscAbs(map->bs);
242: map->N = map->N * PetscAbs(map->bs);
243: if (!map->range) PetscMalloc1(map->size + 1, &map->range);
244: MPI_Allgather(&map->n, 1, MPIU_INT, map->range + 1, 1, MPIU_INT, map->comm);
246: map->range[0] = 0;
247: for (p = 2; p <= map->size; p++) map->range[p] += map->range[p - 1];
249: map->rstart = map->range[rank];
250: map->rend = map->range[rank + 1];
252: /* lock the layout */
253: map->setupcalled = PETSC_TRUE;
254: map->oldn = map->n;
255: map->oldN = map->N;
256: map->oldbs = map->bs;
257: return 0;
258: }
260: /*@
261: PetscLayoutDuplicate - creates a new `PetscLayout` with the same information as a given one. If the `PetscLayout` already exists it is destroyed first.
263: Collective
265: Input Parameter:
266: . in - input `PetscLayout` to be duplicated
268: Output Parameter:
269: . out - the copy
271: Level: developer
273: Note:
274: `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
276: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()`
277: @*/
278: PetscErrorCode PetscLayoutDuplicate(PetscLayout in, PetscLayout *out)
279: {
280: MPI_Comm comm = in->comm;
282: PetscLayoutDestroy(out);
283: PetscLayoutCreate(comm, out);
284: PetscMemcpy(*out, in, sizeof(struct _n_PetscLayout));
285: if (in->range) {
286: PetscMalloc1((*out)->size + 1, &(*out)->range);
287: PetscArraycpy((*out)->range, in->range, (*out)->size + 1);
288: }
289: (*out)->refcnt = 0;
290: return 0;
291: }
293: /*@
294: PetscLayoutReference - Causes a PETSc `Vec` or `Mat` to share a `PetscLayout` with one that already exists.
296: Collective
298: Input Parameter:
299: . in - input `PetscLayout` to be copied
301: Output Parameter:
302: . out - the reference location
304: Level: developer
306: Notes:
307: `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
309: If the out location already contains a `PetscLayout` it is destroyed
311: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
312: @*/
313: PetscErrorCode PetscLayoutReference(PetscLayout in, PetscLayout *out)
314: {
315: in->refcnt++;
316: PetscLayoutDestroy(out);
317: *out = in;
318: return 0;
319: }
321: /*@
322: PetscLayoutSetISLocalToGlobalMapping - sets a `ISLocalGlobalMapping` into a `PetscLayout`
324: Collective
326: Input Parameters:
327: + in - input `PetscLayout`
328: - ltog - the local to global mapping
330: Level: developer
332: Notes:
333: `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
335: If the `PetscLayout` already contains a `ISLocalGlobalMapping` it is destroyed
337: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
338: @*/
339: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in, ISLocalToGlobalMapping ltog)
340: {
341: if (ltog) {
342: PetscInt bs;
344: ISLocalToGlobalMappingGetBlockSize(ltog, &bs);
346: PetscObjectReference((PetscObject)ltog);
347: }
348: ISLocalToGlobalMappingDestroy(&in->mapping);
349: in->mapping = ltog;
350: return 0;
351: }
353: /*@
354: PetscLayoutSetLocalSize - Sets the local size for a `PetscLayout` object.
356: Collective
358: Input Parameters:
359: + map - pointer to the map
360: - n - the local size
362: Level: developer
364: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
365: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
366: @*/
367: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map, PetscInt n)
368: {
370: map->n = n;
371: return 0;
372: }
374: /*@
375: PetscLayoutGetLocalSize - Gets the local size for a `PetscLayout` object.
377: Not Collective
379: Input Parameters:
380: . map - pointer to the map
382: Output Parameters:
383: . n - the local size
385: Level: developer
387: Note:
388: Call this after the call to `PetscLayoutSetUp()`
390: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
391: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
392: @*/
393: PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map, PetscInt *n)
394: {
395: *n = map->n;
396: return 0;
397: }
399: /*@
400: PetscLayoutSetSize - Sets the global size for a `PetscLayout` object.
402: Logically Collective
404: Input Parameters:
405: + map - pointer to the map
406: - n - the global size
408: Level: developer
410: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
411: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
412: @*/
413: PetscErrorCode PetscLayoutSetSize(PetscLayout map, PetscInt n)
414: {
415: map->N = n;
416: return 0;
417: }
419: /*@
420: PetscLayoutGetSize - Gets the global size for a `PetscLayout` object.
422: Not Collective
424: Input Parameters:
425: . map - pointer to the map
427: Output Parameters:
428: . n - the global size
430: Level: developer
432: Note:
433: Call this after the call to `PetscLayoutSetUp()`
435: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
436: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
437: @*/
438: PetscErrorCode PetscLayoutGetSize(PetscLayout map, PetscInt *n)
439: {
440: *n = map->N;
441: return 0;
442: }
444: /*@
445: PetscLayoutSetBlockSize - Sets the block size for a `PetscLayout` object.
447: Logically Collective
449: Input Parameters:
450: + map - pointer to the map
451: - bs - the size
453: Level: developer
455: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
456: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
457: @*/
458: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map, PetscInt bs)
459: {
460: if (bs < 0) return 0;
462: if (map->mapping) {
463: PetscInt obs;
465: ISLocalToGlobalMappingGetBlockSize(map->mapping, &obs);
466: if (obs > 1) ISLocalToGlobalMappingSetBlockSize(map->mapping, bs);
467: }
468: map->bs = bs;
469: return 0;
470: }
472: /*@
473: PetscLayoutGetBlockSize - Gets the block size for a `PetscLayout` object.
475: Not Collective
477: Input Parameters:
478: . map - pointer to the map
480: Output Parameters:
481: . bs - the size
483: Level: developer
485: Notes:
486: Call this after the call to `PetscLayoutSetUp()`
488: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
489: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`
490: @*/
491: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map, PetscInt *bs)
492: {
493: *bs = PetscAbs(map->bs);
494: return 0;
495: }
497: /*@
498: PetscLayoutGetRange - gets the range of values owned by this process
500: Not Collective
502: Input Parameter:
503: . map - pointer to the map
505: Output Parameters:
506: + rstart - first index owned by this process
507: - rend - one more than the last index owned by this process
509: Level: developer
511: Note:
512: Call this after the call to `PetscLayoutSetUp()`
514: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
515: `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
516: @*/
517: PetscErrorCode PetscLayoutGetRange(PetscLayout map, PetscInt *rstart, PetscInt *rend)
518: {
519: if (rstart) *rstart = map->rstart;
520: if (rend) *rend = map->rend;
521: return 0;
522: }
524: /*@C
525: PetscLayoutGetRanges - gets the ranges of values owned by all processes
527: Not Collective
529: Input Parameters:
530: . map - pointer to the map
532: Output Parameters:
533: . range - start of each processors range of indices (the final entry is one more than the
534: last index on the last process)
536: Level: developer
538: Note:
539: Call this after the call to `PetscLayoutSetUp()`
541: Fortran Note:
542: Not available from Fortran
544: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
545: `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
546: @*/
547: PetscErrorCode PetscLayoutGetRanges(PetscLayout map, const PetscInt *range[])
548: {
549: *range = map->range;
550: return 0;
551: }
553: /*@
554: PetscLayoutCompare - Compares two layouts
556: Not Collective
558: Input Parameters:
559: + mapa - pointer to the first map
560: - mapb - pointer to the second map
562: Output Parameters:
563: . congruent - `PETSC_TRUE` if the two layouts are congruent, `PETSC_FALSE` otherwise
565: Level: beginner
567: .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
568: `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
569: @*/
570: PetscErrorCode PetscLayoutCompare(PetscLayout mapa, PetscLayout mapb, PetscBool *congruent)
571: {
572: *congruent = PETSC_FALSE;
573: if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) PetscArraycmp(mapa->range, mapb->range, mapa->size + 1, congruent);
574: return 0;
575: }