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 space and sets the PetscLayout contents to the default.

 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: `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
 47:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`,
 48:           `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 space, 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:   Notes:
 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: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
 98:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromRanges()`

100: @*/
101: PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm,PetscInt n,PetscInt N,PetscInt bs,PetscLayout *map)
102: {
103:   PetscLayoutCreate(comm, map);
104:   PetscLayoutSetLocalSize(*map, n);
105:   PetscLayoutSetSize(*map, N);
106:   PetscLayoutSetBlockSize(*map, bs);
107:   PetscLayoutSetUp(*map);
108:   return 0;
109: }

111: /*@
112:   PetscLayoutDestroy - Frees a map object and frees its range if that exists.

114:   Collective

116:   Input Parameters:
117: . map - the PetscLayout

119:   Level: developer

121:   Note:
122:   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementations; it is
123:   recommended they not be used in user codes unless you really gain something in their use.

125: .seealso: `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutCreate()`,
126:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`

128: @*/
129: PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
130: {
131:   if (!*map) return 0;
132:   if (!(*map)->refcnt--) {
133:     if ((*map)->range_alloc) PetscFree((*map)->range);
134:     ISLocalToGlobalMappingDestroy(&(*map)->mapping);
135:     PetscFree((*map));
136:   }
137:   *map = NULL;
138:   return 0;
139: }

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

144:   Collective

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

152:   Output Parameters:
153: . newmap - the new PetscLayout

155:   Level: developer

157: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
158:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromSizes()`

160: @*/
161: PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm,const PetscInt range[],PetscCopyMode mode,PetscInt bs,PetscLayout *newmap)
162: {
163:   PetscLayout    map;
164:   PetscMPIInt    rank;

166:   MPI_Comm_rank(comm, &rank);
167:   PetscLayoutCreate(comm, &map);
168:   PetscLayoutSetBlockSize(map, bs);
169:   switch (mode) {
170:     case PETSC_COPY_VALUES:
171:       PetscMalloc1(map->size+1, &map->range);
172:       PetscArraycpy(map->range, range, map->size+1);
173:       break;
174:     case PETSC_USE_POINTER:
175:       map->range_alloc = PETSC_FALSE;
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:     MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);
188:     if (map->bs > 1) {
190:     }
191:     if (map->bs > 1) {
193:     }
194:   }
195:   /* lock the layout */
196:   map->setupcalled = PETSC_TRUE;
197:   map->oldn = map->n;
198:   map->oldN = map->N;
199:   map->oldbs = map->bs;
200:   *newmap = map;
201:   return 0;
202: }

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

208:   Collective

210:   Input Parameters:
211: . map - pointer to the map

213:   Level: developer

215:   Notes:
216:     Typical calling sequence
217: $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
218: $ PetscLayoutSetBlockSize(PetscLayout,1);
219: $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
220: $ PetscLayoutSetUp(PetscLayout);
221: $ PetscLayoutGetSize(PetscLayout,PetscInt *);

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: `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
228:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`, `PetscSplitOwnership()`
229: @*/
230: PetscErrorCode PetscLayoutSetUp(PetscLayout map)
231: {
232:   PetscMPIInt    rank;
233:   PetscInt       p;

236:   if (map->setupcalled) return 0;

238:   if (map->n > 0 && map->bs > 1) {
240:   }
241:   if (map->N > 0 && map->bs > 1) {
243:   }

245:   MPI_Comm_rank(map->comm, &rank);
246:   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
247:   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
248:   PetscSplitOwnership(map->comm,&map->n,&map->N);
249:   map->n = map->n*PetscAbs(map->bs);
250:   map->N = map->N*PetscAbs(map->bs);
251:   if (!map->range) {
252:     PetscMalloc1(map->size+1, &map->range);
253:   }
254:   MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);

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

259:   map->rstart = map->range[rank];
260:   map->rend   = map->range[rank+1];

262:   /* lock the layout */
263:   map->setupcalled = PETSC_TRUE;
264:   map->oldn = map->n;
265:   map->oldN = map->N;
266:   map->oldbs = map->bs;
267:   return 0;
268: }

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

273:   Collective on PetscLayout

275:   Input Parameter:
276: . in - input PetscLayout to be duplicated

278:   Output Parameter:
279: . out - the copy

281:   Level: developer

283:   Notes:
284:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

286: .seealso: `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()`
287: @*/
288: PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
289: {
290:   MPI_Comm       comm = in->comm;

292:   PetscLayoutDestroy(out);
293:   PetscLayoutCreate(comm,out);
294:   PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));
295:   if (in->range) {
296:     PetscMalloc1((*out)->size+1,&(*out)->range);
297:     PetscArraycpy((*out)->range,in->range,(*out)->size+1);
298:   }
299:   (*out)->refcnt = 0;
300:   return 0;
301: }

303: /*@
304:   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()

306:   Collective on PetscLayout

308:   Input Parameter:
309: . in - input PetscLayout to be copied

311:   Output Parameter:
312: . out - the reference location

314:   Level: developer

316:   Notes:
317:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

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

321: .seealso: `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
322: @*/
323: PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
324: {
325:   in->refcnt++;
326:   PetscLayoutDestroy(out);
327:   *out = in;
328:   return 0;
329: }

331: /*@
332:   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout

334:   Collective on PetscLayout

336:   Input Parameters:
337: + in - input PetscLayout
338: - ltog - the local to global mapping

340:   Level: developer

342:   Notes:
343:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

345:   If the ltog location already contains a PetscLayout it is destroyed

347: .seealso: `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
348: @*/
349: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
350: {
351:   if (ltog) {
352:     PetscInt bs;

354:     ISLocalToGlobalMappingGetBlockSize(ltog,&bs);
356:     PetscObjectReference((PetscObject)ltog);
357:   }
358:   ISLocalToGlobalMappingDestroy(&in->mapping);
359:   in->mapping = ltog;
360:   return 0;
361: }

363: /*@
364:   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.

366:   Collective on PetscLayout

368:   Input Parameters:
369: + map - pointer to the map
370: - n - the local size

372:   Level: developer

374:   Notes:
375:   Call this after the call to PetscLayoutCreate()

377: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
378:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
379: @*/
380: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
381: {
383:   map->n = n;
384:   return 0;
385: }

387: /*@
388:      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.

390:     Not Collective

392:    Input Parameters:
393: .    map - pointer to the map

395:    Output Parameters:
396: .    n - the local size

398:    Level: developer

400:     Notes:
401:        Call this after the call to PetscLayoutSetUp()

403:     Fortran Notes:
404:       Not available from Fortran

406: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
407:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`

409: @*/
410: PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
411: {
412:   *n = map->n;
413:   return 0;
414: }

416: /*@
417:   PetscLayoutSetSize - Sets the global size for a PetscLayout object.

419:   Logically Collective on PetscLayout

421:   Input Parameters:
422: + map - pointer to the map
423: - n - the global size

425:   Level: developer

427:   Notes:
428:   Call this after the call to PetscLayoutCreate()

430: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
431:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
432: @*/
433: PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
434: {
435:   map->N = n;
436:   return 0;
437: }

439: /*@
440:   PetscLayoutGetSize - Gets the global size for a PetscLayout object.

442:   Not Collective

444:   Input Parameters:
445: . map - pointer to the map

447:   Output Parameters:
448: . n - the global size

450:   Level: developer

452:   Notes:
453:   Call this after the call to PetscLayoutSetUp()

455: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
456:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
457: @*/
458: PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
459: {
460:   *n = map->N;
461:   return 0;
462: }

464: /*@
465:   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.

467:   Logically Collective on PetscLayout

469:   Input Parameters:
470: + map - pointer to the map
471: - bs - the size

473:   Level: developer

475:   Notes:
476:   Call this after the call to PetscLayoutCreate()

478: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
479:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
480: @*/
481: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
482: {
483:   if (bs < 0) return 0;
485:   if (map->mapping) {
486:     PetscInt       obs;

488:     ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);
489:     if (obs > 1) {
490:       ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);
491:     }
492:   }
493:   map->bs = bs;
494:   return 0;
495: }

497: /*@
498:   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.

500:   Not Collective

502:   Input Parameters:
503: . map - pointer to the map

505:   Output Parameters:
506: . bs - the size

508:   Level: developer

510:   Notes:
511:   Call this after the call to PetscLayoutSetUp()

513: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
514:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`
515: @*/
516: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
517: {
518:   *bs = PetscAbs(map->bs);
519:   return 0;
520: }

522: /*@
523:   PetscLayoutGetRange - gets the range of values owned by this process

525:   Not Collective

527:   Input Parameter:
528: . map - pointer to the map

530:   Output Parameters:
531: + rstart - first index owned by this process
532: - rend   - one more than the last index owned by this process

534:   Level: developer

536:   Notes:
537:   Call this after the call to PetscLayoutSetUp()

539: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
540:           `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
541: @*/
542: PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
543: {
544:   if (rstart) *rstart = map->rstart;
545:   if (rend)   *rend   = map->rend;
546:   return 0;
547: }

549: /*@C
550:      PetscLayoutGetRanges - gets the range of values owned by all processes

552:     Not Collective

554:    Input Parameters:
555: .    map - pointer to the map

557:    Output Parameters:
558: .    range - start of each processors range of indices (the final entry is one more than the
559:              last index on the last process)

561:    Level: developer

563:     Notes:
564:        Call this after the call to PetscLayoutSetUp()

566:     Fortran Notes:
567:       Not available from Fortran

569: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
570:           `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`

572: @*/
573: PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
574: {
575:   *range = map->range;
576:   return 0;
577: }

579: /*@
580:   PetscLayoutCompare - Compares two layouts

582:   Not Collective

584:   Input Parameters:
585: + mapa - pointer to the first map
586: - mapb - pointer to the second map

588:   Output Parameters:
589: . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise

591:   Level: beginner

593:   Notes:

595: .seealso: `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
596:           `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
597: @*/
598: PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
599: {
600:   *congruent = PETSC_FALSE;
601:   if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) {
602:     PetscArraycmp(mapa->range,mapb->range,mapa->size+1,congruent);
603:   }
604:   return 0;
605: }