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), §ion));
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(§ion));
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: }