Date: 2025-03-28T21:11:21+00:00

Actual source code: commonmpvec.c

      1: #include <../src/vec/vec/impls/mpi/pvecimpl.h>

      3: /*
      4:   This is used in VecGhostGetLocalForm and VecGhostRestoreLocalForm to ensure
      5:   that the state is updated if either vector has changed since the last time
      6:   one of these functions was called.  It could apply to any PetscObject, but
      7:   VecGhost is quite different from other objects in that two separate vectors
      8:   look at the same memory.

     10:   In principle, we could only propagate state to the local vector on
     11:   GetLocalForm and to the global vector on RestoreLocalForm, but this version is
     12:   more conservative (i.e. robust against misuse) and simpler.

     14:   Note that this function is correct and changes nothing if both arguments are the
     15:   same, which is the case in serial.
     16: */
     17: static PetscErrorCode VecGhostStateSync_Private(Vec g, Vec l)
     18: {
     19:   PetscObjectState gstate, lstate;

     21:   PetscFunctionBegin;
     22:   PetscCall(PetscObjectStateGet((PetscObject)g, &gstate));
     23:   PetscCall(PetscObjectStateGet((PetscObject)l, &lstate));
     24:   PetscCall(PetscObjectStateSet((PetscObject)g, PetscMax(gstate, lstate)));
     25:   PetscCall(PetscObjectStateSet((PetscObject)l, PetscMax(gstate, lstate)));
     26:   PetscFunctionReturn(PETSC_SUCCESS);
     27: }

     29: /*@
     30:   VecGhostGetLocalForm - Obtains the local ghosted representation of
     31:   a parallel vector (obtained with `VecCreateGhost()`, `VecCreateGhostWithArray()` or `VecCreateSeq()`).

     33:   Logically Collective

     35:   Input Parameter:
     36: . g - the global vector

     38:   Output Parameter:
     39: . l - the local (ghosted) representation,`NULL` if `g` is not ghosted

     41:   Level: advanced

     43:   Notes:
     44:   This routine does not actually update the ghost values, but rather it
     45:   returns a sequential vector that includes the locations for the ghost
     46:   values and their current values. The returned vector and the original
     47:   vector passed in share the same array that contains the actual vector data.

     49:   To update the ghost values from the locations on the other processes one must call
     50:   `VecGhostUpdateBegin()` and `VecGhostUpdateEnd()` before accessing the ghost values. Thus normal
     51:   usage is
     52: .vb
     53:      VecGhostUpdateBegin(x,INSERT_VALUES,SCATTER_FORWARD);
     54:      VecGhostUpdateEnd(x,INSERT_VALUES,SCATTER_FORWARD);
     55:      VecGhostGetLocalForm(x,&xlocal);
     56:      VecGetArray(xlocal,&xvalues);
     57:         // access the non-ghost values in locations xvalues[0:n-1] and ghost values in locations xvalues[n:n+nghost];
     58:      VecRestoreArray(xlocal,&xvalues);
     59:      VecGhostRestoreLocalForm(x,&xlocal);
     60: .ve

     62:   One should call `VecGhostRestoreLocalForm()` or `VecDestroy()` once one is
     63:   finished using the object.

     65: .seealso: [](ch_vectors), `Vec`, `VecType`, `VecCreateGhost()`, `VecGhostRestoreLocalForm()`, `VecCreateGhostWithArray()`
     66: @*/
     67: PetscErrorCode VecGhostGetLocalForm(Vec g, Vec *l)
     68: {
     69:   PetscBool isseq, ismpi;

     71:   PetscFunctionBegin;
     73:   PetscAssertPointer(l, 2);

     75:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECSEQ, &isseq));
     76:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECMPI, &ismpi));
     77:   if (ismpi) {
     78:     Vec_MPI *v = (Vec_MPI *)g->data;
     79:     *l         = v->localrep;
     80:   } else if (isseq) {
     81:     *l = g;
     82:   } else {
     83:     *l = NULL;
     84:   }
     85:   if (*l) {
     86:     PetscCall(VecGhostStateSync_Private(g, *l));
     87:     PetscCall(PetscObjectReference((PetscObject)*l));
     88:   }
     89:   PetscFunctionReturn(PETSC_SUCCESS);
     90: }

     92: /*@
     93:   VecGhostIsLocalForm - Checks if a given vector is the local form of a global vector

     95:   Not Collective

     97:   Input Parameters:
     98: + g - the global vector
     99: - l - the local vector

    101:   Output Parameter:
    102: . flg - `PETSC_TRUE` if `l` is the local form

    104:   Level: advanced

    106: .seealso: [](ch_vectors), `Vec`, `VecType`, `VecCreateGhost()`, `VecGhostRestoreLocalForm()`, `VecCreateGhostWithArray()`, `VecGhostGetLocalForm()`
    107: @*/
    108: PetscErrorCode VecGhostIsLocalForm(Vec g, Vec l, PetscBool *flg)
    109: {
    110:   PetscBool isseq, ismpi;

    112:   PetscFunctionBegin;

    116:   *flg = PETSC_FALSE;
    117:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECSEQ, &isseq));
    118:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECMPI, &ismpi));
    119:   if (ismpi) {
    120:     Vec_MPI *v = (Vec_MPI *)g->data;
    121:     if (l == v->localrep) *flg = PETSC_TRUE;
    122:   } else if (isseq) {
    123:     if (l == g) *flg = PETSC_TRUE;
    124:   } else SETERRQ(PetscObjectComm((PetscObject)g), PETSC_ERR_ARG_WRONG, "Global vector is not ghosted");
    125:   PetscFunctionReturn(PETSC_SUCCESS);
    126: }

    128: /*@
    129:   VecGhostRestoreLocalForm - Restores the local ghosted representation of
    130:   a parallel vector obtained with `VecGhostGetLocalForm()`.

    132:   Logically Collective

    134:   Input Parameters:
    135: + g - the global vector
    136: - l - the local (ghosted) representation

    138:   Level: advanced

    140:   Note:
    141:   This routine does not actually update the ghost values, but rather it
    142:   returns a sequential vector that includes the locations for the ghost values
    143:   and their current values.

    145: .seealso: [](ch_vectors), `Vec`, `VecType`, `VecCreateGhost()`, `VecGhostGetLocalForm()`, `VecCreateGhostWithArray()`
    146: @*/
    147: PetscErrorCode VecGhostRestoreLocalForm(Vec g, Vec *l)
    148: {
    149:   PetscFunctionBegin;
    150:   if (*l) {
    151:     PetscCall(VecGhostStateSync_Private(g, *l));
    152:     PetscCall(PetscObjectDereference((PetscObject)*l));
    153:   }
    154:   PetscFunctionReturn(PETSC_SUCCESS);
    155: }

    157: /*@
    158:   VecGhostUpdateBegin - Begins the vector scatter to update the vector from
    159:   local representation to global or global representation to local.

    161:   Neighbor-wise Collective

    163:   Input Parameters:
    164: + g           - the vector (obtained with `VecCreateGhost()` or `VecDuplicate()`)
    165: . insertmode  - one of `ADD_VALUES`, `MAX_VALUES`, `MIN_VALUES` or `INSERT_VALUES`
    166: - scattermode - one of `SCATTER_FORWARD` or `SCATTER_REVERSE`

    168:   Level: advanced

    170:   Notes:
    171:   Use the following to update the ghost regions with correct values from the owning process
    172: .vb
    173:        VecGhostUpdateBegin(v,INSERT_VALUES,SCATTER_FORWARD);
    174:        VecGhostUpdateEnd(v,INSERT_VALUES,SCATTER_FORWARD);
    175: .ve

    177:   Use the following to accumulate the ghost region values onto the owning processors
    178: .vb
    179:        VecGhostUpdateBegin(v,ADD_VALUES,SCATTER_REVERSE);
    180:        VecGhostUpdateEnd(v,ADD_VALUES,SCATTER_REVERSE);
    181: .ve

    183:   To accumulate the ghost region values onto the owning processors and then update
    184:   the ghost regions correctly, call the latter followed by the former, i.e.,
    185: .vb
    186:        VecGhostUpdateBegin(v,ADD_VALUES,SCATTER_REVERSE);
    187:        VecGhostUpdateEnd(v,ADD_VALUES,SCATTER_REVERSE);
    188:        VecGhostUpdateBegin(v,INSERT_VALUES,SCATTER_FORWARD);
    189:        VecGhostUpdateEnd(v,INSERT_VALUES,SCATTER_FORWARD);
    190: .ve

    192: .seealso: [](ch_vectors), `Vec`, `VecType`, `VecCreateGhost()`, `VecGhostUpdateEnd()`, `VecGhostGetLocalForm()`,
    193:           `VecGhostRestoreLocalForm()`, `VecCreateGhostWithArray()`
    194: @*/
    195: PetscErrorCode VecGhostUpdateBegin(Vec g, InsertMode insertmode, ScatterMode scattermode)
    196: {
    197:   Vec_MPI  *v;
    198:   PetscBool ismpi, isseq;

    200:   PetscFunctionBegin;
    202:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECMPI, &ismpi));
    203:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECSEQ, &isseq));
    204:   if (ismpi) {
    205:     v = (Vec_MPI *)g->data;
    206:     PetscCheck(v->localrep, PetscObjectComm((PetscObject)g), PETSC_ERR_ARG_WRONG, "Vector is not ghosted");
    207:     if (!v->localupdate) PetscFunctionReturn(PETSC_SUCCESS);
    208:     if (scattermode == SCATTER_REVERSE) {
    209:       PetscCall(VecScatterBegin(v->localupdate, v->localrep, g, insertmode, scattermode));
    210:     } else {
    211:       PetscCall(VecScatterBegin(v->localupdate, g, v->localrep, insertmode, scattermode));
    212:     }
    213:   } else if (isseq) {
    214:     /* Do nothing */
    215:   } else SETERRQ(PetscObjectComm((PetscObject)g), PETSC_ERR_ARG_WRONG, "Vector is not ghosted");
    216:   PetscFunctionReturn(PETSC_SUCCESS);
    217: }

    219: /*@
    220:   VecGhostUpdateEnd - End the vector scatter to update the vector from
    221:   local representation to global or global representation to local.

    223:   Neighbor-wise Collective

    225:   Input Parameters:
    226: + g           - the vector (obtained with `VecCreateGhost()` or `VecDuplicate()`)
    227: . insertmode  - one of `ADD_VALUES`, `MAX_VALUES`, `MIN_VALUES` or `INSERT_VALUES`
    228: - scattermode - one of `SCATTER_FORWARD` or `SCATTER_REVERSE`

    230:   Level: advanced

    232:   Notes:
    233:   Use the following to update the ghost regions with correct values from the owning process
    234: .vb
    235:        VecGhostUpdateBegin(v,INSERT_VALUES,SCATTER_FORWARD);
    236:        VecGhostUpdateEnd(v,INSERT_VALUES,SCATTER_FORWARD);
    237: .ve

    239:   Use the following to accumulate the ghost region values onto the owning processors
    240: .vb
    241:        VecGhostUpdateBegin(v,ADD_VALUES,SCATTER_REVERSE);
    242:        VecGhostUpdateEnd(v,ADD_VALUES,SCATTER_REVERSE);
    243: .ve

    245:   To accumulate the ghost region values onto the owning processors and then update
    246:   the ghost regions correctly, call the later followed by the former, i.e.,
    247: .vb
    248:        VecGhostUpdateBegin(v,ADD_VALUES,SCATTER_REVERSE);
    249:        VecGhostUpdateEnd(v,ADD_VALUES,SCATTER_REVERSE);
    250:        VecGhostUpdateBegin(v,INSERT_VALUES,SCATTER_FORWARD);
    251:        VecGhostUpdateEnd(v,INSERT_VALUES,SCATTER_FORWARD);
    252: .ve

    254: .seealso: [](ch_vectors), `Vec`, `VecType`, `VecCreateGhost()`, `VecGhostUpdateBegin()`, `VecGhostGetLocalForm()`,
    255:           `VecGhostRestoreLocalForm()`, `VecCreateGhostWithArray()`
    256: @*/
    257: PetscErrorCode VecGhostUpdateEnd(Vec g, InsertMode insertmode, ScatterMode scattermode)
    258: {
    259:   Vec_MPI  *v;
    260:   PetscBool ismpi;

    262:   PetscFunctionBegin;
    264:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECMPI, &ismpi));
    265:   if (ismpi) {
    266:     v = (Vec_MPI *)g->data;
    267:     PetscCheck(v->localrep, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Vector is not ghosted");
    268:     if (!v->localupdate) PetscFunctionReturn(PETSC_SUCCESS);
    269:     if (scattermode == SCATTER_REVERSE) {
    270:       PetscCall(VecScatterEnd(v->localupdate, v->localrep, g, insertmode, scattermode));
    271:     } else {
    272:       PetscCall(VecScatterEnd(v->localupdate, g, v->localrep, insertmode, scattermode));
    273:     }
    274:   }
    275:   PetscFunctionReturn(PETSC_SUCCESS);
    276: }