Actual source code: dacorn.c

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

  5: #include <petsc/private/dmdaimpl.h>
  6: #include <petscdmfield.h>

  8: PetscErrorCode DMCreateCoordinateDM_DA(DM dm, DM *cdm)
  9: {
 10:   const char *prefix;

 12:   PetscFunctionBegin;
 13:   PetscCall(DMDACreateCompatibleDMDA(dm, dm->dim, cdm));
 14:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
 15:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
 16:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
 17:   PetscFunctionReturn(PETSC_SUCCESS);
 18: }

 20: /*@C
 21:   DMDASetFieldName - Sets the names of individual field components in multicomponent
 22:   vectors associated with a `DMDA`.

 24:   Logically Collective; name must contain a common value

 26:   Input Parameters:
 27: + da   - the distributed array
 28: . nf   - field number for the `DMDA` (0, 1, ... dof-1), where dof indicates the
 29:         number of degrees of freedom per node within the `DMDA`
 30: - name - the name of the field (component)

 32:   Level: intermediate

 34:   Note:
 35:   It must be called after having called `DMSetUp()`.

 37: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldNames()`, `DMSetUp()`
 38: @*/
 39: PetscErrorCode DMDASetFieldName(DM da, PetscInt nf, const char name[])
 40: {
 41:   DM_DA *dd = (DM_DA *)da->data;

 43:   PetscFunctionBegin;
 45:   PetscCheck(nf >= 0 && nf < dd->w, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid field number: %" PetscInt_FMT, nf);
 46:   PetscCheck(dd->fieldname, PetscObjectComm((PetscObject)da), PETSC_ERR_ORDER, "You should call DMSetUp() first");
 47:   PetscCall(PetscFree(dd->fieldname[nf]));
 48:   PetscCall(PetscStrallocpy(name, &dd->fieldname[nf]));
 49:   PetscFunctionReturn(PETSC_SUCCESS);
 50: }

 52: /*@C
 53:   DMDAGetFieldNames - Gets the name of each component in the vector associated with the `DMDA`

 55:   Not Collective; names will contain a common value; No Fortran Support

 57:   Input Parameter:
 58: . da - the `DMDA` object

 60:   Output Parameter:
 61: . 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`

 63:   Level: intermediate

 65:   Fortran Note:
 66:   Use `DMDAGetFieldName()`

 68: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMDASetFieldNames()`
 69: @*/
 70: PetscErrorCode DMDAGetFieldNames(DM da, const char *const **names)
 71: {
 72:   DM_DA *dd = (DM_DA *)da->data;

 74:   PetscFunctionBegin;
 75:   *names = (const char *const *)dd->fieldname;
 76:   PetscFunctionReturn(PETSC_SUCCESS);
 77: }

 79: /*@C
 80:   DMDASetFieldNames - Sets the name of each component in the vector associated with the DMDA

 82:   Logically Collective; names must contain a common value; No Fortran Support

 84:   Input Parameters:
 85: + da    - the `DMDA` object
 86: - 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`

 88:   Level: intermediate

 90:   Note:
 91:   It must be called after having called `DMSetUp()`.

 93:   Fortran Note:
 94:   Use `DMDASetFieldName()`

 96: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMSetUp()`
 97: @*/
 98: PetscErrorCode DMDASetFieldNames(DM da, const char *const *names)
 99: {
100:   DM_DA   *dd = (DM_DA *)da->data;
101:   char   **fieldname;
102:   PetscInt nf = 0;

104:   PetscFunctionBegin;
105:   PetscCheck(dd->fieldname, PetscObjectComm((PetscObject)da), PETSC_ERR_ORDER, "You should call DMSetUp() first");
106:   while (names[nf++]) { }
107:   PetscCheck(nf == dd->w + 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of fields %" PetscInt_FMT, nf - 1);
108:   PetscCall(PetscStrArrayallocpy(names, &fieldname));
109:   PetscCall(PetscStrArrayDestroy(&dd->fieldname));
110:   dd->fieldname = fieldname;
111:   PetscFunctionReturn(PETSC_SUCCESS);
112: }

114: /*@C
115:   DMDAGetFieldName - Gets the names of individual field components in multicomponent
116:   vectors associated with a `DMDA`.

118:   Not Collective; name will contain a common value

120:   Input Parameters:
121: + da - the distributed array
122: - nf - field number for the `DMDA` (0, 1, ... dof-1), where dof indicates the
123:         number of degrees of freedom per node within the `DMDA`

125:   Output Parameter:
126: . name - the name of the field (component)

128:   Level: intermediate

130:   Note:
131:   It must be called after having called `DMSetUp()`.

133: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDASetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMSetUp()`
134: @*/
135: PetscErrorCode DMDAGetFieldName(DM da, PetscInt nf, const char **name)
136: {
137:   DM_DA *dd = (DM_DA *)da->data;

139:   PetscFunctionBegin;
141:   PetscAssertPointer(name, 3);
142:   PetscCheck(nf >= 0 && nf < dd->w, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid field number: %" PetscInt_FMT, nf);
143:   PetscCheck(dd->fieldname, PetscObjectComm((PetscObject)da), PETSC_ERR_ORDER, "You should call DMSetUp() first");
144:   *name = dd->fieldname[nf];
145:   PetscFunctionReturn(PETSC_SUCCESS);
146: }

148: /*@C
149:   DMDASetCoordinateName - Sets the name of the coordinate directions associated with a `DMDA`, for example "x" or "y"

151:   Logically Collective; name must contain a common value; No Fortran Support

153:   Input Parameters:
154: + dm   - the `DMDA`
155: . nf   - coordinate number for the `DMDA` (0, 1, ... dim-1),
156: - name - the name of the coordinate

158:   Level: intermediate

160:   Note:
161:   Must be called after having called `DMSetUp()`.

163: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMSetUp()`
164: @*/
165: PetscErrorCode DMDASetCoordinateName(DM dm, PetscInt nf, const char name[])
166: {
167:   DM_DA *dd = (DM_DA *)dm->data;

169:   PetscFunctionBegin;
171:   PetscCheck(nf >= 0 && nf < dm->dim, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid coordinate number: %" PetscInt_FMT, nf);
172:   PetscCheck(dd->coordinatename, PetscObjectComm((PetscObject)dm), PETSC_ERR_ORDER, "You should call DMSetUp() first");
173:   PetscCall(PetscFree(dd->coordinatename[nf]));
174:   PetscCall(PetscStrallocpy(name, &dd->coordinatename[nf]));
175:   PetscFunctionReturn(PETSC_SUCCESS);
176: }

178: /*@C
179:   DMDAGetCoordinateName - Gets the name of a coordinate direction associated with a `DMDA`.

181:   Not Collective; name will contain a common value; No Fortran Support

183:   Input Parameters:
184: + dm - the `DMDA`
185: - nf - number for the `DMDA` (0, 1, ... dim-1)

187:   Output Parameter:
188: . name - the name of the coordinate direction

190:   Level: intermediate

192:   Note:
193:   It must be called after having called `DMSetUp()`.

195: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMSetUp()`
196: @*/
197: PetscErrorCode DMDAGetCoordinateName(DM dm, PetscInt nf, const char **name)
198: {
199:   DM_DA *dd = (DM_DA *)dm->data;

201:   PetscFunctionBegin;
203:   PetscAssertPointer(name, 3);
204:   PetscCheck(nf >= 0 && nf < dm->dim, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid coordinate number: %" PetscInt_FMT, nf);
205:   PetscCheck(dd->coordinatename, PetscObjectComm((PetscObject)dm), PETSC_ERR_ORDER, "You should call DMSetUp() first");
206:   *name = dd->coordinatename[nf];
207:   PetscFunctionReturn(PETSC_SUCCESS);
208: }

210: /*@C
211:   DMDAGetCorners - Returns the global (`x`,`y`,`z`) indices of the lower left
212:   corner and size of the local region, excluding ghost points.

214:   Not Collective

216:   Input Parameter:
217: . da - the distributed array

219:   Output Parameters:
220: + x - the corner index for the first dimension
221: . y - the corner index for the second dimension (only used in 2D and 3D problems)
222: . z - the corner index for the third dimension (only used in 3D problems)
223: . m - the width in the first dimension
224: . n - the width in the second dimension (only used in 2D and 3D problems)
225: - p - the width in the third dimension (only used in 3D problems)

227:   Level: beginner

229:   Note:
230:   The corner information is independent of the number of degrees of
231:   freedom per node set with the `DMDACreateXX()` routine. Thus the `x`, `y`, `z`, and
232:   `m`, `n`, `p` can be thought of as coordinates on a logical grid, where each
233:   grid point has (potentially) several degrees of freedom.
234:   Any of `y`, `z`, `n`, and `p` can be passed in as `NULL` if not needed.

236: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetOwnershipRanges()`, `DMStagGetCorners()`
237: @*/
238: PetscErrorCode DMDAGetCorners(DM da, PetscInt *x, PetscInt *y, PetscInt *z, PetscInt *m, PetscInt *n, PetscInt *p)
239: {
240:   PetscInt w;
241:   DM_DA   *dd = (DM_DA *)da->data;

243:   PetscFunctionBegin;
245:   /* since the xs, xe ... have all been multiplied by the number of degrees
246:      of freedom per cell, w = dd->w, we divide that out before returning.*/
247:   w = dd->w;
248:   if (x) *x = dd->xs / w + dd->xo;
249:   /* the y and z have NOT been multiplied by w */
250:   if (y) *y = dd->ys + dd->yo;
251:   if (z) *z = dd->zs + dd->zo;
252:   if (m) *m = (dd->xe - dd->xs) / w;
253:   if (n) *n = (dd->ye - dd->ys);
254:   if (p) *p = (dd->ze - dd->zs);
255:   PetscFunctionReturn(PETSC_SUCCESS);
256: }

258: PetscErrorCode DMGetLocalBoundingIndices_DMDA(DM dm, PetscReal lmin[], PetscReal lmax[])
259: {
260:   DMDALocalInfo info;

262:   PetscFunctionBegin;
263:   PetscCall(DMDAGetLocalInfo(dm, &info));
264:   lmin[0] = info.xs;
265:   lmin[1] = info.ys;
266:   lmin[2] = info.zs;
267:   lmax[0] = info.xs + info.xm - 1;
268:   lmax[1] = info.ys + info.ym - 1;
269:   lmax[2] = info.zs + info.zm - 1;
270:   PetscFunctionReturn(PETSC_SUCCESS);
271: }

273: // PetscClangLinter pragma ignore: -fdoc-*
274: /*@
275:   DMDAGetReducedDMDA - Deprecated; use DMDACreateCompatibleDMDA()

277:   Level: deprecated
278: @*/
279: PetscErrorCode DMDAGetReducedDMDA(DM da, PetscInt nfields, DM *nda)
280: {
281:   PetscFunctionBegin;
282:   PetscCall(DMDACreateCompatibleDMDA(da, nfields, nda));
283:   PetscFunctionReturn(PETSC_SUCCESS);
284: }

286: /*@
287:   DMDACreateCompatibleDMDA - Creates a `DMDA` with the same layout but with fewer or more fields

289:   Collective

291:   Input Parameters:
292: + da      - the distributed array
293: - nfields - number of fields in new `DMDA`

295:   Output Parameter:
296: . nda - the new `DMDA`

298:   Level: intermediate

300: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMSetCoordinates()`, `DMDASetUniformCoordinates()`, `DMGetCoordinates()`, `DMDAGetGhostedCoordinates()`,
301:           `DMStagCreateCompatibleDMStag()`
302: @*/
303: PetscErrorCode DMDACreateCompatibleDMDA(DM da, PetscInt nfields, DM *nda)
304: {
305:   DM_DA          *dd = (DM_DA *)da->data;
306:   PetscInt        s, m, n, p, M, N, P, dim, Mo, No, Po;
307:   const PetscInt *lx, *ly, *lz;
308:   DMBoundaryType  bx, by, bz;
309:   DMDAStencilType stencil_type;
310:   Vec             coords;
311:   PetscInt        ox, oy, oz;
312:   PetscInt        cl, rl;

314:   PetscFunctionBegin;
315:   dim = da->dim;
316:   M   = dd->M;
317:   N   = dd->N;
318:   P   = dd->P;
319:   m   = dd->m;
320:   n   = dd->n;
321:   p   = dd->p;
322:   s   = dd->s;
323:   bx  = dd->bx;
324:   by  = dd->by;
325:   bz  = dd->bz;

327:   stencil_type = dd->stencil_type;

329:   PetscCall(DMDAGetOwnershipRanges(da, &lx, &ly, &lz));
330:   if (dim == 1) {
331:     PetscCall(DMDACreate1d(PetscObjectComm((PetscObject)da), bx, M, nfields, s, dd->lx, nda));
332:   } else if (dim == 2) {
333:     PetscCall(DMDACreate2d(PetscObjectComm((PetscObject)da), bx, by, stencil_type, M, N, m, n, nfields, s, lx, ly, nda));
334:   } else if (dim == 3) {
335:     PetscCall(DMDACreate3d(PetscObjectComm((PetscObject)da), bx, by, bz, stencil_type, M, N, P, m, n, p, nfields, s, lx, ly, lz, nda));
336:   }
337:   PetscCall(DMSetUp(*nda));
338:   PetscCall(DMGetCoordinates(da, &coords));
339:   PetscCall(DMSetCoordinates(*nda, coords));

341:   /* allow for getting a reduced DA corresponding to a domain decomposition */
342:   PetscCall(DMDAGetOffset(da, &ox, &oy, &oz, &Mo, &No, &Po));
343:   PetscCall(DMDASetOffset(*nda, ox, oy, oz, Mo, No, Po));

345:   /* allow for getting a reduced DA corresponding to a coarsened DA */
346:   PetscCall(DMGetCoarsenLevel(da, &cl));
347:   PetscCall(DMGetRefineLevel(da, &rl));

349:   (*nda)->levelup   = rl;
350:   (*nda)->leveldown = cl;
351:   PetscFunctionReturn(PETSC_SUCCESS);
352: }

354: /*@C
355:   DMDAGetCoordinateArray - Gets an array containing the coordinates of the `DMDA`

357:   Not Collective; No Fortran Support

359:   Input Parameter:
360: . dm - the `DMDA`

362:   Output Parameter:
363: . xc - the coordinates

365:   Level: intermediate

367:   Note:
368:   Use  `DMDARestoreCoordinateArray()` to return the array

370: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMDARestoreCoordinateArray()`
371: @*/
372: PetscErrorCode DMDAGetCoordinateArray(DM dm, void *xc)
373: {
374:   DM  cdm;
375:   Vec x;

377:   PetscFunctionBegin;
379:   PetscCall(DMGetCoordinates(dm, &x));
380:   PetscCall(DMGetCoordinateDM(dm, &cdm));
381:   PetscCall(DMDAVecGetArray(cdm, x, xc));
382:   PetscFunctionReturn(PETSC_SUCCESS);
383: }

385: /*@C
386:   DMDARestoreCoordinateArray - Returns an array containing the coordinates of the `DMDA` obtained with `DMDAGetCoordinateArray()`

388:   Not Collective; No Fortran Support

390:   Input Parameters:
391: + dm - the `DMDA`
392: - xc - the coordinates

394:   Level: intermediate

396: .seealso: [](sec_struct), `DM`, `DMDA`, `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMDAGetCoordinateArray()`
397: @*/
398: PetscErrorCode DMDARestoreCoordinateArray(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(DMDAVecRestoreArray(cdm, x, xc));
408:   PetscFunctionReturn(PETSC_SUCCESS);
409: }