Actual source code: commonmpvec.c

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

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

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

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

     22:   PetscObjectStateGet((PetscObject)g,&gstate);
     23:   PetscObjectStateGet((PetscObject)l,&lstate);
     24:   PetscObjectStateSet((PetscObject)g,PetscMax(gstate,lstate));
     25:   PetscObjectStateSet((PetscObject)l,PetscMax(gstate,lstate));
     26:   return 0;
     27: }

     29: /*@
     30:     VecGhostGetLocalForm - Obtains the local ghosted representation of
     31:     a parallel vector (obtained with VecCreateGhost(), VecCreateGhostWithArray()
     32:     or VecCreateSeq()). Returns NULL if the Vec is not ghosted.

     34:     Logically Collective

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

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

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

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

     59:     One should call VecGhostRestoreLocalForm() or VecDestroy() once one is
     60:     finished using the object.

     62:     Level: advanced

     64: .seealso: VecCreateGhost(), VecGhostRestoreLocalForm(), VecCreateGhostWithArray()

     66: @*/
     67: PetscErrorCode  VecGhostGetLocalForm(Vec g,Vec *l)
     68: {
     69:   PetscBool      isseq,ismpi;

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

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

     94:     Not Collective

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

    100:     Output Parameter:
    101: .   flg - PETSC_TRUE if local vector is local form

    103:     Level: advanced

    105: .seealso: VecCreateGhost(), VecGhostRestoreLocalForm(), VecCreateGhostWithArray(), VecGhostGetLocalForm()

    107: @*/
    108: PetscErrorCode VecGhostIsLocalForm(Vec g,Vec l,PetscBool *flg)
    109: {
    110:   PetscBool      isseq,ismpi;

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

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

    131:     Logically Collective

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

    137:     Notes:
    138:     This routine does not actually update the ghost values, but rather it
    139:     returns a sequential vector that includes the locations for the ghost values
    140:     and their current values.

    142:     Level: advanced

    144: .seealso: VecCreateGhost(), VecGhostGetLocalForm(), VecCreateGhostWithArray()
    145: @*/
    146: PetscErrorCode  VecGhostRestoreLocalForm(Vec g,Vec *l)
    147: {
    148:   if (*l) {
    149:     VecGhostStateSync_Private(g,*l);
    150:     PetscObjectDereference((PetscObject)*l);
    151:   }
    152:   return 0;
    153: }

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

    159:    Neighbor-wise Collective on Vec

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

    166:    Notes:
    167:    Use the following to update the ghost regions with correct values from the owning process
    168: .vb
    169:        VecGhostUpdateBegin(v,INSERT_VALUES,SCATTER_FORWARD);
    170:        VecGhostUpdateEnd(v,INSERT_VALUES,SCATTER_FORWARD);
    171: .ve

    173:    Use the following to accumulate the ghost region values onto the owning processors
    174: .vb
    175:        VecGhostUpdateBegin(v,ADD_VALUES,SCATTER_REVERSE);
    176:        VecGhostUpdateEnd(v,ADD_VALUES,SCATTER_REVERSE);
    177: .ve

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

    188:    Level: advanced

    190: .seealso: VecCreateGhost(), VecGhostUpdateEnd(), VecGhostGetLocalForm(),
    191:           VecGhostRestoreLocalForm(),VecCreateGhostWithArray()

    193: @*/
    194: PetscErrorCode  VecGhostUpdateBegin(Vec g,InsertMode insertmode,ScatterMode scattermode)
    195: {
    196:   Vec_MPI        *v;
    197:   PetscBool      ismpi,isseq;

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

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

    221:    Neighbor-wise Collective on Vec

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

    228:    Notes:

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

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

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

    251:    Level: advanced

    253: .seealso: VecCreateGhost(), VecGhostUpdateBegin(), VecGhostGetLocalForm(),
    254:           VecGhostRestoreLocalForm(),VecCreateGhostWithArray()

    256: @*/
    257: PetscErrorCode  VecGhostUpdateEnd(Vec g,InsertMode insertmode,ScatterMode scattermode)
    258: {
    259:   Vec_MPI        *v;
    260:   PetscBool      ismpi;

    263:   PetscObjectTypeCompare((PetscObject)g,VECMPI,&ismpi);
    264:   if (ismpi) {
    265:     v = (Vec_MPI*)g->data;
    267:     if (!v->localupdate) return 0;
    268:     if (scattermode == SCATTER_REVERSE) {
    269:       VecScatterEnd(v->localupdate,v->localrep,g,insertmode,scattermode);
    270:     } else {
    271:       VecScatterEnd(v->localupdate,g,v->localrep,insertmode,scattermode);
    272:     }
    273:   }
    274:   return 0;
    275: }