Date: 2025-03-28T21:10:44+00:00

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 `DMDAVecRestoreArrayF90()`

    103: .seealso: [](sec_struct), [](sec_struct_set), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetCorners()`, `DMDAVecRestoreArrayF90()`, `VecGetArray()`, `VecRestoreArray()`, `DMDAVecGetArray()`,
    104:           `DMDAVecGetArrayWrite()`, `DMDAVecRestoreArrayWrite()`, `DMDAVecGetArrayRead()`, `DMDAVecRestoreArrayRead()`,
    105:           `DMStagVecRestoreArray()`
    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 `DMDAVecRestoreArrayF90()`

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