Actual source code: dacorn.c
2: /*
3: Code for manipulating distributed regular arrays in parallel.
4: */
6: #include <petsc/private/dmdaimpl.h>
7: #include <petscdmfield.h>
9: PetscErrorCode DMCreateCoordinateDM_DA(DM dm, DM *cdm)
10: {
11: const char *prefix;
13: PetscFunctionBegin;
14: PetscCall(DMDACreateCompatibleDMDA(dm, dm->dim, cdm));
15: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
16: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
17: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
18: PetscFunctionReturn(PETSC_SUCCESS);
19: }
21: PetscErrorCode DMCreateCoordinateField_DA(DM dm, DMField *field)
22: {
23: PetscReal gmin[3], gmax[3];
24: PetscScalar corners[24];
25: PetscInt dim;
26: PetscInt i, j;
27: DM cdm;
29: PetscFunctionBegin;
30: PetscCall(DMGetDimension(dm, &dim));
31: /* TODO: this is wrong if coordinates are not rectilinear */
32: PetscCall(DMGetBoundingBox(dm, gmin, gmax));
33: for (i = 0; i < (1 << dim); i++) {
34: for (j = 0; j < dim; j++) corners[i * dim + j] = (i & (1 << j)) ? gmax[j] : gmin[j];
35: }
36: PetscCall(DMClone(dm, &cdm));
37: PetscCall(DMFieldCreateDA(cdm, dim, corners, field));
38: PetscCall(DMDestroy(&cdm));
39: PetscFunctionReturn(PETSC_SUCCESS);
40: }
42: /*@C
43: DMDASetFieldName - Sets the names of individual field components in multicomponent
44: vectors associated with a `DMDA`.
46: Logically collective; name must contain a common value
48: Input Parameters:
49: + da - the distributed array
50: . nf - field number for the `DMDA` (0, 1, ... dof-1), where dof indicates the
51: number of degrees of freedom per node within the `DMDA`
52: - names - the name of the field (component)
54: Level: intermediate
56: Note:
57: It must be called after having called `DMSetUp()`.
59: .seealso: `DM`, `DMDA`, `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldNames()`, `DMSetUp()`
60: @*/
61: PetscErrorCode DMDASetFieldName(DM da, PetscInt nf, const char name[])
62: {
63: DM_DA *dd = (DM_DA *)da->data;
65: PetscFunctionBegin;
67: PetscCheck(nf >= 0 && nf < dd->w, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid field number: %" PetscInt_FMT, nf);
68: PetscCheck(dd->fieldname, PetscObjectComm((PetscObject)da), PETSC_ERR_ORDER, "You should call DMSetUp() first");
69: PetscCall(PetscFree(dd->fieldname[nf]));
70: PetscCall(PetscStrallocpy(name, &dd->fieldname[nf]));
71: PetscFunctionReturn(PETSC_SUCCESS);
72: }
74: /*@C
75: DMDAGetFieldNames - Gets the name of each component in the vector associated with the `DMDA`
77: Not collective; names will contain a common value
79: Input Parameter:
80: . dm - the `DMDA` object
82: Output Parameter:
83: . names - the names of the components, final string is NULL, will have the same number of entries as the dof used in creating the `DMDA`
85: Level: intermediate
87: Fortran Note:
88: Not supported from Fortran, use `DMDAGetFieldName()`
90: .seealso: `DM`, `DMDA`, `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMDASetFieldNames()`
91: @*/
92: PetscErrorCode DMDAGetFieldNames(DM da, const char *const **names)
93: {
94: DM_DA *dd = (DM_DA *)da->data;
96: PetscFunctionBegin;
97: *names = (const char *const *)dd->fieldname;
98: PetscFunctionReturn(PETSC_SUCCESS);
99: }
101: /*@C
102: DMDASetFieldNames - Sets the name of each component in the vector associated with the DMDA
104: Logically collective; names must contain a common value
106: Input Parameters:
107: + dm - the `DMDA` object
108: - names - the names of the components, final string must be NULL, must have the same number of entries as the dof used in creating the `DMDA`
110: Level: intermediate
112: Note:
113: It must be called after having called `DMSetUp()`.
115: Fortran Note:
116: Not supported from Fortran, use `DMDASetFieldName()`
118: .seealso: `DM`, `DMDA`, `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMSetUp()`
119: @*/
120: PetscErrorCode DMDASetFieldNames(DM da, const char *const *names)
121: {
122: DM_DA *dd = (DM_DA *)da->data;
123: char **fieldname;
124: PetscInt nf = 0;
126: PetscFunctionBegin;
127: PetscCheck(dd->fieldname, PetscObjectComm((PetscObject)da), PETSC_ERR_ORDER, "You should call DMSetUp() first");
128: while (names[nf++]) { };
129: PetscCheck(nf == dd->w + 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of fields %" PetscInt_FMT, nf - 1);
130: PetscCall(PetscStrArrayallocpy(names, &fieldname));
131: PetscCall(PetscStrArrayDestroy(&dd->fieldname));
132: dd->fieldname = fieldname;
133: PetscFunctionReturn(PETSC_SUCCESS);
134: }
136: /*@C
137: DMDAGetFieldName - Gets the names of individual field components in multicomponent
138: vectors associated with a `DMDA`.
140: Not collective; name will contain a common value
142: Input Parameters:
143: + da - the distributed array
144: - nf - field number for the `DMDA` (0, 1, ... dof-1), where dof indicates the
145: number of degrees of freedom per node within the `DMDA`
147: Output Parameter:
148: . names - the name of the field (component)
150: Level: intermediate
152: Note:
153: It must be called after having called `DMSetUp()`.
155: .seealso: `DM`, `DMDA`, `DMDASetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMSetUp()`
156: @*/
157: PetscErrorCode DMDAGetFieldName(DM da, PetscInt nf, const char **name)
158: {
159: DM_DA *dd = (DM_DA *)da->data;
161: PetscFunctionBegin;
164: PetscCheck(nf >= 0 && nf < dd->w, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid field number: %" PetscInt_FMT, nf);
165: PetscCheck(dd->fieldname, PetscObjectComm((PetscObject)da), PETSC_ERR_ORDER, "You should call DMSetUp() first");
166: *name = dd->fieldname[nf];
167: PetscFunctionReturn(PETSC_SUCCESS);
168: }
170: /*@C
171: DMDASetCoordinateName - Sets the name of the coordinate directions associated with a `DMDA`, for example "x" or "y"
173: Logically collective; name must contain a common value
175: Input Parameters:
176: + dm - the `DMDA`
177: . nf - coordinate number for the DMDA (0, 1, ... dim-1),
178: - name - the name of the coordinate
180: Level: intermediate
182: Note:
183: It must be called after having called `DMSetUp()`.
185: Fortran Note:
186: Not supported from Fortran
188: .seealso: `DM`, `DMDA`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMSetUp()`
189: @*/
190: PetscErrorCode DMDASetCoordinateName(DM dm, PetscInt nf, const char name[])
191: {
192: DM_DA *dd = (DM_DA *)dm->data;
194: PetscFunctionBegin;
196: PetscCheck(nf >= 0 && nf < dm->dim, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid coordinate number: %" PetscInt_FMT, nf);
197: PetscCheck(dd->coordinatename, PetscObjectComm((PetscObject)dm), PETSC_ERR_ORDER, "You should call DMSetUp() first");
198: PetscCall(PetscFree(dd->coordinatename[nf]));
199: PetscCall(PetscStrallocpy(name, &dd->coordinatename[nf]));
200: PetscFunctionReturn(PETSC_SUCCESS);
201: }
203: /*@C
204: DMDAGetCoordinateName - Gets the name of a coordinate direction associated with a `DMDA`.
206: Not collective; name will contain a common value
208: Input Parameters:
209: + dm - the `DMDA`
210: - nf - number for the DMDA (0, 1, ... dim-1)
212: Output Parameter:
213: . names - the name of the coordinate direction
215: Level: intermediate
217: Note:
218: It must be called after having called `DMSetUp()`.
220: Fortran Note:
221: Not supported from Fortran
223: .seealso: `DM`, `DMDA`, `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMSetUp()`
224: @*/
225: PetscErrorCode DMDAGetCoordinateName(DM dm, PetscInt nf, const char **name)
226: {
227: DM_DA *dd = (DM_DA *)dm->data;
229: PetscFunctionBegin;
232: PetscCheck(nf >= 0 && nf < dm->dim, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid coordinate number: %" PetscInt_FMT, nf);
233: PetscCheck(dd->coordinatename, PetscObjectComm((PetscObject)dm), PETSC_ERR_ORDER, "You should call DMSetUp() first");
234: *name = dd->coordinatename[nf];
235: PetscFunctionReturn(PETSC_SUCCESS);
236: }
238: /*@C
239: DMDAGetCorners - Returns the global (x,y,z) indices of the lower left
240: corner and size of the local region, excluding ghost points.
242: Not collective
244: Input Parameter:
245: . da - the distributed array
247: Output Parameters:
248: + x - the corner index for the first dimension
249: . y - the corner index for the second dimension (only used in 2D and 3D problems)
250: . z - the corner index for the third dimension (only used in 3D problems)
251: . m - the width in the first dimension
252: . n - the width in the second dimension (only used in 2D and 3D problems)
253: - p - the width in the third dimension (only used in 3D problems)
255: Level: beginner
257: Note:
258: The corner information is independent of the number of degrees of
259: freedom per node set with the `DMDACreateXX()` routine. Thus the x, y, z, and
260: m, n, p can be thought of as coordinates on a logical grid, where each
261: grid point has (potentially) several degrees of freedom.
262: Any of y, z, n, and p can be passed in as NULL if not needed.
264: .seealso: `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetOwnershipRanges()`, `DMStagGetCorners()`
265: @*/
266: PetscErrorCode DMDAGetCorners(DM da, PetscInt *x, PetscInt *y, PetscInt *z, PetscInt *m, PetscInt *n, PetscInt *p)
267: {
268: PetscInt w;
269: DM_DA *dd = (DM_DA *)da->data;
271: PetscFunctionBegin;
273: /* since the xs, xe ... have all been multiplied by the number of degrees
274: of freedom per cell, w = dd->w, we divide that out before returning.*/
275: w = dd->w;
276: if (x) *x = dd->xs / w + dd->xo;
277: /* the y and z have NOT been multiplied by w */
278: if (y) *y = dd->ys + dd->yo;
279: if (z) *z = dd->zs + dd->zo;
280: if (m) *m = (dd->xe - dd->xs) / w;
281: if (n) *n = (dd->ye - dd->ys);
282: if (p) *p = (dd->ze - dd->zs);
283: PetscFunctionReturn(PETSC_SUCCESS);
284: }
286: PetscErrorCode DMGetLocalBoundingIndices_DMDA(DM dm, PetscReal lmin[], PetscReal lmax[])
287: {
288: DMDALocalInfo info;
290: PetscFunctionBegin;
291: PetscCall(DMDAGetLocalInfo(dm, &info));
292: lmin[0] = info.xs;
293: lmin[1] = info.ys;
294: lmin[2] = info.zs;
295: lmax[0] = info.xs + info.xm - 1;
296: lmax[1] = info.ys + info.ym - 1;
297: lmax[2] = info.zs + info.zm - 1;
298: PetscFunctionReturn(PETSC_SUCCESS);
299: }
301: /*@
302: DMDAGetReducedDMDA - Deprecated; use DMDACreateCompatibleDMDA()
304: Level: deprecated
305: @*/
306: PetscErrorCode DMDAGetReducedDMDA(DM da, PetscInt nfields, DM *nda)
307: {
308: PetscFunctionBegin;
309: PetscCall(DMDACreateCompatibleDMDA(da, nfields, nda));
310: PetscFunctionReturn(PETSC_SUCCESS);
311: }
313: /*@
314: DMDACreateCompatibleDMDA - Creates a `DMDA` with the same layout but with fewer or more fields
316: Collective
318: Input Parameters:
319: + da - the distributed array
320: - nfields - number of fields in new `DMDA`
322: Output Parameter:
323: . nda - the new `DMDA`
325: Level: intermediate
327: .seealso: `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMSetCoordinates()`, `DMDASetUniformCoordinates()`, `DMGetCoordinates()`, `DMDAGetGhostedCoordinates()`, `DMStagCreateCompatibleDMStag()`
328: @*/
329: PetscErrorCode DMDACreateCompatibleDMDA(DM da, PetscInt nfields, DM *nda)
330: {
331: DM_DA *dd = (DM_DA *)da->data;
332: PetscInt s, m, n, p, M, N, P, dim, Mo, No, Po;
333: const PetscInt *lx, *ly, *lz;
334: DMBoundaryType bx, by, bz;
335: DMDAStencilType stencil_type;
336: Vec coords;
337: PetscInt ox, oy, oz;
338: PetscInt cl, rl;
340: PetscFunctionBegin;
341: dim = da->dim;
342: M = dd->M;
343: N = dd->N;
344: P = dd->P;
345: m = dd->m;
346: n = dd->n;
347: p = dd->p;
348: s = dd->s;
349: bx = dd->bx;
350: by = dd->by;
351: bz = dd->bz;
353: stencil_type = dd->stencil_type;
355: PetscCall(DMDAGetOwnershipRanges(da, &lx, &ly, &lz));
356: if (dim == 1) {
357: PetscCall(DMDACreate1d(PetscObjectComm((PetscObject)da), bx, M, nfields, s, dd->lx, nda));
358: } else if (dim == 2) {
359: PetscCall(DMDACreate2d(PetscObjectComm((PetscObject)da), bx, by, stencil_type, M, N, m, n, nfields, s, lx, ly, nda));
360: } else if (dim == 3) {
361: PetscCall(DMDACreate3d(PetscObjectComm((PetscObject)da), bx, by, bz, stencil_type, M, N, P, m, n, p, nfields, s, lx, ly, lz, nda));
362: }
363: PetscCall(DMSetUp(*nda));
364: PetscCall(DMGetCoordinates(da, &coords));
365: PetscCall(DMSetCoordinates(*nda, coords));
367: /* allow for getting a reduced DA corresponding to a domain decomposition */
368: PetscCall(DMDAGetOffset(da, &ox, &oy, &oz, &Mo, &No, &Po));
369: PetscCall(DMDASetOffset(*nda, ox, oy, oz, Mo, No, Po));
371: /* allow for getting a reduced DA corresponding to a coarsened DA */
372: PetscCall(DMGetCoarsenLevel(da, &cl));
373: PetscCall(DMGetRefineLevel(da, &rl));
375: (*nda)->levelup = rl;
376: (*nda)->leveldown = cl;
377: PetscFunctionReturn(PETSC_SUCCESS);
378: }
380: /*@C
381: DMDAGetCoordinateArray - Gets an array containing the coordinates of the `DMDA`
383: Not collective
385: Input Parameter:
386: . dm - the `DMDA`
388: Output Parameter:
389: . xc - the coordinates
391: Level: intermediate
393: Fortran Note:
394: Not supported from Fortran
396: .seealso: `DM`, `DMDA`, `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMDARestoreCoordinateArray()`
397: @*/
398: PetscErrorCode DMDAGetCoordinateArray(DM dm, void *xc)
399: {
400: DM cdm;
401: Vec x;
403: PetscFunctionBegin;
405: PetscCall(DMGetCoordinates(dm, &x));
406: PetscCall(DMGetCoordinateDM(dm, &cdm));
407: PetscCall(DMDAVecGetArray(cdm, x, xc));
408: PetscFunctionReturn(PETSC_SUCCESS);
409: }
411: /*@C
412: DMDARestoreCoordinateArray - Sets an array containing the coordinates of the `DMDA`
414: Not collective
416: Input Parameters:
417: + dm - the `DMDA`
418: - xc - the coordinates
420: Level: intermediate
422: Fortran Note:
423: Not supported from Fortran
425: .seealso: `DM`, `DMDA`, `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMDAGetCoordinateArray()`
426: @*/
427: PetscErrorCode DMDARestoreCoordinateArray(DM dm, void *xc)
428: {
429: DM cdm;
430: Vec x;
432: PetscFunctionBegin;
434: PetscCall(DMGetCoordinates(dm, &x));
435: PetscCall(DMGetCoordinateDM(dm, &cdm));
436: PetscCall(DMDAVecRestoreArray(cdm, x, xc));
437: PetscFunctionReturn(PETSC_SUCCESS);
438: }