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:   DMDACreateCompatibleDMDA(dm, dm->dim, cdm);
 12:   return 0;
 13: }

 15: PetscErrorCode DMCreateCoordinateField_DA(DM dm, DMField *field)
 16: {
 17:   PetscReal   gmin[3], gmax[3];
 18:   PetscScalar corners[24];
 19:   PetscInt    dim;
 20:   PetscInt    i, j;
 21:   DM          cdm;

 23:   DMGetDimension(dm, &dim);
 24:   /* TODO: this is wrong if coordinates are not rectilinear */
 25:   DMGetBoundingBox(dm, gmin, gmax);
 26:   for (i = 0; i < (1 << dim); i++) {
 27:     for (j = 0; j < dim; j++) corners[i * dim + j] = (i & (1 << j)) ? gmax[j] : gmin[j];
 28:   }
 29:   DMClone(dm, &cdm);
 30:   DMFieldCreateDA(cdm, dim, corners, field);
 31:   DMDestroy(&cdm);
 32:   return 0;
 33: }

 35: /*@C
 36:    DMDASetFieldName - Sets the names of individual field components in multicomponent
 37:    vectors associated with a DMDA.

 39:    Logically collective; name must contain a common value

 41:    Input Parameters:
 42: +  da - the distributed array
 43: .  nf - field number for the DMDA (0, 1, ... dof-1), where dof indicates the
 44:         number of degrees of freedom per node within the DMDA
 45: -  names - the name of the field (component)

 47:   Notes:
 48:     It must be called after having called DMSetUp().

 50:   Level: intermediate

 52: .seealso: `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldNames()`, `DMSetUp()`
 53: @*/
 54: PetscErrorCode DMDASetFieldName(DM da, PetscInt nf, const char name[])
 55: {
 56:   DM_DA *dd = (DM_DA *)da->data;

 61:   PetscFree(dd->fieldname[nf]);
 62:   PetscStrallocpy(name, &dd->fieldname[nf]);
 63:   return 0;
 64: }

 66: /*@C
 67:    DMDAGetFieldNames - Gets the name of each component in the vector associated with the DMDA

 69:    Not collective; names will contain a common value

 71:    Input Parameter:
 72: .  dm - the DMDA object

 74:    Output Parameter:
 75: .  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

 77:    Level: intermediate

 79:    Not supported from Fortran, use DMDAGetFieldName()

 81: .seealso: `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMDASetFieldNames()`
 82: @*/
 83: PetscErrorCode DMDAGetFieldNames(DM da, const char *const **names)
 84: {
 85:   DM_DA *dd = (DM_DA *)da->data;

 87:   *names = (const char *const *)dd->fieldname;
 88:   return 0;
 89: }

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

 94:    Logically collective; names must contain a common value

 96:    Input Parameters:
 97: +  dm - the DMDA object
 98: -  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

100:    Notes:
101:     It must be called after having called DMSetUp().

103:    Level: intermediate

105:    Not supported from Fortran, use DMDASetFieldName()

107: .seealso: `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMSetUp()`
108: @*/
109: PetscErrorCode DMDASetFieldNames(DM da, const char *const *names)
110: {
111:   DM_DA   *dd = (DM_DA *)da->data;
112:   char   **fieldname;
113:   PetscInt nf = 0;

116:   while (names[nf++]) { };
118:   PetscStrArrayallocpy(names, &fieldname);
119:   PetscStrArrayDestroy(&dd->fieldname);
120:   dd->fieldname = fieldname;
121:   return 0;
122: }

124: /*@C
125:    DMDAGetFieldName - Gets the names of individual field components in multicomponent
126:    vectors associated with a DMDA.

128:    Not collective; name will contain a common value

130:    Input Parameters:
131: +  da - the distributed array
132: -  nf - field number for the DMDA (0, 1, ... dof-1), where dof indicates the
133:         number of degrees of freedom per node within the DMDA

135:    Output Parameter:
136: .  names - the name of the field (component)

138:   Notes:
139:     It must be called after having called DMSetUp().

141:   Level: intermediate

143: .seealso: `DMDASetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMSetUp()`
144: @*/
145: PetscErrorCode DMDAGetFieldName(DM da, PetscInt nf, const char **name)
146: {
147:   DM_DA *dd = (DM_DA *)da->data;

153:   *name = dd->fieldname[nf];
154:   return 0;
155: }

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

160:    Logically collective; name must contain a common value

162:    Input Parameters:
163: +  dm - the DM
164: .  nf - coordinate number for the DMDA (0, 1, ... dim-1),
165: -  name - the name of the coordinate

167:   Notes:
168:     It must be called after having called DMSetUp().

170:   Level: intermediate

172:   Not supported from Fortran

174: .seealso: `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMSetUp()`
175: @*/
176: PetscErrorCode DMDASetCoordinateName(DM dm, PetscInt nf, const char name[])
177: {
178:   DM_DA *dd = (DM_DA *)dm->data;

183:   PetscFree(dd->coordinatename[nf]);
184:   PetscStrallocpy(name, &dd->coordinatename[nf]);
185:   return 0;
186: }

188: /*@C
189:    DMDAGetCoordinateName - Gets the name of a coodinate direction associated with a DMDA.

191:    Not collective; name will contain a common value

193:    Input Parameters:
194: +  dm - the DM
195: -  nf -  number for the DMDA (0, 1, ... dim-1)

197:    Output Parameter:
198: .  names - the name of the coordinate direction

200:   Notes:
201:     It must be called after having called DMSetUp().

203:   Level: intermediate

205:   Not supported from Fortran

207: .seealso: `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMSetUp()`
208: @*/
209: PetscErrorCode DMDAGetCoordinateName(DM dm, PetscInt nf, const char **name)
210: {
211:   DM_DA *dd = (DM_DA *)dm->data;

217:   *name = dd->coordinatename[nf];
218:   return 0;
219: }

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

225:    Not collective

227:    Input Parameter:
228: .  da - the distributed array

230:    Output Parameters:
231: +  x - the corner index for the first dimension
232: .  y - the corner index for the second dimension (only used in 2D and 3D problems)
233: .  z - the corner index for the third dimension (only used in 3D problems)
234: .  m - the width in the first dimension
235: .  n - the width in the second dimension (only used in 2D and 3D problems)
236: -  p - the width in the third dimension (only used in 3D problems)

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

245:   Level: beginner

247: .seealso: `DMDAGetGhostCorners()`, `DMDAGetOwnershipRanges()`, `DMStagGetCorners()`
248: @*/
249: PetscErrorCode DMDAGetCorners(DM da, PetscInt *x, PetscInt *y, PetscInt *z, PetscInt *m, PetscInt *n, PetscInt *p)
250: {
251:   PetscInt w;
252:   DM_DA   *dd = (DM_DA *)da->data;

255:   /* since the xs, xe ... have all been multiplied by the number of degrees
256:      of freedom per cell, w = dd->w, we divide that out before returning.*/
257:   w = dd->w;
258:   if (x) *x = dd->xs / w + dd->xo;
259:   /* the y and z have NOT been multiplied by w */
260:   if (y) *y = dd->ys + dd->yo;
261:   if (z) *z = dd->zs + dd->zo;
262:   if (m) *m = (dd->xe - dd->xs) / w;
263:   if (n) *n = (dd->ye - dd->ys);
264:   if (p) *p = (dd->ze - dd->zs);
265:   return 0;
266: }

268: PetscErrorCode DMGetLocalBoundingIndices_DMDA(DM dm, PetscReal lmin[], PetscReal lmax[])
269: {
270:   DMDALocalInfo info;

272:   DMDAGetLocalInfo(dm, &info);
273:   lmin[0] = info.xs;
274:   lmin[1] = info.ys;
275:   lmin[2] = info.zs;
276:   lmax[0] = info.xs + info.xm - 1;
277:   lmax[1] = info.ys + info.ym - 1;
278:   lmax[2] = info.zs + info.zm - 1;
279:   return 0;
280: }

282: /*@
283:    DMDAGetReducedDMDA - Deprecated; use DMDACreateCompatibleDMDA()

285:    Level: deprecated
286: @*/
287: PetscErrorCode DMDAGetReducedDMDA(DM da, PetscInt nfields, DM *nda)
288: {
289:   DMDACreateCompatibleDMDA(da, nfields, nda);
290:   return 0;
291: }

293: /*@
294:    DMDACreateCompatibleDMDA - Creates a DMDA with the same layout but with fewer or more fields

296:    Collective

298:    Input Parameters:
299: +  da - the distributed array
300: -  nfields - number of fields in new DMDA

302:    Output Parameter:
303: .  nda - the new DMDA

305:   Level: intermediate

307: .seealso: `DMDAGetGhostCorners()`, `DMSetCoordinates()`, `DMDASetUniformCoordinates()`, `DMGetCoordinates()`, `DMDAGetGhostedCoordinates()`, `DMStagCreateCompatibleDMStag()`
308: @*/
309: PetscErrorCode DMDACreateCompatibleDMDA(DM da, PetscInt nfields, DM *nda)
310: {
311:   DM_DA          *dd = (DM_DA *)da->data;
312:   PetscInt        s, m, n, p, M, N, P, dim, Mo, No, Po;
313:   const PetscInt *lx, *ly, *lz;
314:   DMBoundaryType  bx, by, bz;
315:   DMDAStencilType stencil_type;
316:   Vec             coords;
317:   PetscInt        ox, oy, oz;
318:   PetscInt        cl, rl;

320:   dim = da->dim;
321:   M   = dd->M;
322:   N   = dd->N;
323:   P   = dd->P;
324:   m   = dd->m;
325:   n   = dd->n;
326:   p   = dd->p;
327:   s   = dd->s;
328:   bx  = dd->bx;
329:   by  = dd->by;
330:   bz  = dd->bz;

332:   stencil_type = dd->stencil_type;

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

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

350:   /* allow for getting a reduced DA corresponding to a coarsened DA */
351:   DMGetCoarsenLevel(da, &cl);
352:   DMGetRefineLevel(da, &rl);

354:   (*nda)->levelup   = rl;
355:   (*nda)->leveldown = cl;
356:   return 0;
357: }

359: /*@C
360:    DMDAGetCoordinateArray - Gets an array containing the coordinates of the DMDA

362:    Not collective

364:    Input Parameter:
365: .  dm - the DM

367:    Output Parameter:
368: .  xc - the coordinates

370:   Level: intermediate

372:   Not supported from Fortran

374: .seealso: `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMDARestoreCoordinateArray()`
375: @*/
376: PetscErrorCode DMDAGetCoordinateArray(DM dm, void *xc)
377: {
378:   DM  cdm;
379:   Vec x;

382:   DMGetCoordinates(dm, &x);
383:   DMGetCoordinateDM(dm, &cdm);
384:   DMDAVecGetArray(cdm, x, xc);
385:   return 0;
386: }

388: /*@C
389:    DMDARestoreCoordinateArray - Sets an array containing the coordinates of the DMDA

391:    Not collective

393:    Input Parameters:
394: +  dm - the DM
395: -  xc - the coordinates

397:   Level: intermediate

399:   Not supported from Fortran

401: .seealso: `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMDAGetCoordinateArray()`
402: @*/
403: PetscErrorCode DMDARestoreCoordinateArray(DM dm, void *xc)
404: {
405:   DM  cdm;
406:   Vec x;

409:   DMGetCoordinates(dm, &x);
410:   DMGetCoordinateDM(dm, &cdm);
411:   DMDAVecRestoreArray(cdm, x, xc);
412:   return 0;
413: }