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:      VecGetArrayRead(xlocal, &xvalues);
 57:         // access the non-ghost values in locations xvalues[0:n-1] and ghost values in locations xvalues[n:n+nghost];
 58:      VecRestoreArrayRead(xlocal, &xvalues);
 59:      VecGhostRestoreLocalForm(x, &xlocal);
 60: .ve

 62:   One must call `VecGhostRestoreLocalForm()` once finished using the object.

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

 70:   PetscFunctionBegin;
 72:   PetscAssertPointer(l, 2);

 74:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECSEQ, &isseq));
 75:   PetscCall(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) PetscCall(VecGhostStateSync_Private(g, *l));
 85:   PetscFunctionReturn(PETSC_SUCCESS);
 86: }

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

 91:   Not Collective

 93:   Input Parameters:
 94: + g - the global vector
 95: - l - the local vector

 97:   Output Parameter:
 98: . flg - `PETSC_TRUE` if `l` is the local form

100:   Level: advanced

102: .seealso: [](ch_vectors), `Vec`, `VecType`, `VecCreateGhost()`, `VecGhostRestoreLocalForm()`, `VecCreateGhostWithArray()`, `VecGhostGetLocalForm()`
103: @*/
104: PetscErrorCode VecGhostIsLocalForm(Vec g, Vec l, PetscBool *flg)
105: {
106:   PetscBool isseq, ismpi;

108:   PetscFunctionBegin;

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

124: /*@
125:   VecGhostRestoreLocalForm - Restores the local ghosted representation of
126:   a parallel vector obtained with `VecGhostGetLocalForm()`.

128:   Logically Collective

130:   Input Parameters:
131: + g - the global vector
132: - l - the local (ghosted) representation

134:   Level: advanced

136: .seealso: [](ch_vectors), `VecGhostUpdateBegin()`, `VecGhostUpdateEnd()`, `Vec`, `VecType`, `VecCreateGhost()`, `VecGhostGetLocalForm()`, `VecCreateGhostWithArray()`
137: @*/
138: PetscErrorCode VecGhostRestoreLocalForm(Vec g, Vec *l)
139: {
140:   PetscFunctionBegin;
141:   if (*l) PetscCall(VecGhostStateSync_Private(g, *l));
142:   PetscFunctionReturn(PETSC_SUCCESS);
143: }

145: /*@
146:   VecGhostUpdateBegin - Begins the vector scatter to update the vector from
147:   local representation to global or global representation to local.

149:   Neighbor-wise Collective

151:   Input Parameters:
152: + g           - the vector (obtained with `VecCreateGhost()` or `VecDuplicate()`)
153: . insertmode  - one of `ADD_VALUES`, `MAX_VALUES`, `MIN_VALUES` or `INSERT_VALUES`
154: - scattermode - one of `SCATTER_FORWARD` (update ghosts) or `SCATTER_REVERSE` (update local values from ghosts)

156:   Level: advanced

158:   Notes:
159:   Use the following to update the ghost regions with correct values from the owning process
160: .vb
161:        VecGhostUpdateBegin(v,INSERT_VALUES,SCATTER_FORWARD);
162:        VecGhostUpdateEnd(v,INSERT_VALUES,SCATTER_FORWARD);
163: .ve

165:   Use the following to accumulate the ghost region values onto the owning processors
166: .vb
167:        VecGhostUpdateBegin(v,ADD_VALUES,SCATTER_REVERSE);
168:        VecGhostUpdateEnd(v,ADD_VALUES,SCATTER_REVERSE);
169: .ve

171:   To accumulate the ghost region values onto the owning processors and then update
172:   the ghost regions correctly, call the latter followed by the former, i.e.,
173: .vb
174:        VecGhostUpdateBegin(v,ADD_VALUES,SCATTER_REVERSE);
175:        VecGhostUpdateEnd(v,ADD_VALUES,SCATTER_REVERSE);
176:        VecGhostUpdateBegin(v,INSERT_VALUES,SCATTER_FORWARD);
177:        VecGhostUpdateEnd(v,INSERT_VALUES,SCATTER_FORWARD);
178: .ve

180: .seealso: [](ch_vectors), `Vec`, `VecType`, `VecCreateGhost()`, `VecGhostUpdateEnd()`, `VecGhostGetLocalForm()`,
181:           `VecGhostRestoreLocalForm()`, `VecCreateGhostWithArray()`
182: @*/
183: PetscErrorCode VecGhostUpdateBegin(Vec g, InsertMode insertmode, ScatterMode scattermode)
184: {
185:   Vec_MPI  *v;
186:   PetscBool ismpi, isseq;

188:   PetscFunctionBegin;
190:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECMPI, &ismpi));
191:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECSEQ, &isseq));
192:   if (ismpi) {
193:     v = (Vec_MPI *)g->data;
194:     PetscCheck(v->localrep, PetscObjectComm((PetscObject)g), PETSC_ERR_ARG_WRONG, "Vector is not ghosted");
195:     if (!v->localupdate) PetscFunctionReturn(PETSC_SUCCESS);
196:     if (scattermode == SCATTER_REVERSE) {
197:       PetscCall(VecScatterBegin(v->localupdate, v->localrep, g, insertmode, scattermode));
198:     } else {
199:       PetscCall(VecScatterBegin(v->localupdate, g, v->localrep, insertmode, scattermode));
200:     }
201:   } else if (isseq) {
202:     /* Do nothing */
203:   } else SETERRQ(PetscObjectComm((PetscObject)g), PETSC_ERR_ARG_WRONG, "Vector is not ghosted");
204:   PetscFunctionReturn(PETSC_SUCCESS);
205: }

207: /*@
208:   VecGhostUpdateEnd - End the vector scatter to update the vector from
209:   local representation to global or global representation to local.

211:   Neighbor-wise Collective

213:   Input Parameters:
214: + g           - the vector (obtained with `VecCreateGhost()` or `VecDuplicate()`)
215: . insertmode  - one of `ADD_VALUES`, `MAX_VALUES`, `MIN_VALUES` or `INSERT_VALUES`
216: - scattermode - one of `SCATTER_FORWARD` (update ghosts) or `SCATTER_REVERSE` (update local values from ghosts)

218:   Level: advanced

220:   Notes:
221:   Use the following to update the ghost regions with correct values from the owning process
222: .vb
223:        VecGhostUpdateBegin(v,INSERT_VALUES,SCATTER_FORWARD);
224:        VecGhostUpdateEnd(v,INSERT_VALUES,SCATTER_FORWARD);
225: .ve

227:   Use the following to accumulate the ghost region values onto the owning processors
228: .vb
229:        VecGhostUpdateBegin(v,ADD_VALUES,SCATTER_REVERSE);
230:        VecGhostUpdateEnd(v,ADD_VALUES,SCATTER_REVERSE);
231: .ve

233:   To accumulate the ghost region values onto the owning processors and then update
234:   the ghost regions correctly, call the later followed by the former, i.e.,
235: .vb
236:        VecGhostUpdateBegin(v,ADD_VALUES,SCATTER_REVERSE);
237:        VecGhostUpdateEnd(v,ADD_VALUES,SCATTER_REVERSE);
238:        VecGhostUpdateBegin(v,INSERT_VALUES,SCATTER_FORWARD);
239:        VecGhostUpdateEnd(v,INSERT_VALUES,SCATTER_FORWARD);
240: .ve

242: .seealso: [](ch_vectors), `Vec`, `VecType`, `VecCreateGhost()`, `VecGhostUpdateBegin()`, `VecGhostGetLocalForm()`,
243:           `VecGhostRestoreLocalForm()`, `VecCreateGhostWithArray()`
244: @*/
245: PetscErrorCode VecGhostUpdateEnd(Vec g, InsertMode insertmode, ScatterMode scattermode)
246: {
247:   Vec_MPI  *v;
248:   PetscBool ismpi;

250:   PetscFunctionBegin;
252:   PetscCall(PetscObjectTypeCompare((PetscObject)g, VECMPI, &ismpi));
253:   if (ismpi) {
254:     v = (Vec_MPI *)g->data;
255:     PetscCheck(v->localrep, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Vector is not ghosted");
256:     if (!v->localupdate) PetscFunctionReturn(PETSC_SUCCESS);
257:     if (scattermode == SCATTER_REVERSE) {
258:       PetscCall(VecScatterEnd(v->localupdate, v->localrep, g, insertmode, scattermode));
259:     } else {
260:       PetscCall(VecScatterEnd(v->localupdate, g, v->localrep, insertmode, scattermode));
261:     }
262:   }
263:   PetscFunctionReturn(PETSC_SUCCESS);
264: }