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