Actual source code: dalocal.c

  1: /*
  2:   Code for manipulating distributed regular arrays in parallel.
  3: */

  5: #include <petsc/private/dmdaimpl.h>
  6: #include <petscsf.h>
  7: #include <petscds.h>
  8: #include <petscfe.h>

 10: /*
 11:    This allows the DMDA vectors to properly tell MATLAB their dimensions
 12: */
 13: #if PetscDefined(HAVE_MATLAB)
 14:   #include <engine.h> /* MATLAB include file */
 15:   #include <mex.h>    /* MATLAB include file */
 16: static PetscErrorCode VecMatlabEnginePut_DA2d(PetscObject obj, void *mengine)
 17: {
 18:   PetscInt     n, m;
 19:   Vec          vec = (Vec)obj;
 20:   PetscScalar *array;
 21:   mxArray     *mat;
 22:   DM           da;

 24:   PetscFunctionBegin;
 25:   PetscCall(VecGetDM(vec, &da));
 26:   PetscCheck(da, PetscObjectComm((PetscObject)vec), PETSC_ERR_ARG_WRONGSTATE, "Vector not associated with a DMDA");
 27:   PetscCall(DMDAGetGhostCorners(da, 0, 0, 0, &m, &n, 0));

 29:   PetscCall(VecGetArray(vec, &array));
 30:   #if !PetscDefined(USE_COMPLEX)
 31:   mat = mxCreateDoubleMatrix(m, n, mxREAL);
 32:   #else
 33:   mat = mxCreateDoubleMatrix(m, n, mxCOMPLEX);
 34:   #endif
 35:   PetscCall(PetscArraycpy(mxGetPr(mat), array, n * m));
 36:   PetscCall(PetscObjectName(obj));
 37:   engPutVariable((Engine *)mengine, obj->name, mat);

 39:   PetscCall(VecRestoreArray(vec, &array));
 40:   PetscFunctionReturn(PETSC_SUCCESS);
 41: }
 42: #endif

 44: PetscErrorCode DMCreateLocalVector_DA(DM da, Vec *g)
 45: {
 46:   DM_DA *dd = (DM_DA *)da->data;

 48:   PetscFunctionBegin;
 50:   PetscAssertPointer(g, 2);
 51:   PetscCall(VecCreate(PETSC_COMM_SELF, g));
 52:   PetscCall(VecSetSizes(*g, dd->nlocal, PETSC_DETERMINE));
 53:   PetscCall(VecSetBlockSize(*g, dd->w));
 54:   PetscCall(VecSetType(*g, da->vectype));
 55:   if (dd->nlocal < da->bind_below) {
 56:     PetscCall(VecSetBindingPropagates(*g, PETSC_TRUE));
 57:     PetscCall(VecBindToCPU(*g, PETSC_TRUE));
 58:   }
 59:   PetscCall(VecSetDM(*g, da));
 60: #if PetscDefined(HAVE_MATLAB)
 61:   if (dd->w == 1 && da->dim == 2) PetscCall(PetscObjectComposeFunction((PetscObject)*g, "PetscMatlabEnginePut_C", VecMatlabEnginePut_DA2d));
 62: #endif
 63:   PetscFunctionReturn(PETSC_SUCCESS);
 64: }

 66: /*@
 67:   DMDAGetNumCells - Get the number of cells (or vertices) in the local piece of the `DMDA`. This includes ghost cells.

 69:   Input Parameter:
 70: . dm - The `DMDA` object

 72:   Output Parameters:
 73: + numCellsX - The number of local cells in the x-direction
 74: . numCellsY - The number of local cells in the y-direction
 75: . numCellsZ - The number of local cells in the z-direction
 76: - numCells  - The number of local cells

 78:   Level: developer

 80: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetCellPoint()`
 81: @*/
 82: PetscErrorCode DMDAGetNumCells(DM dm, PeOp PetscInt *numCellsX, PeOp PetscInt *numCellsY, PeOp PetscInt *numCellsZ, PeOp PetscInt *numCells)
 83: {
 84:   DM_DA         *da  = (DM_DA *)dm->data;
 85:   const PetscInt dim = dm->dim;
 86:   const PetscInt mx = (da->Xe - da->Xs) / da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
 87:   const PetscInt nC = mx * (dim > 1 ? my * (dim > 2 ? mz : 1) : 1);

 89:   PetscFunctionBegin;
 91:   if (numCellsX) {
 92:     PetscAssertPointer(numCellsX, 2);
 93:     *numCellsX = mx;
 94:   }
 95:   if (numCellsY) {
 96:     PetscAssertPointer(numCellsY, 3);
 97:     *numCellsY = my;
 98:   }
 99:   if (numCellsZ) {
100:     PetscAssertPointer(numCellsZ, 4);
101:     *numCellsZ = mz;
102:   }
103:   if (numCells) {
104:     PetscAssertPointer(numCells, 5);
105:     *numCells = nC;
106:   }
107:   PetscFunctionReturn(PETSC_SUCCESS);
108: }

110: /*@
111:   DMDAGetCellPoint - Get the `DM` point corresponding to the tuple (i, j, k) in the `DMDA`

113:   Input Parameters:
114: + dm - The `DMDA` object
115: . i  - The global x index for the cell
116: . j  - The global y index for the cell
117: - k  - The global z index for the cell

119:   Output Parameter:
120: . point - The local `DM` point

122:   Level: developer

124: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetNumCells()`
125: @*/
126: PetscErrorCode DMDAGetCellPoint(DM dm, PetscInt i, PetscInt j, PetscInt k, PetscInt *point)
127: {
128:   const PetscInt dim = dm->dim;
129:   DMDALocalInfo  info;

131:   PetscFunctionBegin;
133:   PetscAssertPointer(point, 5);
134:   PetscCall(DMDAGetLocalInfo(dm, &info));
135:   if (dim > 0) PetscCheck(!(i < info.gxs) && !(i >= info.gxs + info.gxm), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "X index %" PetscInt_FMT " not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", i, info.gxs, info.gxs + info.gxm);
136:   if (dim > 1) PetscCheck(!(j < info.gys) && !(j >= info.gys + info.gym), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Y index %" PetscInt_FMT " not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", j, info.gys, info.gys + info.gym);
137:   if (dim > 2) PetscCheck(!(k < info.gzs) && !(k >= info.gzs + info.gzm), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Z index %" PetscInt_FMT " not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", k, info.gzs, info.gzs + info.gzm);
138:   *point = i + (dim > 1 ? (j + (dim > 2 ? k * info.gym : 0)) * info.gxm : 0);
139:   PetscFunctionReturn(PETSC_SUCCESS);
140: }

142: /*@
143:   DMDAGetNumVertices - Return the number of local vertices (including ghost vertices) of a `DMDA` in each dimension and in total.

145:   Not Collective

147:   Input Parameter:
148: . dm - the `DMDA`

150:   Output Parameters:
151: + numVerticesX - number of vertices in the x direction, or `NULL` if not needed
152: . numVerticesY - number of vertices in the y direction (`1` if `dim < 2`), or `NULL` if not needed
153: . numVerticesZ - number of vertices in the z direction (`1` if `dim < 3`), or `NULL` if not needed
154: - numVertices  - total number of vertices, or `NULL` if not needed

156:   Level: developer

158: .seealso: `DM`, `DMDA`, `DMDAGetNumCells()`, `DMDAGetNumFaces()`
159: @*/
160: PetscErrorCode DMDAGetNumVertices(DM dm, PetscInt *numVerticesX, PetscInt *numVerticesY, PetscInt *numVerticesZ, PetscInt *numVertices)
161: {
162:   DM_DA         *da  = (DM_DA *)dm->data;
163:   const PetscInt dim = dm->dim;
164:   const PetscInt mx = (da->Xe - da->Xs) / da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
165:   const PetscInt nVx = mx + 1;
166:   const PetscInt nVy = dim > 1 ? (my + 1) : 1;
167:   const PetscInt nVz = dim > 2 ? (mz + 1) : 1;
168:   const PetscInt nV  = nVx * nVy * nVz;

170:   PetscFunctionBegin;
171:   if (numVerticesX) {
172:     PetscAssertPointer(numVerticesX, 2);
173:     *numVerticesX = nVx;
174:   }
175:   if (numVerticesY) {
176:     PetscAssertPointer(numVerticesY, 3);
177:     *numVerticesY = nVy;
178:   }
179:   if (numVerticesZ) {
180:     PetscAssertPointer(numVerticesZ, 4);
181:     *numVerticesZ = nVz;
182:   }
183:   if (numVertices) {
184:     PetscAssertPointer(numVertices, 5);
185:     *numVertices = nV;
186:   }
187:   PetscFunctionReturn(PETSC_SUCCESS);
188: }

190: /*@
191:   DMDAGetNumFaces - Return the number of local mesh faces of each orientation (including ghost faces) for a `DMDA`.

193:   Not Collective

195:   Input Parameter:
196: . dm - the `DMDA`

198:   Output Parameters:
199: + numXFacesX - number of X-normal faces along the x direction, or `NULL` if not needed
200: . numXFaces  - total number of X-normal faces, or `NULL` if not needed
201: . numYFacesY - number of Y-normal faces along the y direction, or `NULL` if not needed
202: . numYFaces  - total number of Y-normal faces (`0` for 1D), or `NULL` if not needed
203: . numZFacesZ - number of Z-normal faces along the z direction, or `NULL` if not needed
204: - numZFaces  - total number of Z-normal faces (`0` for 1D/2D), or `NULL` if not needed

206:   Level: developer

208: .seealso: `DM`, `DMDA`, `DMDAGetNumVertices()`, `DMDAGetNumCells()`
209: @*/
210: PetscErrorCode DMDAGetNumFaces(DM dm, PetscInt *numXFacesX, PetscInt *numXFaces, PetscInt *numYFacesY, PetscInt *numYFaces, PetscInt *numZFacesZ, PetscInt *numZFaces)
211: {
212:   DM_DA         *da  = (DM_DA *)dm->data;
213:   const PetscInt dim = dm->dim;
214:   const PetscInt mx = (da->Xe - da->Xs) / da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
215:   const PetscInt nxF = (dim > 1 ? my * (dim > 2 ? mz : 1) : 1);
216:   const PetscInt nXF = (mx + 1) * nxF;
217:   const PetscInt nyF = mx * (dim > 2 ? mz : 1);
218:   const PetscInt nYF = dim > 1 ? (my + 1) * nyF : 0;
219:   const PetscInt nzF = mx * (dim > 1 ? my : 0);
220:   const PetscInt nZF = dim > 2 ? (mz + 1) * nzF : 0;

222:   PetscFunctionBegin;
223:   if (numXFacesX) {
224:     PetscAssertPointer(numXFacesX, 2);
225:     *numXFacesX = nxF;
226:   }
227:   if (numXFaces) {
228:     PetscAssertPointer(numXFaces, 3);
229:     *numXFaces = nXF;
230:   }
231:   if (numYFacesY) {
232:     PetscAssertPointer(numYFacesY, 4);
233:     *numYFacesY = nyF;
234:   }
235:   if (numYFaces) {
236:     PetscAssertPointer(numYFaces, 5);
237:     *numYFaces = nYF;
238:   }
239:   if (numZFacesZ) {
240:     PetscAssertPointer(numZFacesZ, 6);
241:     *numZFacesZ = nzF;
242:   }
243:   if (numZFaces) {
244:     PetscAssertPointer(numZFaces, 7);
245:     *numZFaces = nZF;
246:   }
247:   PetscFunctionReturn(PETSC_SUCCESS);
248: }

250: /*@
251:   DMDAGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height.

253:   Not Collective

255:   Input Parameters:
256: + dm     - The `DMDA` object
257: - height - The requested height

259:   Output Parameters:
260: + pStart - The first point at this `height`
261: - pEnd   - One beyond the last point at this `height`

263:   Level: developer

265:   Note:
266:   See `DMPlexGetHeightStratum()` for the meaning of these values

268: .seealso: [](ch_unstructured), `DM`, `DMDA`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`,
269:           `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`, `DMDAGetDepthStratum()`
270: @*/
271: PetscErrorCode DMDAGetHeightStratum(DM dm, PetscInt height, PeOp PetscInt *pStart, PeOp PetscInt *pEnd)
272: {
273:   const PetscInt dim = dm->dim;
274:   PetscInt       nC, nV, nXF, nYF, nZF;

276:   PetscFunctionBegin;
277:   if (pStart) PetscAssertPointer(pStart, 3);
278:   if (pEnd) PetscAssertPointer(pEnd, 4);
279:   PetscCall(DMDAGetNumCells(dm, NULL, NULL, NULL, &nC));
280:   PetscCall(DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV));
281:   PetscCall(DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF));
282:   if (height == 0) {
283:     /* Cells */
284:     if (pStart) *pStart = 0;
285:     if (pEnd) *pEnd = nC;
286:   } else if (height == 1) {
287:     /* Faces */
288:     if (pStart) *pStart = nC + nV;
289:     if (pEnd) *pEnd = nC + nV + nXF + nYF + nZF;
290:   } else if (height == dim) {
291:     /* Vertices */
292:     if (pStart) *pStart = nC;
293:     if (pEnd) *pEnd = nC + nV;
294:   } else if (height < 0) {
295:     /* All points */
296:     if (pStart) *pStart = 0;
297:     if (pEnd) *pEnd = nC + nV + nXF + nYF + nZF;
298:   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No points of height %" PetscInt_FMT " in the DA", height);
299:   PetscFunctionReturn(PETSC_SUCCESS);
300: }

302: /*@
303:   DMDAGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth.

305:   Not Collective

307:   Input Parameters:
308: + dm    - The `DMDA` object
309: - depth - The requested depth

311:   Output Parameters:
312: + pStart - The first point at this `depth`
313: - pEnd   - One beyond the last point at this `depth`

315:   Level: developer

317:   Note:
318:   See `DMPlexGetDepthStratum()` for the meaning of these values

320: .seealso: [](ch_unstructured), `DM`, `DMDA`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`,
321:           `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`, `DMDAGetHeightStratum()`
322: @*/
323: PetscErrorCode DMDAGetDepthStratum(DM dm, PetscInt depth, PeOp PetscInt *pStart, PeOp PetscInt *pEnd)
324: {
325:   const PetscInt dim = dm->dim;
326:   PetscInt       nC, nV, nXF, nYF, nZF;

328:   PetscFunctionBegin;
329:   if (pStart) PetscAssertPointer(pStart, 3);
330:   if (pEnd) PetscAssertPointer(pEnd, 4);
331:   PetscCall(DMDAGetNumCells(dm, NULL, NULL, NULL, &nC));
332:   PetscCall(DMDAGetNumVertices(dm, NULL, NULL, NULL, &nV));
333:   PetscCall(DMDAGetNumFaces(dm, NULL, &nXF, NULL, &nYF, NULL, &nZF));
334:   if (depth == dim) {
335:     /* Cells */
336:     if (pStart) *pStart = 0;
337:     if (pEnd) *pEnd = nC;
338:   } else if (depth == dim - 1) {
339:     /* Faces */
340:     if (pStart) *pStart = nC + nV;
341:     if (pEnd) *pEnd = nC + nV + nXF + nYF + nZF;
342:   } else if (depth == 0) {
343:     /* Vertices */
344:     if (pStart) *pStart = nC;
345:     if (pEnd) *pEnd = nC + nV;
346:   } else if (depth < 0) {
347:     /* All points */
348:     if (pStart) *pStart = 0;
349:     if (pEnd) *pEnd = nC + nV + nXF + nYF + nZF;
350:   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No points of depth %" PetscInt_FMT " in the DA", depth);
351:   PetscFunctionReturn(PETSC_SUCCESS);
352: }

354: /*@
355:   DMDASetVertexCoordinates - Sets the lower and upper coordinates for a `DMDA`

357:   Logically Collective

359:   Input Parameters:
360: + dm - The `DMDA` object
361: . xl - the lower x coordinate
362: . xu - the upper x coordinate
363: . yl - the lower y coordinate
364: . yu - the upper y coordinate
365: . zl - the lower z coordinate
366: - zu - the upper z coordinate

368:   Level: intermediate

370: .seealso: [](ch_unstructured), `DM`, `DMDA`
371: @*/
372: PetscErrorCode DMDASetVertexCoordinates(DM dm, PetscReal xl, PetscReal xu, PetscReal yl, PetscReal yu, PetscReal zl, PetscReal zu)
373: {
374:   DM_DA       *da = (DM_DA *)dm->data;
375:   Vec          coordinates;
376:   PetscSection section;
377:   PetscScalar *coords;
378:   PetscReal    h[3];
379:   PetscInt     dim, size, M, N, P, nVx, nVy, nVz, nV, vStart, vEnd, v, i, j, k;

381:   PetscFunctionBegin;
383:   PetscCall(DMDAGetInfo(dm, &dim, &M, &N, &P, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL));
384:   PetscCheck(dim <= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "The following code only works for dim <= 3");
385:   h[0] = (xu - xl) / M;
386:   h[1] = (yu - yl) / N;
387:   h[2] = (zu - zl) / P;
388:   PetscCall(DMDAGetDepthStratum(dm, 0, &vStart, &vEnd));
389:   PetscCall(DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV));
390:   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
391:   PetscCall(PetscSectionSetNumFields(section, 1));
392:   PetscCall(PetscSectionSetFieldComponents(section, 0, dim));
393:   PetscCall(PetscSectionSetChart(section, vStart, vEnd));
394:   for (v = vStart; v < vEnd; ++v) PetscCall(PetscSectionSetDof(section, v, dim));
395:   PetscCall(PetscSectionSetUp(section));
396:   PetscCall(PetscSectionGetStorageSize(section, &size));
397:   PetscCall(VecCreateSeq(PETSC_COMM_SELF, size, &coordinates));
398:   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
399:   PetscCall(VecGetArray(coordinates, &coords));
400:   for (k = 0; k < nVz; ++k) {
401:     PetscInt ind[3], d, off;

403:     ind[0] = 0;
404:     ind[1] = 0;
405:     ind[2] = k + da->zs;
406:     for (j = 0; j < nVy; ++j) {
407:       ind[1] = j + da->ys;
408:       for (i = 0; i < nVx; ++i) {
409:         const PetscInt vertex = (k * nVy + j) * nVx + i + vStart;

411:         PetscCall(PetscSectionGetOffset(section, vertex, &off));
412:         ind[0] = i + da->xs;
413:         for (d = 0; d < dim; ++d) coords[off + d] = h[d] * ind[d];
414:       }
415:     }
416:   }
417:   PetscCall(VecRestoreArray(coordinates, &coords));
418:   PetscCall(DMSetCoordinateSection(dm, PETSC_DETERMINE, section));
419:   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
420:   PetscCall(PetscSectionDestroy(&section));
421:   PetscCall(VecDestroy(&coordinates));
422:   PetscFunctionReturn(PETSC_SUCCESS);
423: }

425: /*@
426:   DMDAGetArray - Gets a work array for a `DMDA`

428:   Input Parameters:
429: + da      - a `DMDA`
430: - ghosted - do you want arrays for the ghosted or nonghosted patch

432:   Output Parameter:
433: . vptr - array data structured

435:   Level: advanced

437:   Notes:
438:   The vector values are NOT initialized and may have garbage in them, so you may need
439:   to zero them.

441:   Use `DMDARestoreArray()` to return the array

443: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDARestoreArray()`
444: @*/
445: PetscErrorCode DMDAGetArray(DM da, PetscBool ghosted, void *vptr)
446: {
447:   PetscInt j, i, xs, ys, xm, ym, zs, zm;
448:   char    *iarray_start;
449:   void   **iptr = (void **)vptr;
450:   DM_DA   *dd   = (DM_DA *)da->data;

452:   PetscFunctionBegin;
454:   if (ghosted) {
455:     for (i = 0; i < DMDA_MAX_WORK_ARRAYS; i++) {
456:       if (dd->arrayghostedin[i]) {
457:         *iptr                 = dd->arrayghostedin[i];
458:         iarray_start          = (char *)dd->startghostedin[i];
459:         dd->arrayghostedin[i] = NULL;
460:         dd->startghostedin[i] = NULL;

462:         goto done;
463:       }
464:     }
465:     xs = dd->Xs;
466:     ys = dd->Ys;
467:     zs = dd->Zs;
468:     xm = dd->Xe - dd->Xs;
469:     ym = dd->Ye - dd->Ys;
470:     zm = dd->Ze - dd->Zs;
471:   } else {
472:     for (i = 0; i < DMDA_MAX_WORK_ARRAYS; i++) {
473:       if (dd->arrayin[i]) {
474:         *iptr          = dd->arrayin[i];
475:         iarray_start   = (char *)dd->startin[i];
476:         dd->arrayin[i] = NULL;
477:         dd->startin[i] = NULL;

479:         goto done;
480:       }
481:     }
482:     xs = dd->xs;
483:     ys = dd->ys;
484:     zs = dd->zs;
485:     xm = dd->xe - dd->xs;
486:     ym = dd->ye - dd->ys;
487:     zm = dd->ze - dd->zs;
488:   }

490:   switch (da->dim) {
491:   case 1: {
492:     void *ptr;

494:     PetscCall(PetscMalloc(xm * sizeof(PetscScalar), &iarray_start));

496:     ptr   = (void *)((PetscScalar *)iarray_start - xs);
497:     *iptr = ptr;
498:     break;
499:   }
500:   case 2: {
501:     void **ptr;

503:     PetscCall(PetscMalloc((ym + 1) * sizeof(void *) + xm * ym * sizeof(PetscScalar), &iarray_start));

505:     ptr = (void **)(iarray_start + xm * ym * sizeof(PetscScalar) - ys * sizeof(void *));
506:     for (j = ys; j < ys + ym; j++) ptr[j] = iarray_start + sizeof(PetscScalar) * (xm * (j - ys) - xs);
507:     *iptr = (void *)ptr;
508:     break;
509:   }
510:   case 3: {
511:     void ***ptr, **bptr;

513:     PetscCall(PetscMalloc((zm + 1) * sizeof(void **) + (ym * zm + 1) * sizeof(void *) + xm * ym * zm * sizeof(PetscScalar), &iarray_start));

515:     ptr  = (void ***)(iarray_start + xm * ym * zm * sizeof(PetscScalar) - zs * sizeof(void *));
516:     bptr = (void **)(iarray_start + xm * ym * zm * sizeof(PetscScalar) + zm * sizeof(void **));
517:     for (i = zs; i < zs + zm; i++) ptr[i] = bptr + ((i - zs) * ym - ys);
518:     for (i = zs; i < zs + zm; i++) {
519:       for (j = ys; j < ys + ym; j++) ptr[i][j] = iarray_start + sizeof(PetscScalar) * (xm * ym * (i - zs) + xm * (j - ys) - xs);
520:     }
521:     *iptr = (void *)ptr;
522:     break;
523:   }
524:   default:
525:     SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", da->dim);
526:   }

528: done:
529:   /* add arrays to the checked out list */
530:   if (ghosted) {
531:     for (i = 0; i < DMDA_MAX_WORK_ARRAYS; i++) {
532:       if (!dd->arrayghostedout[i]) {
533:         dd->arrayghostedout[i] = *iptr;
534:         dd->startghostedout[i] = iarray_start;
535:         break;
536:       }
537:     }
538:   } else {
539:     for (i = 0; i < DMDA_MAX_WORK_ARRAYS; i++) {
540:       if (!dd->arrayout[i]) {
541:         dd->arrayout[i] = *iptr;
542:         dd->startout[i] = iarray_start;
543:         break;
544:       }
545:     }
546:   }
547:   PetscFunctionReturn(PETSC_SUCCESS);
548: }

550: /*@
551:   DMDARestoreArray - Restores an array for a `DMDA` obtained with  `DMDAGetArray()`

553:   Input Parameters:
554: + da      - information about my local patch
555: . ghosted - do you want arrays for the ghosted or nonghosted patch
556: - vptr    - array data structured

558:   Level: advanced

560: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetArray()`
561: @*/
562: PetscErrorCode DMDARestoreArray(DM da, PetscBool ghosted, void *vptr)
563: {
564:   void **iptr = (void **)vptr, *iarray_start = NULL;
565:   DM_DA *dd = (DM_DA *)da->data;

567:   PetscFunctionBegin;
569:   if (ghosted) {
570:     for (PetscInt i = 0; i < DMDA_MAX_WORK_ARRAYS; i++) {
571:       if (dd->arrayghostedout[i] == *iptr) {
572:         iarray_start           = dd->startghostedout[i];
573:         dd->arrayghostedout[i] = NULL;
574:         dd->startghostedout[i] = NULL;
575:         break;
576:       }
577:     }
578:     for (PetscInt i = 0; i < DMDA_MAX_WORK_ARRAYS; i++) {
579:       if (!dd->arrayghostedin[i]) {
580:         dd->arrayghostedin[i] = *iptr;
581:         dd->startghostedin[i] = iarray_start;
582:         break;
583:       }
584:     }
585:   } else {
586:     for (PetscInt i = 0; i < DMDA_MAX_WORK_ARRAYS; i++) {
587:       if (dd->arrayout[i] == *iptr) {
588:         iarray_start    = dd->startout[i];
589:         dd->arrayout[i] = NULL;
590:         dd->startout[i] = NULL;
591:         break;
592:       }
593:     }
594:     for (PetscInt i = 0; i < DMDA_MAX_WORK_ARRAYS; i++) {
595:       if (!dd->arrayin[i]) {
596:         dd->arrayin[i] = *iptr;
597:         dd->startin[i] = iarray_start;
598:         break;
599:       }
600:     }
601:   }
602:   PetscFunctionReturn(PETSC_SUCCESS);
603: }