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()
    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: /*@C
    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: }