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