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