Date: 2026-03-01T05:24:36+00:00

Actual source code: dagetarray.c

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

      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`.

      7:   Logically Collective

      9:   Input Parameters:
     10: + da  - the `DMDA`
     11: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

     13:   Output Parameter:
     14: . array - the array

     16:   Level: intermediate

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

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

     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.

     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.

     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`.

     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.

     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;

     47:   PetscFunctionBegin;
     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));

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

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

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

     79:   Logically Collective

     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

     86:   Level: intermediate

     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;

     96:   PetscFunctionBegin;
     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));

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

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

    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`.

    129:   Logically Collective

    131:   Input Parameters:
    132: + da  - the `DMDA`
    133: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

    135:   Output Parameter:
    136: . array - the array

    138:   Level: intermediate

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

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

    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.

    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.

    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`.

    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.

    161:   Developer Note:
    162:   This has code duplication with `DMDAVecGetArray()` and `DMDAVecGetArrayRead()`

    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;

    171:   PetscFunctionBegin;
    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));

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

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

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

    207:   Logically Collective

    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

    214:   Level: intermediate

    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;

    223:   PetscFunctionBegin;
    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));

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

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

    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`

    260:   Logically Collective

    262:   Input Parameters:
    263: + da  - the `DMDA`
    264: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

    266:   Output Parameter:
    267: . array - the `array` pointer

    269:   Level: intermediate

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

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

    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.

    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`.

    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.

    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;

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

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

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

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

    324:   Logically Collective

    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

    331:   Level: intermediate

    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;

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

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

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

    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`.

    370:   Not Collective

    372:   Input Parameters:
    373: + da  - the `DMDA`
    374: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

    376:   Output Parameter:
    377: . array - the array

    379:   Level: intermediate

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

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

    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.

    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.

    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`.

    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.

    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;

    411:   PetscFunctionBegin;
    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));

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

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

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

    443:   Not Collective

    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

    450:   Level: intermediate

    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;

    460:   PetscFunctionBegin;
    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));

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

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

    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`

    493:   Not Collective

    495:   Input Parameters:
    496: + da  - the `DMDA`
    497: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

    499:   Output Parameter:
    500: . array - the array

    502:   Level: intermediate

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

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

    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.

    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`.

    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.

    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;

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

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

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

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

    557:   Not Collective

    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

    564:   Level: intermediate

    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;

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

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

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

    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`

    603:   Not Collective

    605:   Input Parameters:
    606: + da  - the `DMDA`
    607: - vec - a vector the same size as one obtained with `DMCreateGlobalVector()` or `DMCreateLocalVector()`

    609:   Output Parameter:
    610: . array - the array

    612:   Level: intermediate

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

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

    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.

    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`.

    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.

    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;

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

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

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

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

    667:   Not Collective

    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

    674:   Level: intermediate

    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;

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

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

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