xref: /petsc/src/dm/impls/da/dagetarray.c (revision 3f02e49b19195914bf17f317a25cb39636853415)
1 #include <petsc/private/dmdaimpl.h> /*I   "petscdmda.h"   I*/
2 
3 /*@C
4   DMDAVecGetArray - Returns a multiple dimension array that shares data with
5   the underlying vector and is indexed using the global or local dimensions of a `DMDA`.
6 
7   Logically Collective
8 
9   Input Parameters:
10 + da  - the `DMDA`
11 - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
12 
13   Output Parameter:
14 . array - the array
15 
16   Level: intermediate
17 
18   Notes:
19   Call `DMDAVecRestoreArray()` once you have finished accessing the vector entries.
20 
21   In C, the indexing is "backwards" from what expects: array[k][j][i] NOT array[i][j][k]!
22 
23   If `vec` is a local vector (obtained with DMCreateLocalVector() etc) then the ghost point locations are accessible. If it is
24   a global vector then the ghost points are not accessible. Of course, with a local vector you will have had to do the
25   appropriate `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()` to have correct values in the ghost locations.
26 
27   The accessible indices are `array[zs:zs+zm-1][ys:ys+ym-1][xs:xs+xm-1]` where the values are obtained from
28   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
29 
30   Fortran Notes:
31   Use `DMDAVecGetArray()` and pass for the array type `PetscScalar`,pointer :: array(:,...,:) of the appropriate
32   dimension. For a `DMDA` created with a dof of 1 use the dimension of the `DMDA`, for a `DMDA` created with a dof greater than 1 use one more than the
33   dimension of the `DMDA`.
34 
35   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when dof is 1) otherwise
36   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
37   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
38 
39 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArray()`, `DMDAVecRestoreArrayDOF()`
40           `DMDAVecGetArrayDOF()`, `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`,
41           `DMStagVecGetArray()`
42 @*/
43 PetscErrorCode DMDAVecGetArray(DM da, Vec vec, void *array)
44 {
45   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
46 
47   PetscFunctionBegin;
48   PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
49   PetscValidHeaderSpecific(vec, VEC_CLASSID, 2);
50   PetscAssertPointer(array, 3);
51   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
52   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
53   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
54 
55   /* Handle case where user passes in global vector as opposed to local */
56   PetscCall(VecGetLocalSize(vec, &N));
57   if (N == xm * ym * zm * dof) {
58     gxm = xm;
59     gym = ym;
60     gzm = zm;
61     gxs = xs;
62     gys = ys;
63     gzs = zs;
64   } else PetscCheck(N == gxm * gym * gzm * dof, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Vector local size %" PetscInt_FMT " is not compatible with DMDA local sizes %" PetscInt_FMT " %" PetscInt_FMT, N, xm * ym * zm * dof, gxm * gym * gzm * dof);
65 
66   if (dim == 1) {
67     PetscCall(VecGetArray1d(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
68   } else if (dim == 2) {
69     PetscCall(VecGetArray2d(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
70   } else if (dim == 3) {
71     PetscCall(VecGetArray3d(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
72   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
73   PetscFunctionReturn(PETSC_SUCCESS);
74 }
75 
76 /*@
77   DMDAVecRestoreArray - Restores a multiple dimension array obtained with `DMDAVecGetArray()`
78 
79   Logically Collective
80 
81   Input Parameters:
82 + da    - the `DMDA`
83 . vec   - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
84 - array - the `array` pointer
85 
86   Level: intermediate
87 
88 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArray()`,
89           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`,
90           `DMStagVecRestoreArray()`
91 @*/
92 PetscErrorCode DMDAVecRestoreArray(DM da, Vec vec, void *array)
93 {
94   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
95 
96   PetscFunctionBegin;
97   PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
98   PetscValidHeaderSpecific(vec, VEC_CLASSID, 2);
99   PetscAssertPointer(array, 3);
100   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
101   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
102   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
103 
104   /* Handle case where user passes in global vector as opposed to local */
105   PetscCall(VecGetLocalSize(vec, &N));
106   if (N == xm * ym * zm * dof) {
107     gxm = xm;
108     gym = ym;
109     gzm = zm;
110     gxs = xs;
111     gys = ys;
112     gzs = zs;
113   } else PetscCheck(N == gxm * gym * gzm * dof, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Vector local size %" PetscInt_FMT " is not compatible with DMDA local sizes %" PetscInt_FMT " %" PetscInt_FMT, N, xm * ym * zm * dof, gxm * gym * gzm * dof);
114 
115   if (dim == 1) {
116     PetscCall(VecRestoreArray1d(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
117   } else if (dim == 2) {
118     PetscCall(VecRestoreArray2d(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
119   } else if (dim == 3) {
120     PetscCall(VecRestoreArray3d(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
121   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
122   PetscFunctionReturn(PETSC_SUCCESS);
123 }
124 
125 /*@C
126   DMDAVecGetArrayWrite - Returns a multiple dimension array that shares data with
127   the underlying vector and is indexed using the global or local dimensions of a `DMDA`.
128 
129   Logically Collective
130 
131   Input Parameters:
132 + da  - the `DMDA`
133 - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
134 
135   Output Parameter:
136 . array - the array
137 
138   Level: intermediate
139 
140   Notes:
141   Call `DMDAVecRestoreArray()` once you have finished accessing the vector entries.
142 
143   In C, the indexing is "backwards" from what expects: array[k][j][i] NOT array[i][j][k]!
144 
145   if `vec` is a local vector (obtained with `DMCreateLocalVector()` etc) then the ghost point locations are accessible. If it is
146   a global vector then the ghost points are not accessible. Of course with the local vector you will have had to do the
147   appropriate `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()` to have correct values in the ghost locations.
148 
149   The accessible indices are `array[zs:zs+zm-1][ys:ys+ym-1][xs:xs+xm-1]` where the values are obtained from
150   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
151 
152   Fortran Notes:
153   Use `DMDAVecGetArrayWrite()` and pass for the array type PetscScalar,pointer :: array(:,...,:) of the appropriate
154   dimension. For a `DMDA` created with a dof of 1 use the dimension of the `DMDA`, for a `DMDA` created with a dof greater than 1 use one more than the
155   dimension of the `DMDA`.
156 
157   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when dof is 1) otherwise
158   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
159   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
160 
161   Developer Note:
162   This has code duplication with `DMDAVecGetArray()` and `DMDAVecGetArrayRead()`
163 
164 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecRestoreArrayDOF()`
165           `DMDAVecGetArrayDOF()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`
166 @*/
167 PetscErrorCode DMDAVecGetArrayWrite(DM da, Vec vec, void *array)
168 {
169   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
170 
171   PetscFunctionBegin;
172   PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
173   PetscValidHeaderSpecific(vec, VEC_CLASSID, 2);
174   PetscAssertPointer(array, 3);
175   if (da->localSection) {
176     PetscCall(VecGetArrayWrite(vec, (PetscScalar **)array));
177     PetscFunctionReturn(PETSC_SUCCESS);
178   }
179   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
180   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
181   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
182 
183   /* Handle case where user passes in global vector as opposed to local */
184   PetscCall(VecGetLocalSize(vec, &N));
185   if (N == xm * ym * zm * dof) {
186     gxm = xm;
187     gym = ym;
188     gzm = zm;
189     gxs = xs;
190     gys = ys;
191     gzs = zs;
192   } else PetscCheck(N == gxm * gym * gzm * dof, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Vector local size %" PetscInt_FMT " is not compatible with DMDA local sizes %" PetscInt_FMT " %" PetscInt_FMT, N, xm * ym * zm * dof, gxm * gym * gzm * dof);
193 
194   if (dim == 1) {
195     PetscCall(VecGetArray1dWrite(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
196   } else if (dim == 2) {
197     PetscCall(VecGetArray2dWrite(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
198   } else if (dim == 3) {
199     PetscCall(VecGetArray3dWrite(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
200   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
201   PetscFunctionReturn(PETSC_SUCCESS);
202 }
203 
204 /*@
205   DMDAVecRestoreArrayWrite - Restores a multiple dimension array obtained with `DMDAVecGetArrayWrite()`
206 
207   Logically Collective
208 
209   Input Parameters:
210 + da    - the `DMDA`
211 . vec   - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
212 - array - the `array` pointer
213 
214   Level: intermediate
215 
216 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArrayWrite()`,
217           `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`
218 @*/
219 PetscErrorCode DMDAVecRestoreArrayWrite(DM da, Vec vec, void *array)
220 {
221   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
222 
223   PetscFunctionBegin;
224   PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
225   PetscValidHeaderSpecific(vec, VEC_CLASSID, 2);
226   PetscAssertPointer(array, 3);
227   if (da->localSection) {
228     PetscCall(VecRestoreArray(vec, (PetscScalar **)array));
229     PetscFunctionReturn(PETSC_SUCCESS);
230   }
231   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
232   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
233   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
234 
235   /* Handle case where user passes in global vector as opposed to local */
236   PetscCall(VecGetLocalSize(vec, &N));
237   if (N == xm * ym * zm * dof) {
238     gxm = xm;
239     gym = ym;
240     gzm = zm;
241     gxs = xs;
242     gys = ys;
243     gzs = zs;
244   } else PetscCheck(N == gxm * gym * gzm * dof, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Vector local size %" PetscInt_FMT " is not compatible with DMDA local sizes %" PetscInt_FMT " %" PetscInt_FMT, N, xm * ym * zm * dof, gxm * gym * gzm * dof);
245 
246   if (dim == 1) {
247     PetscCall(VecRestoreArray1dWrite(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
248   } else if (dim == 2) {
249     PetscCall(VecRestoreArray2dWrite(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
250   } else if (dim == 3) {
251     PetscCall(VecRestoreArray3dWrite(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
252   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
253   PetscFunctionReturn(PETSC_SUCCESS);
254 }
255 
256 /*@C
257   DMDAVecGetArrayDOF - Returns a multiple dimension array that shares data with
258   the underlying vector and is indexed using the global or local dimensions of a `DMDA`
259 
260   Logically Collective
261 
262   Input Parameters:
263 + da  - the `DMDA`
264 - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
265 
266   Output Parameter:
267 . array - the `array` pointer
268 
269   Level: intermediate
270 
271   Notes:
272   Call `DMDAVecRestoreArrayDOF()` once you have finished accessing the vector entries.
273 
274   In C, the indexing is "backwards" from what expects: array[k][j][i][DOF] NOT array[i][j][k][DOF]
275 
276   The accessible indices are `array[zs:zs+zm-1][ys:ys+ym-1][xs:xs+xm-1][0:ndof-1]` where the values are obtained from
277   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
278 
279   Fortran Notes:
280   Use `DMDAVecGetArray()` and pass for the array type PetscScalar,pointer :: array(:,...,:) of the appropriate
281   dimension. For a `DMDA` created with a dof of 1 use the dimension of the `DMDA`, for a `DMDA` created with a dof greater than 1 use one more than the
282   dimension of the `DMDA`.
283 
284   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when ndof is 1) otherwise
285   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
286   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
287 
288 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecRestoreArrayDOF()`,
289           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`, `DMDAVecGetArrayDOFRead()`
290 @*/
291 PetscErrorCode DMDAVecGetArrayDOF(DM da, Vec vec, void *array)
292 {
293   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
294 
295   PetscFunctionBegin;
296   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
297   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
298   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
299 
300   /* Handle case where user passes in global vector as opposed to local */
301   PetscCall(VecGetLocalSize(vec, &N));
302   if (N == xm * ym * zm * dof) {
303     gxm = xm;
304     gym = ym;
305     gzm = zm;
306     gxs = xs;
307     gys = ys;
308     gzs = zs;
309   } else PetscCheck(N == gxm * gym * gzm * dof, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Vector local size %" PetscInt_FMT " is not compatible with DMDA local sizes %" PetscInt_FMT " %" PetscInt_FMT, N, xm * ym * zm * dof, gxm * gym * gzm * dof);
310 
311   if (dim == 1) {
312     PetscCall(VecGetArray2d(vec, gxm, dof, gxs, 0, (PetscScalar ***)array));
313   } else if (dim == 2) {
314     PetscCall(VecGetArray3d(vec, gym, gxm, dof, gys, gxs, 0, (PetscScalar ****)array));
315   } else if (dim == 3) {
316     PetscCall(VecGetArray4d(vec, gzm, gym, gxm, dof, gzs, gys, gxs, 0, (PetscScalar *****)array));
317   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
318   PetscFunctionReturn(PETSC_SUCCESS);
319 }
320 
321 /*@
322   DMDAVecRestoreArrayDOF - Restores a multiple dimension array obtained with `DMDAVecGetArrayDOF()`
323 
324   Logically Collective
325 
326   Input Parameters:
327 + da    - the `DMDA`
328 . vec   - vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
329 - array - the `array` point
330 
331   Level: intermediate
332 
333 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecGetArrayDOF()`,
334           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`
335 @*/
336 PetscErrorCode DMDAVecRestoreArrayDOF(DM da, Vec vec, void *array)
337 {
338   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
339 
340   PetscFunctionBegin;
341   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
342   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
343   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
344 
345   /* Handle case where user passes in global vector as opposed to local */
346   PetscCall(VecGetLocalSize(vec, &N));
347   if (N == xm * ym * zm * dof) {
348     gxm = xm;
349     gym = ym;
350     gzm = zm;
351     gxs = xs;
352     gys = ys;
353     gzs = zs;
354   }
355 
356   if (dim == 1) {
357     PetscCall(VecRestoreArray2d(vec, gxm, dof, gxs, 0, (PetscScalar ***)array));
358   } else if (dim == 2) {
359     PetscCall(VecRestoreArray3d(vec, gym, gxm, dof, gys, gxs, 0, (PetscScalar ****)array));
360   } else if (dim == 3) {
361     PetscCall(VecRestoreArray4d(vec, gzm, gym, gxm, dof, gzs, gys, gxs, 0, (PetscScalar *****)array));
362   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
363   PetscFunctionReturn(PETSC_SUCCESS);
364 }
365 
366 /*@C
367   DMDAVecGetArrayRead - Returns a multiple dimension array that shares data with
368   the underlying vector and is indexed using the global or local dimensions of a `DMDA`.
369 
370   Not Collective
371 
372   Input Parameters:
373 + da  - the `DMDA`
374 - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
375 
376   Output Parameter:
377 . array - the array
378 
379   Level: intermediate
380 
381   Notes:
382   Call `DMDAVecRestoreArrayRead()` once you have finished accessing the vector entries.
383 
384   In C, the indexing is "backwards" from what expects: array[k][j][i] NOT array[i][j][k]!
385 
386   If `vec` is a local vector (obtained with `DMCreateLocalVector()` etc) then the ghost point locations are accessible. If it is
387   a global vector then the ghost points are not accessible. Of course with the local vector you will have had to do the
388   appropriate `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()` to have correct values in the ghost locations.
389 
390   The accessible indices are `array[zs:zs+zm-1][ys:ys+ym-1][xs:xs+xm-1]` where the values are obtained from
391   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
392 
393   Fortran Notes:
394   Use `DMDAVecGetArrayRead()` and pass for the array type `PetscScalar`,pointer :: array(:,...,:) of the appropriate
395   dimension. For a `DMDA` created with a dof of 1 use the dimension of the `DMDA`, for a `DMDA` created with a dof greater than 1 use one more than the
396   dimension of the `DMDA`.
397 
398   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when dof is 1) otherwise
399   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
400   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
401 
402 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`,
403 `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArrayRead()`,
404 `DMDAVecRestoreArrayDOF()`, `DMDAVecGetArrayDOF()`, `DMDAVecGetArray()`,
405 `DMDAVecRestoreArray()`, `DMStagVecGetArrayRead()`
406 @*/
407 PetscErrorCode DMDAVecGetArrayRead(DM da, Vec vec, void *array)
408 {
409   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
410 
411   PetscFunctionBegin;
412   PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
413   PetscValidHeaderSpecific(vec, VEC_CLASSID, 2);
414   PetscAssertPointer(array, 3);
415   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
416   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
417   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
418 
419   /* Handle case where user passes in global vector as opposed to local */
420   PetscCall(VecGetLocalSize(vec, &N));
421   if (N == xm * ym * zm * dof) {
422     gxm = xm;
423     gym = ym;
424     gzm = zm;
425     gxs = xs;
426     gys = ys;
427     gzs = zs;
428   } else PetscCheck(N == gxm * gym * gzm * dof, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Vector local size %" PetscInt_FMT " is not compatible with DMDA local sizes %" PetscInt_FMT " %" PetscInt_FMT, N, xm * ym * zm * dof, gxm * gym * gzm * dof);
429 
430   if (dim == 1) {
431     PetscCall(VecGetArray1dRead(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
432   } else if (dim == 2) {
433     PetscCall(VecGetArray2dRead(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
434   } else if (dim == 3) {
435     PetscCall(VecGetArray3dRead(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
436   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
437   PetscFunctionReturn(PETSC_SUCCESS);
438 }
439 
440 /*@
441   DMDAVecRestoreArrayRead - Restores a multiple dimension array obtained with `DMDAVecGetArrayRead()`
442 
443   Not Collective
444 
445   Input Parameters:
446 + da    - the `DMDA`
447 . vec   - vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
448 - array - the `array` pointer
449 
450   Level: intermediate
451 
452 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArrayRead()`,
453           `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`,
454           `DMStagVecRestoreArrayRead()`
455 @*/
456 PetscErrorCode DMDAVecRestoreArrayRead(DM da, Vec vec, void *array)
457 {
458   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
459 
460   PetscFunctionBegin;
461   PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
462   PetscValidHeaderSpecific(vec, VEC_CLASSID, 2);
463   PetscAssertPointer(array, 3);
464   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
465   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
466   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
467 
468   /* Handle case where user passes in global vector as opposed to local */
469   PetscCall(VecGetLocalSize(vec, &N));
470   if (N == xm * ym * zm * dof) {
471     gxm = xm;
472     gym = ym;
473     gzm = zm;
474     gxs = xs;
475     gys = ys;
476     gzs = zs;
477   } else PetscCheck(N == gxm * gym * gzm * dof, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Vector local size %" PetscInt_FMT " is not compatible with DMDA local sizes %" PetscInt_FMT " %" PetscInt_FMT, N, xm * ym * zm * dof, gxm * gym * gzm * dof);
478 
479   if (dim == 1) {
480     PetscCall(VecRestoreArray1dRead(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
481   } else if (dim == 2) {
482     PetscCall(VecRestoreArray2dRead(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
483   } else if (dim == 3) {
484     PetscCall(VecRestoreArray3dRead(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
485   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
486   PetscFunctionReturn(PETSC_SUCCESS);
487 }
488 
489 /*@C
490   DMDAVecGetArrayDOFRead - Returns a multiple dimension array that shares data with
491   the underlying vector and is indexed using the global or local dimensions of a `DMDA`
492 
493   Not Collective
494 
495   Input Parameters:
496 + da  - the `DMDA`
497 - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
498 
499   Output Parameter:
500 . array - the array
501 
502   Level: intermediate
503 
504   Notes:
505   Call `DMDAVecRestoreArrayDOFRead()` once you have finished accessing the vector entries.
506 
507   In C, the indexing is "backwards" from what expects: array[k][j][i][DOF] NOT array[i][j][k][DOF]!
508 
509   The accessible indices are `array[zs:zs+zm-1][ys:ys+ym-1][xs:xs+xm-1]` where the values are obtained from
510   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
511 
512   Fortran Notes:
513   Use  `DMDAVecGetArrayRead()` and pass for the array type PetscScalar,pointer :: array(:,...,:) of the appropriate
514   dimension. For a `DMDA` created with a dof of 1 use the dimension of the `DMDA`, for a `DMDA` created with a dof greater than 1 use one more than the
515   dimension of the `DMDA`.
516 
517   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when dof is 1) otherwise
518   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
519   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
520 
521 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecGetArrayDOF()`,
522           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`
523 @*/
524 PetscErrorCode DMDAVecGetArrayDOFRead(DM da, Vec vec, void *array)
525 {
526   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
527 
528   PetscFunctionBegin;
529   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
530   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
531   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
532 
533   /* Handle case where user passes in global vector as opposed to local */
534   PetscCall(VecGetLocalSize(vec, &N));
535   if (N == xm * ym * zm * dof) {
536     gxm = xm;
537     gym = ym;
538     gzm = zm;
539     gxs = xs;
540     gys = ys;
541     gzs = zs;
542   } else PetscCheck(N == gxm * gym * gzm * dof, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Vector local size %" PetscInt_FMT " is not compatible with DMDA local sizes %" PetscInt_FMT " %" PetscInt_FMT, N, xm * ym * zm * dof, gxm * gym * gzm * dof);
543 
544   if (dim == 1) {
545     PetscCall(VecGetArray2dRead(vec, gxm, dof, gxs, 0, (PetscScalar ***)array));
546   } else if (dim == 2) {
547     PetscCall(VecGetArray3dRead(vec, gym, gxm, dof, gys, gxs, 0, (PetscScalar ****)array));
548   } else if (dim == 3) {
549     PetscCall(VecGetArray4dRead(vec, gzm, gym, gxm, dof, gzs, gys, gxs, 0, (PetscScalar *****)array));
550   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
551   PetscFunctionReturn(PETSC_SUCCESS);
552 }
553 
554 /*@
555   DMDAVecRestoreArrayDOFRead - Restores a multiple dimension array obtained with `DMDAVecGetArrayDOFRead()`
556 
557   Not Collective
558 
559   Input Parameters:
560 + da    - the `DMDA`
561 . vec   - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
562 - array - the `array` pointer
563 
564   Level: intermediate
565 
566 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecGetArrayDOF()`, `DMDAVecRestoreArrayDOF()`,
567           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`
568 @*/
569 PetscErrorCode DMDAVecRestoreArrayDOFRead(DM da, Vec vec, void *array)
570 {
571   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
572 
573   PetscFunctionBegin;
574   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
575   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
576   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
577 
578   /* Handle case where user passes in global vector as opposed to local */
579   PetscCall(VecGetLocalSize(vec, &N));
580   if (N == xm * ym * zm * dof) {
581     gxm = xm;
582     gym = ym;
583     gzm = zm;
584     gxs = xs;
585     gys = ys;
586     gzs = zs;
587   }
588 
589   if (dim == 1) {
590     PetscCall(VecRestoreArray2dRead(vec, gxm, dof, gxs, 0, (PetscScalar ***)array));
591   } else if (dim == 2) {
592     PetscCall(VecRestoreArray3dRead(vec, gym, gxm, dof, gys, gxs, 0, (PetscScalar ****)array));
593   } else if (dim == 3) {
594     PetscCall(VecRestoreArray4dRead(vec, gzm, gym, gxm, dof, gzs, gys, gxs, 0, (PetscScalar *****)array));
595   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
596   PetscFunctionReturn(PETSC_SUCCESS);
597 }
598 
599 /*@C
600   DMDAVecGetArrayDOFWrite - Returns a multiple dimension array that shares data with
601   the underlying vector and is indexed using the global or local dimensions of a `DMDA`
602 
603   Not Collective
604 
605   Input Parameters:
606 + da  - the `DMDA`
607 - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
608 
609   Output Parameter:
610 . array - the array
611 
612   Level: intermediate
613 
614   Notes:
615   Call `DMDAVecRestoreArrayDOFWrite()` once you have finished accessing the vector entries.
616 
617   In C, the indexing is "backwards" from what expects: array[k][j][i][DOF] NOT array[i][j][k][DOF]!
618 
619   The accessible indices are `array[zs:zs+zm-1][ys:ys+ym-1][xs:xs+xm-1][0:dof-1]` where the values are obtained from
620   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
621 
622   Fortran Notes:
623   Use  `DMDAVecGetArrayWrite()` and pass for the array type PetscScalar,pointer :: array(:,...,:) of the appropriate
624   dimension. For a `DMDA` created with a dof of 1 use the dimension of the `DMDA`, for a `DMDA` created with a dof greater than 1 use one more than the
625   dimension of the `DMDA`.
626 
627   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when dof is 1) otherwise
628   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
629   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.
630 
631 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecGetArrayDOF()`,
632           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`
633 @*/
634 PetscErrorCode DMDAVecGetArrayDOFWrite(DM da, Vec vec, void *array)
635 {
636   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
637 
638   PetscFunctionBegin;
639   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
640   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
641   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
642 
643   /* Handle case where user passes in global vector as opposed to local */
644   PetscCall(VecGetLocalSize(vec, &N));
645   if (N == xm * ym * zm * dof) {
646     gxm = xm;
647     gym = ym;
648     gzm = zm;
649     gxs = xs;
650     gys = ys;
651     gzs = zs;
652   } else PetscCheck(N == gxm * gym * gzm * dof, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Vector local size %" PetscInt_FMT " is not compatible with DMDA local sizes %" PetscInt_FMT " %" PetscInt_FMT, N, xm * ym * zm * dof, gxm * gym * gzm * dof);
653 
654   if (dim == 1) {
655     PetscCall(VecGetArray2dWrite(vec, gxm, dof, gxs, 0, (PetscScalar ***)array));
656   } else if (dim == 2) {
657     PetscCall(VecGetArray3dWrite(vec, gym, gxm, dof, gys, gxs, 0, (PetscScalar ****)array));
658   } else if (dim == 3) {
659     PetscCall(VecGetArray4dWrite(vec, gzm, gym, gxm, dof, gzs, gys, gxs, 0, (PetscScalar *****)array));
660   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
661   PetscFunctionReturn(PETSC_SUCCESS);
662 }
663 
664 /*@
665   DMDAVecRestoreArrayDOFWrite - Restores a multiple dimension array obtained with `DMDAVecGetArrayDOFWrite()`
666 
667   Not Collective
668 
669   Input Parameters:
670 + da    - the `DMDA`
671 . vec   - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
672 - array - the `array` pointer
673 
674   Level: intermediate
675 
676 .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecGetArrayDOF()`, `DMDAVecRestoreArrayDOF()`,
677           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`
678 @*/
679 PetscErrorCode DMDAVecRestoreArrayDOFWrite(DM da, Vec vec, void *array)
680 {
681   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;
682 
683   PetscFunctionBegin;
684   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
685   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
686   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));
687 
688   /* Handle case where user passes in global vector as opposed to local */
689   PetscCall(VecGetLocalSize(vec, &N));
690   if (N == xm * ym * zm * dof) {
691     gxm = xm;
692     gym = ym;
693     gzm = zm;
694     gxs = xs;
695     gys = ys;
696     gzs = zs;
697   }
698 
699   if (dim == 1) {
700     PetscCall(VecRestoreArray2dWrite(vec, gxm, dof, gxs, 0, (PetscScalar ***)array));
701   } else if (dim == 2) {
702     PetscCall(VecRestoreArray3dWrite(vec, gym, gxm, dof, gys, gxs, 0, (PetscScalar ****)array));
703   } else if (dim == 3) {
704     PetscCall(VecRestoreArray4dWrite(vec, gzm, gym, gxm, dof, gzs, gys, gxs, 0, (PetscScalar *****)array));
705   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708