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

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

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: }