Actual source code: dagetarray.c

  1: #include <petsc/private/dmdaimpl.h>

  3: /*MC
  4:   DMDAVecGetArrayF90 - see Fortran Notes at `DMDAVecGetArray()`

  6:   Level: intermediate
  7: M*/

  9: /*@C
 10:   DMDAVecGetArray - Returns a multiple dimension array that shares data with
 11:   the underlying vector and is indexed using the global or local dimensions of a `DMDA`.

 13:   Logically Collective

 15:   Input Parameters:
 16: + da  - the `DMDA`
 17: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

 19:   Output Parameter:
 20: . array - the array

 22:   Level: intermediate

 24:   Notes:
 25:   Call `DMDAVecRestoreArray()` once you have finished accessing the vector entries.

 27:   In C, the indexing is "backwards" from what expects: array[k][j][i] NOT array[i][j][k]!

 29:   If `vec` is a local vector (obtained with DMCreateLocalVector() etc) then the ghost point locations are accessible. If it is
 30:   a global vector then the ghost points are not accessible. Of course, with a local vector you will have had to do the
 31:   appropriate `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()` to have correct values in the ghost locations.

 33:   The accessible indices are `array[zs:zs+zm-1][ys:ys+ym-1][xs:xs+xm-1]` where the values are obtained from
 34:   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.

 36:   Fortran Notes:
 37:   Use `DMDAVecGetArrayF90()` and pass for the array type `PetscScalar`,pointer :: array(:,...,:) of the appropriate
 38:   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
 39:   dimension of the `DMDA`.

 41:   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when dof is 1) otherwise
 42:   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
 43:   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.

 45: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArray()`, `DMDAVecRestoreArrayDOF()`
 46:           `DMDAVecGetArrayDOF()`, `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`,
 47:           `DMStagVecGetArray()`
 48: @*/
 49: PetscErrorCode DMDAVecGetArray(DM da, Vec vec, void *array)
 50: {
 51:   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;

 53:   PetscFunctionBegin;
 56:   PetscAssertPointer(array, 3);
 57:   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
 58:   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
 59:   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));

 61:   /* Handle case where user passes in global vector as opposed to local */
 62:   PetscCall(VecGetLocalSize(vec, &N));
 63:   if (N == xm * ym * zm * dof) {
 64:     gxm = xm;
 65:     gym = ym;
 66:     gzm = zm;
 67:     gxs = xs;
 68:     gys = ys;
 69:     gzs = zs;
 70:   } 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:   if (dim == 1) {
 73:     PetscCall(VecGetArray1d(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
 74:   } else if (dim == 2) {
 75:     PetscCall(VecGetArray2d(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
 76:   } else if (dim == 3) {
 77:     PetscCall(VecGetArray3d(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
 78:   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
 79:   PetscFunctionReturn(PETSC_SUCCESS);
 80: }

 82: /*MC
 83:   DMDAVecRestoreArrayF90 - see Fortran Notes at `DMDAVecRestoreArray()`

 85:   Level: intermediate
 86: M*/

 88: /*@
 89:   DMDAVecRestoreArray - Restores a multiple dimension array obtained with `DMDAVecGetArray()`

 91:   Logically Collective

 93:   Input Parameters:
 94: + da    - the `DMDA`
 95: . vec   - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
 96: - array - the `array` pointer

 98:   Level: intermediate

100:   Fortran Note:
101:   Use `DMDAVecRestoreArayF90()`

103: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `DMDAVecRestoreArayF90()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArray()`,
104:           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`,
105:           `DMDStagVecRestoreArray()`
106: @*/
107: PetscErrorCode DMDAVecRestoreArray(DM da, Vec vec, void *array)
108: {
109:   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;

111:   PetscFunctionBegin;
114:   PetscAssertPointer(array, 3);
115:   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
116:   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
117:   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));

119:   /* Handle case where user passes in global vector as opposed to local */
120:   PetscCall(VecGetLocalSize(vec, &N));
121:   if (N == xm * ym * zm * dof) {
122:     gxm = xm;
123:     gym = ym;
124:     gzm = zm;
125:     gxs = xs;
126:     gys = ys;
127:     gzs = zs;
128:   } 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:   if (dim == 1) {
131:     PetscCall(VecRestoreArray1d(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
132:   } else if (dim == 2) {
133:     PetscCall(VecRestoreArray2d(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
134:   } else if (dim == 3) {
135:     PetscCall(VecRestoreArray3d(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
136:   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
137:   PetscFunctionReturn(PETSC_SUCCESS);
138: }

140: /*MC
141:   DMDAVecGetArrayWriteF90 - see Fortran Notes at `DMDAVecGetArrayWrite()`

143:   Level: intermediate
144: M*/

146: /*@C
147:   DMDAVecGetArrayWrite - Returns a multiple dimension array that shares data with
148:   the underlying vector and is indexed using the global or local dimensions of a `DMDA`.

150:   Logically Collective

152:   Input Parameters:
153: + da  - the `DMDA`
154: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

156:   Output Parameter:
157: . array - the array

159:   Level: intermediate

161:   Notes:
162:   Call `DMDAVecRestoreArray()` once you have finished accessing the vector entries.

164:   In C, the indexing is "backwards" from what expects: array[k][j][i] NOT array[i][j][k]!

166:   if `vec` is a local vector (obtained with `DMCreateLocalVector()` etc) then the ghost point locations are accessible. If it is
167:   a global vector then the ghost points are not accessible. Of course with the local vector you will have had to do the
168:   appropriate `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()` to have correct values in the ghost locations.

170:   The accessible indices are `array[zs:zs+zm-1][ys:ys+ym-1][xs:xs+xm-1]` where the values are obtained from
171:   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.

173:   Fortran Notes:
174:   Use `DMDAVecGetArrayWriteF90()` and pass for the array type PetscScalar,pointer :: array(:,...,:) of the appropriate
175:   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
176:   dimension of the `DMDA`.

178:   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when dof is 1) otherwise
179:   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
180:   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.

182:   Developer Note:
183:   This has code duplication with `DMDAVecGetArray()` and `DMDAVecGetArrayRead()`

185: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecRestoreArrayDOF()`
186:           `DMDAVecGetArrayDOF()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`
187: @*/
188: PetscErrorCode DMDAVecGetArrayWrite(DM da, Vec vec, void *array)
189: {
190:   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;

192:   PetscFunctionBegin;
195:   PetscAssertPointer(array, 3);
196:   if (da->localSection) {
197:     PetscCall(VecGetArrayWrite(vec, (PetscScalar **)array));
198:     PetscFunctionReturn(PETSC_SUCCESS);
199:   }
200:   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
201:   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
202:   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));

204:   /* Handle case where user passes in global vector as opposed to local */
205:   PetscCall(VecGetLocalSize(vec, &N));
206:   if (N == xm * ym * zm * dof) {
207:     gxm = xm;
208:     gym = ym;
209:     gzm = zm;
210:     gxs = xs;
211:     gys = ys;
212:     gzs = zs;
213:   } 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:   if (dim == 1) {
216:     PetscCall(VecGetArray1dWrite(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
217:   } else if (dim == 2) {
218:     PetscCall(VecGetArray2dWrite(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
219:   } else if (dim == 3) {
220:     PetscCall(VecGetArray3dWrite(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
221:   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
222:   PetscFunctionReturn(PETSC_SUCCESS);
223: }

225: /*MC
226:   DMDAVecRestoreArrayWriteF90 - see Fortran Notes at `DMDAVecRestoreArrayWrite()`

228:   Level: intermediate
229: M*/

231: /*@
232:   DMDAVecRestoreArrayWrite - Restores a multiple dimension array obtained with `DMDAVecGetArrayWrite()`

234:   Logically Collective

236:   Input Parameters:
237: + da    - the `DMDA`
238: . vec   - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
239: - array - the `array` pointer

241:   Level: intermediate

243:   Fortran Note:
244:   Use `DMDAVecRestoreArayWriteF90()`

246: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArrayWrite()`,
247:           `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`
248: @*/
249: PetscErrorCode DMDAVecRestoreArrayWrite(DM da, Vec vec, void *array)
250: {
251:   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;

253:   PetscFunctionBegin;
256:   PetscAssertPointer(array, 3);
257:   if (da->localSection) {
258:     PetscCall(VecRestoreArray(vec, (PetscScalar **)array));
259:     PetscFunctionReturn(PETSC_SUCCESS);
260:   }
261:   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
262:   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
263:   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));

265:   /* Handle case where user passes in global vector as opposed to local */
266:   PetscCall(VecGetLocalSize(vec, &N));
267:   if (N == xm * ym * zm * dof) {
268:     gxm = xm;
269:     gym = ym;
270:     gzm = zm;
271:     gxs = xs;
272:     gys = ys;
273:     gzs = zs;
274:   } 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:   if (dim == 1) {
277:     PetscCall(VecRestoreArray1dWrite(vec, gxm * dof, gxs * dof, (PetscScalar **)array));
278:   } else if (dim == 2) {
279:     PetscCall(VecRestoreArray2dWrite(vec, gym, gxm * dof, gys, gxs * dof, (PetscScalar ***)array));
280:   } else if (dim == 3) {
281:     PetscCall(VecRestoreArray3dWrite(vec, gzm, gym, gxm * dof, gzs, gys, gxs * dof, (PetscScalar ****)array));
282:   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
283:   PetscFunctionReturn(PETSC_SUCCESS);
284: }

286: /*@C
287:   DMDAVecGetArrayDOF - Returns a multiple dimension array that shares data with
288:   the underlying vector and is indexed using the global or local dimensions of a `DMDA`

290:   Logically Collective

292:   Input Parameters:
293: + da  - the `DMDA`
294: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

296:   Output Parameter:
297: . array - the `array` pointer

299:   Level: intermediate

301:   Notes:
302:   Call `DMDAVecRestoreArrayDOF()` once you have finished accessing the vector entries.

304:   In C, the indexing is "backwards" from what expects: array[k][j][i][DOF] NOT array[i][j][k][DOF]

306:   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
307:   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.

309:   Fortran Notes:
310:   Use `DMDAVecGetArrayF90()` and pass for the array type PetscScalar,pointer :: array(:,...,:) of the appropriate
311:   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
312:   dimension of the `DMDA`.

314:   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when ndof is 1) otherwise
315:   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
316:   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.

318: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecRestoreArrayDOF()`,
319:           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`, `DMDAVecGetArrayDOFRead()`
320: @*/
321: PetscErrorCode DMDAVecGetArrayDOF(DM da, Vec vec, void *array)
322: {
323:   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;

325:   PetscFunctionBegin;
326:   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
327:   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
328:   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));

330:   /* Handle case where user passes in global vector as opposed to local */
331:   PetscCall(VecGetLocalSize(vec, &N));
332:   if (N == xm * ym * zm * dof) {
333:     gxm = xm;
334:     gym = ym;
335:     gzm = zm;
336:     gxs = xs;
337:     gys = ys;
338:     gzs = zs;
339:   } 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:   if (dim == 1) {
342:     PetscCall(VecGetArray2d(vec, gxm, dof, gxs, 0, (PetscScalar ***)array));
343:   } else if (dim == 2) {
344:     PetscCall(VecGetArray3d(vec, gym, gxm, dof, gys, gxs, 0, (PetscScalar ****)array));
345:   } else if (dim == 3) {
346:     PetscCall(VecGetArray4d(vec, gzm, gym, gxm, dof, gzs, gys, gxs, 0, (PetscScalar *****)array));
347:   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
348:   PetscFunctionReturn(PETSC_SUCCESS);
349: }

351: /*@
352:   DMDAVecRestoreArrayDOF - Restores a multiple dimension array obtained with `DMDAVecGetArrayDOF()`

354:   Logically Collective

356:   Input Parameters:
357: + da    - the `DMDA`
358: . vec   - vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
359: - array - the `array` point

361:   Level: intermediate

363:   Fortran Note:
364:   Use `DMDAVecRestoreArayF90()`

366: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecGetArrayDOF()`,
367:           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`
368: @*/
369: PetscErrorCode DMDAVecRestoreArrayDOF(DM da, Vec vec, void *array)
370: {
371:   PetscInt xs, ys, zs, xm, ym, zm, gxs, gys, gzs, gxm, gym, gzm, N, dim, dof;

373:   PetscFunctionBegin;
374:   PetscCall(DMDAGetCorners(da, &xs, &ys, &zs, &xm, &ym, &zm));
375:   PetscCall(DMDAGetGhostCorners(da, &gxs, &gys, &gzs, &gxm, &gym, &gzm));
376:   PetscCall(DMDAGetInfo(da, &dim, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL));

378:   /* Handle case where user passes in global vector as opposed to local */
379:   PetscCall(VecGetLocalSize(vec, &N));
380:   if (N == xm * ym * zm * dof) {
381:     gxm = xm;
382:     gym = ym;
383:     gzm = zm;
384:     gxs = xs;
385:     gys = ys;
386:     gzs = zs;
387:   }

389:   if (dim == 1) {
390:     PetscCall(VecRestoreArray2d(vec, gxm, dof, gxs, 0, (PetscScalar ***)array));
391:   } else if (dim == 2) {
392:     PetscCall(VecRestoreArray3d(vec, gym, gxm, dof, gys, gxs, 0, (PetscScalar ****)array));
393:   } else if (dim == 3) {
394:     PetscCall(VecRestoreArray4d(vec, gzm, gym, gxm, dof, gzs, gys, gxs, 0, (PetscScalar *****)array));
395:   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "DMDA dimension not 1, 2, or 3, it is %" PetscInt_FMT, dim);
396:   PetscFunctionReturn(PETSC_SUCCESS);
397: }

399: /*MC
400:   DMDAVecGetArrayReadF90 - see Fortran Notes at `DMDAVecGetArrayRead()`

402:   Level: intermediate
403: M*/

405: /*@C
406:   DMDAVecGetArrayRead - Returns a multiple dimension array that shares data with
407:   the underlying vector and is indexed using the global or local dimensions of a `DMDA`.

409:   Not Collective

411:   Input Parameters:
412: + da  - the `DMDA`
413: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

415:   Output Parameter:
416: . array - the array

418:   Level: intermediate

420:   Notes:
421:   Call `DMDAVecRestoreArrayRead()` once you have finished accessing the vector entries.

423:   In C, the indexing is "backwards" from what expects: array[k][j][i] NOT array[i][j][k]!

425:   If `vec` is a local vector (obtained with `DMCreateLocalVector()` etc) then the ghost point locations are accessible. If it is
426:   a global vector then the ghost points are not accessible. Of course with the local vector you will have had to do the
427:   appropriate `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()` to have correct values in the ghost locations.

429:   The accessible indices are `array[zs:zs+zm-1][ys:ys+ym-1][xs:xs+xm-1]` where the values are obtained from
430:   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.

432:   Fortran Notes:
433:   Use `DMDAVecGetArrayReadF90()` and pass for the array type `PetscScalar`,pointer :: array(:,...,:) of the appropriate
434:   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
435:   dimension of the `DMDA`.

437:   The order of the indices is `array(xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` (when dof is 1) otherwise
438:   `array(0:dof-1,xs:xs+xm-1,ys:ys+ym-1,zs:zs+zm-1)` where the values are obtained from
439:   `DMDAGetCorners()` for a global vector or `DMDAGetGhostCorners()` for a local vector.

441: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAVecGetArrayReadF90()`, `DMDAGetGhostCorners()`,
442: `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArrayRead()`,
443: `DMDAVecRestoreArrayDOF()`, `DMDAVecGetArrayDOF()`, `DMDAVecGetArray()`,
444: `DMDAVecRestoreArray()`, `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;

450:   PetscFunctionBegin;
453:   PetscAssertPointer(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));

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);

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

479: /*MC
480:   DMDAVecRestoreArrayReadF90 - see Fortran Notes at `DMDAVecRestoreArrayRead()`

482:   Level: intermediate
483: M*/

485: /*@
486:   DMDAVecRestoreArrayRead - Restores a multiple dimension array obtained with `DMDAVecGetArrayRead()`

488:   Not Collective

490:   Input Parameters:
491: + da    - the `DMDA`
492: . vec   - vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
493: - array - the `array` pointer

495:   Level: intermediate

497:   Fortran Note:
498:   Use `DMDAVecRestoreArrayReadF90()`

500: .seealso: [](sec_struct), [](sec_struct_set), `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;

508:   PetscFunctionBegin;
511:   PetscAssertPointer(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));

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);

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

537: /*@C
538:   DMDAVecGetArrayDOFRead - Returns a multiple dimension array that shares data with
539:   the underlying vector and is indexed using the global or local dimensions of a `DMDA`

541:   Not Collective

543:   Input Parameters:
544: + da  - the `DMDA`
545: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

547:   Output Parameter:
548: . array - the array

550:   Level: intermediate

552:   Notes:
553:   Call `DMDAVecRestoreArrayDOFRead()` once you have finished accessing the vector entries.

555:   In C, the indexing is "backwards" from what expects: array[k][j][i][DOF] NOT array[i][j][k][DOF]!

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.

560:   Fortran Notes:
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`.

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.

569: .seealso: [](sec_struct), [](sec_struct_set), `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;

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));

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);

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

602: /*@
603:   DMDAVecRestoreArrayDOFRead - Restores a multiple dimension array obtained with `DMDAVecGetArrayDOFRead()`

605:   Not Collective

607:   Input Parameters:
608: + da    - the `DMDA`
609: . vec   - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
610: - array - the `array` pointer

612:   Level: intermediate

614:   Fortran Note:
615:   Use `DMDAVecRestoreArrayReadF90()`

617: .seealso: [](sec_struct), [](sec_struct_set), `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;

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));

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

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

650: /*@C
651:   DMDAVecGetArrayDOFWrite - Returns a multiple dimension array that shares data with
652:   the underlying vector and is indexed using the global or local dimensions of a `DMDA`

654:   Not Collective

656:   Input Parameters:
657: + da  - the `DMDA`
658: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

660:   Output Parameter:
661: . array - the array

663:   Level: intermediate

665:   Notes:
666:   Call `DMDAVecRestoreArrayDOFWrite()` once you have finished accessing the vector entries.

668:   In C, the indexing is "backwards" from what expects: array[k][j][i][DOF] NOT array[i][j][k][DOF]!

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.

673:   Fortran Notes:
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`.

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.

682: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `DMDAVecRestoreArrayWriteF90()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecGetArrayDOF()`,
683:           `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;

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));

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);

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

715: /*@
716:   DMDAVecRestoreArrayDOFWrite - Restores a multiple dimension array obtained with `DMDAVecGetArrayDOFWrite()`

718:   Not Collective

720:   Input Parameters:
721: + da    - the `DMDA`
722: . vec   - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`
723: - array - the `array` pointer

725:   Level: intermediate

727:   Fortran Note:
728:   Use `DMDAVecRestoreArrayWriteF90()`

730: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArray()`, `DMDAVecGetArrayDOF()`, `DMDAVecRestoreArrayDOF()`,
731:           `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;

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));

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

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