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:   PetscFunctionBegin;
 23:   PetscCall(PetscObjectStateGet((PetscObject)g, &gstate));
 24:   PetscCall(PetscObjectStateGet((PetscObject)l, &lstate));
 25:   PetscCall(PetscObjectStateSet((PetscObject)g, PetscMax(gstate, lstate)));
 26:   PetscCall(PetscObjectStateSet((PetscObject)l, PetscMax(gstate, lstate)));
 27:   PetscFunctionReturn(PETSC_SUCCESS);
 28: }

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

 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:     Level: advanced

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

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

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

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

 72:   PetscFunctionBegin;

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

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

 96:     Not Collective

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

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

105:     Level: advanced

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

113:   PetscFunctionBegin;

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

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

133:     Logically Collective

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

139:     Level: advanced

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

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

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

162:    Neighbor-wise Collective

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

169:    Level: advanced

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

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

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

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

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

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

224:    Neighbor-wise Collective

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

231:    Level: advanced

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

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

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

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

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