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: }