Actual source code: pmap.c
petsc-3.10.5 2019-03-28
Report Typos and Errors

      2: /*
      3:    This file contains routines for basic map object implementation.
      4: */

      6:  #include <petscis.h>
      7:  #include <petscsf.h>

      9: /*@
     10:   PetscLayoutCreate - Allocates PetscLayout space and sets the map contents to the default.

     12:   Collective on MPI_Comm

     14:   Input Parameters:
     15: + comm - the MPI communicator
     16: - map - pointer to the map

     18:   Level: advanced

     20:   Notes:
     21:   Typical calling sequence
     22: .vb
     23:        PetscLayoutCreate(MPI_Comm,PetscLayout *);
     24:        PetscLayoutSetBlockSize(PetscLayout,1);
     25:        PetscLayoutSetSize(PetscLayout,N) // or PetscLayoutSetLocalSize(PetscLayout,n);
     26:        PetscLayoutSetUp(PetscLayout);
     27: .ve
     28:   Optionally use any of the following:

     30: + PetscLayoutGetSize(PetscLayout,PetscInt *);
     31: . PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
     32: . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
     33: . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
     34: - PetscLayoutDestroy(PetscLayout*);

     36:   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is often not needed in
     37:   user codes unless you really gain something in their use.

     39: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
     40:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()

     42: @*/
     43: PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
     44: {

     48:   PetscNew(map);

     50:   (*map)->comm   = comm;
     51:   (*map)->bs     = -1;
     52:   (*map)->n      = -1;
     53:   (*map)->N      = -1;
     54:   (*map)->range  = NULL;
     55:   (*map)->rstart = 0;
     56:   (*map)->rend   = 0;
     57:   return(0);
     58: }

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

     63:   Collective on MPI_Comm

     65:   Input Parameters:
     66: . map - the PetscLayout

     68:   Level: developer

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

     74: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(),
     75:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()

     77: @*/
     78: PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
     79: {

     83:   if (!*map) return(0);
     84:   if (!(*map)->refcnt--) {
     85:     PetscFree((*map)->range);
     86:     ISLocalToGlobalMappingDestroy(&(*map)->mapping);
     87:     PetscFree((*map));
     88:   }
     89:   *map = NULL;
     90:   return(0);
     91: }

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

     97:   Collective on MPI_Comm

     99:   Input Parameters:
    100: . map - pointer to the map

    102:   Level: developer

    104:   Notes:
    105:     Typical calling sequence
    106: $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
    107: $ PetscLayoutSetBlockSize(PetscLayout,1);
    108: $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
    109: $ PetscLayoutSetUp(PetscLayout);
    110: $ PetscLayoutGetSize(PetscLayout,PetscInt *);

    113:   If the local size, global size are already set and range exists then this does nothing.

    115: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
    116:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
    117: @*/
    118: PetscErrorCode PetscLayoutSetUp(PetscLayout map)
    119: {
    120:   PetscMPIInt    rank,size;
    121:   PetscInt       p;

    125:   if ((map->n >= 0) && (map->N >= 0) && (map->range)) return(0);

    127:   if (map->n > 0 && map->bs > 1) {
    128:     if (map->n % map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local matrix size %D must be divisible by blocksize %D",map->n,map->bs);
    129:   }
    130:   if (map->N > 0 && map->bs > 1) {
    131:     if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global matrix size %D must be divisible by blocksize %D",map->N,map->bs);
    132:   }

    134:   MPI_Comm_size(map->comm, &size);
    135:   MPI_Comm_rank(map->comm, &rank);
    136:   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
    137:   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
    138:   PetscSplitOwnership(map->comm,&map->n,&map->N);
    139:   map->n = map->n*PetscAbs(map->bs);
    140:   map->N = map->N*PetscAbs(map->bs);
    141:   if (!map->range) {
    142:     PetscMalloc1(size+1, &map->range);
    143:   }
    144:   MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);

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

    149:   map->rstart = map->range[rank];
    150:   map->rend   = map->range[rank+1];
    151:   return(0);
    152: }

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

    157:   Collective on PetscLayout

    159:   Input Parameter:
    160: . in - input PetscLayout to be duplicated

    162:   Output Parameter:
    163: . out - the copy

    165:   Level: developer

    167:   Notes:
    168:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

    170: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
    171: @*/
    172: PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
    173: {
    174:   PetscMPIInt    size;
    176:   MPI_Comm       comm = in->comm;

    179:   PetscLayoutDestroy(out);
    180:   PetscLayoutCreate(comm,out);
    181:   MPI_Comm_size(comm,&size);
    182:   PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));
    183:   PetscMalloc1(size+1,&(*out)->range);
    184:   PetscMemcpy((*out)->range,in->range,(size+1)*sizeof(PetscInt));

    186:   (*out)->refcnt = 0;
    187:   return(0);
    188: }

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

    193:   Collective on PetscLayout

    195:   Input Parameter:
    196: . in - input PetscLayout to be copied

    198:   Output Parameter:
    199: . out - the reference location

    201:   Level: developer

    203:   Notes:
    204:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

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

    208: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
    209: @*/
    210: PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
    211: {

    215:   in->refcnt++;
    216:   PetscLayoutDestroy(out);
    217:   *out = in;
    218:   return(0);
    219: }

    221: /*@
    222:   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout

    224:   Collective on PetscLayout

    226:   Input Parameter:
    227: + in - input PetscLayout
    228: - ltog - the local to global mapping

    231:   Level: developer

    233:   Notes:
    234:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

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

    238: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
    239: @*/
    240: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
    241: {
    243:   PetscInt       bs;

    246:   ISLocalToGlobalMappingGetBlockSize(ltog,&bs);
    247:   if (in->bs > 0 && in->bs != bs) SETERRQ2(in->comm,PETSC_ERR_PLIB,"Blocksize of layout %D must match that of mapping %D",in->bs,bs);
    248:   PetscObjectReference((PetscObject)ltog);
    249:   ISLocalToGlobalMappingDestroy(&in->mapping);
    250:   in->mapping = ltog;
    251:   return(0);
    252: }

    254: /*@
    255:   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.

    257:   Collective on PetscLayout

    259:   Input Parameters:
    260: + map - pointer to the map
    261: - n - the local size

    263:   Level: developer

    265:   Notes:
    266:   Call this after the call to PetscLayoutCreate()

    268: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
    269:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
    270: @*/
    271: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
    272: {
    274:   if (map->bs > 1 && n % map->bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Local size %D not compatible with block size %D",n,map->bs);
    275:   map->n = n;
    276:   return(0);
    277: }

    279: /*@C
    280:      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.

    282:     Not Collective

    284:    Input Parameters:
    285: .    map - pointer to the map

    287:    Output Parameters:
    288: .    n - the local size

    290:    Level: developer

    292:     Notes:
    293:        Call this after the call to PetscLayoutSetUp()

    295:     Fortran Notes:
    296:       Not available from Fortran

    298: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
    299:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()

    301: @*/
    302: PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
    303: {
    305:   *n = map->n;
    306:   return(0);
    307: }

    309: /*@
    310:   PetscLayoutSetSize - Sets the global size for a PetscLayout object.

    312:   Logically Collective on PetscLayout

    314:   Input Parameters:
    315: + map - pointer to the map
    316: - n - the global size

    318:   Level: developer

    320:   Notes:
    321:   Call this after the call to PetscLayoutCreate()

    323: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
    324:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
    325: @*/
    326: PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
    327: {
    329:   map->N = n;
    330:   return(0);
    331: }

    333: /*@
    334:   PetscLayoutGetSize - Gets the global size for a PetscLayout object.

    336:   Not Collective

    338:   Input Parameters:
    339: . map - pointer to the map

    341:   Output Parameters:
    342: . n - the global size

    344:   Level: developer

    346:   Notes:
    347:   Call this after the call to PetscLayoutSetUp()

    349: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
    350:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
    351: @*/
    352: PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
    353: {
    355:   *n = map->N;
    356:   return(0);
    357: }

    359: /*@
    360:   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.

    362:   Logically Collective on PetscLayout

    364:   Input Parameters:
    365: + map - pointer to the map
    366: - bs - the size

    368:   Level: developer

    370:   Notes:
    371:   Call this after the call to PetscLayoutCreate()

    373: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
    374:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
    375: @*/
    376: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
    377: {
    379:   if (bs < 0) return(0);
    380:   if (map->n > 0 && map->n % bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Local size %D not compatible with block size %D",map->n,bs);
    381:   if (map->mapping) {
    382:     PetscInt       obs;

    385:     ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);
    386:     if (obs > 1) {
    387:       ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);
    388:     }
    389:   }
    390:   map->bs = bs;
    391:   return(0);
    392: }

    394: /*@
    395:   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.

    397:   Not Collective

    399:   Input Parameters:
    400: . map - pointer to the map

    402:   Output Parameters:
    403: . bs - the size

    405:   Level: developer

    407:   Notes:
    408:   Call this after the call to PetscLayoutSetUp()

    410: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
    411:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
    412: @*/
    413: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
    414: {
    416:   *bs = PetscAbs(map->bs);
    417:   return(0);
    418: }

    420: /*@
    421:   PetscLayoutGetRange - gets the range of values owned by this process

    423:   Not Collective

    425:   Input Parameters:
    426: . map - pointer to the map

    428:   Output Parameters:
    429: + rstart - first index owned by this process
    430: - rend   - one more than the last index owned by this process

    432:   Level: developer

    434:   Notes:
    435:   Call this after the call to PetscLayoutSetUp()

    437: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
    438:           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
    439: @*/
    440: PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
    441: {
    443:   if (rstart) *rstart = map->rstart;
    444:   if (rend)   *rend   = map->rend;
    445:   return(0);
    446: }

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

    451:     Not Collective

    453:    Input Parameters:
    454: .    map - pointer to the map

    456:    Output Parameters:
    457: .    range - start of each processors range of indices (the final entry is one more then the
    458:              last index on the last process)

    460:    Level: developer

    462:     Notes:
    463:        Call this after the call to PetscLayoutSetUp()

    465:     Fortran Notes:
    466:       Not available from Fortran

    468: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
    469:           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()

    471: @*/
    472: PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
    473: {
    475:   *range = map->range;
    476:   return(0);
    477: }

    479: /*@C
    480:    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout

    482:    Collective

    484:    Input Arguments:
    485: +  sf - star forest
    486: .  layout - PetscLayout defining the global space
    487: .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
    488: .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
    489: .  localmode - copy mode for ilocal
    490: -  iremote - remote locations of root vertices for each leaf on the current process

    492:    Level: intermediate

    494:    Developers Note: Local indices which are the identity permutation in the range [0,nleaves) are discarded as they
    495:    encode contiguous storage. In such case, if localmode is PETSC_OWN_POINTER, the memory is deallocated as it is not
    496:    needed

    498: .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
    499: @*/
    500: PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
    501: {
    503:   PetscInt       i,nroots;
    504:   PetscSFNode    *remote;

    507:   PetscLayoutGetLocalSize(layout,&nroots);
    508:   PetscMalloc1(nleaves,&remote);
    509:   for (i=0; i<nleaves; i++) {
    510:     PetscInt owner = -1;
    511:     PetscLayoutFindOwner(layout,iremote[i],&owner);
    512:     remote[i].rank  = owner;
    513:     remote[i].index = iremote[i] - layout->range[owner];
    514:   }
    515:   PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);
    516:   return(0);
    517: }

    519: /*@
    520:   PetscLayoutCompare - Compares two layouts

    522:   Not Collective

    524:   Input Parameters:
    525: + mapa - pointer to the first map
    526: - mapb - pointer to the second map

    528:   Output Parameters:
    529: . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise

    531:   Level: beginner

    533:   Notes:

    535: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
    536:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
    537: @*/
    538: PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
    539: {
    541:   PetscMPIInt    sizea,sizeb;

    544:   *congruent = PETSC_FALSE;
    545:   MPI_Comm_size(mapa->comm,&sizea);
    546:   MPI_Comm_size(mapb->comm,&sizeb);
    547:   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
    548:     PetscMemcmp(mapa->range,mapb->range,(sizea+1)*sizeof(PetscInt),congruent);
    549:   }
    550:   return(0);
    551: }