xref: /petsc/src/dm/impls/da/dacorn.c (revision 6d8694c4fbab79f9439f1ad13c0386ba7ee1ca4b)
1 /*
2   Code for manipulating distributed regular arrays in parallel.
3 */
4 
5 #include <petsc/private/dmdaimpl.h> /*I   "petscdmda.h"   I*/
6 #include <petscdmfield.h>
7 
DMCreateCoordinateDM_DA(DM dm,DM * cdm)8 PetscErrorCode DMCreateCoordinateDM_DA(DM dm, DM *cdm)
9 {
10   const char *prefix;
11 
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 }
19 
20 /*@
21   DMDASetFieldName - Sets the names of individual field components in multicomponent
22   vectors associated with a `DMDA`.
23 
24   Logically Collective; name must contain a common value
25 
26   Input Parameters:
27 + da   - the `DMDA`
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)
31 
32   Level: intermediate
33 
34   Note:
35   It must be called after having called `DMSetUp()`.
36 
37 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldNames()`, `DMSetUp()`
38 @*/
DMDASetFieldName(DM da,PetscInt nf,const char name[])39 PetscErrorCode DMDASetFieldName(DM da, PetscInt nf, const char name[])
40 {
41   DM_DA *dd = (DM_DA *)da->data;
42 
43   PetscFunctionBegin;
44   PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
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 }
51 
52 /*@C
53   DMDAGetFieldNames - Gets the name of all the components in the vector associated with the `DMDA`
54 
55   Not Collective; names will contain a common value; No Fortran Support
56 
57   Input Parameter:
58 . da - the `DMDA` object
59 
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`
62 
63   Level: intermediate
64 
65   Fortran Note:
66   Use `DMDAGetFieldName()`
67 
68 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMDASetFieldNames()`
69 @*/
DMDAGetFieldNames(DM da,const char * const ** names)70 PetscErrorCode DMDAGetFieldNames(DM da, const char *const **names)
71 {
72   DM_DA *dd = (DM_DA *)da->data;
73 
74   PetscFunctionBegin;
75   *names = (const char *const *)dd->fieldname;
76   PetscFunctionReturn(PETSC_SUCCESS);
77 }
78 
79 /*@C
80   DMDASetFieldNames - Sets the name of each component in the vector associated with the `DMDA`
81 
82   Logically Collective; names must contain a common value; No Fortran Support
83 
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`
87 
88   Level: intermediate
89 
90   Note:
91   It must be called after having called `DMSetUp()`.
92 
93   Fortran Note:
94   Use `DMDASetFieldName()`
95 
96 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMSetUp()`
97 @*/
DMDASetFieldNames(DM da,const char * const names[])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;
103 
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 }
113 
114 /*@
115   DMDAGetFieldName - Gets the names of individual field components in multicomponent
116   vectors associated with a `DMDA`.
117 
118   Not Collective; name will contain a common value
119 
120   Input Parameters:
121 + da - the `DMDA`
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`
124 
125   Output Parameter:
126 . name - the name of the field (component)
127 
128   Level: intermediate
129 
130   Note:
131   It must be called after having called `DMSetUp()`.
132 
133 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDASetFieldName()`, `DMDASetCoordinateName()`, `DMDAGetCoordinateName()`, `DMSetUp()`
134 @*/
DMDAGetFieldName(DM da,PetscInt nf,const char * name[])135 PetscErrorCode DMDAGetFieldName(DM da, PetscInt nf, const char *name[])
136 {
137   DM_DA *dd = (DM_DA *)da->data;
138 
139   PetscFunctionBegin;
140   PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
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 }
147 
148 /*@
149   DMDASetCoordinateName - Sets the name of the coordinate directions associated with a `DMDA`, for example "x" or "y"
150 
151   Logically Collective; name must contain a common value; No Fortran Support
152 
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
157 
158   Level: intermediate
159 
160   Note:
161   Must be called after having called `DMSetUp()`.
162 
163 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMSetUp()`
164 @*/
DMDASetCoordinateName(DM dm,PetscInt nf,const char name[])165 PetscErrorCode DMDASetCoordinateName(DM dm, PetscInt nf, const char name[])
166 {
167   DM_DA *dd = (DM_DA *)dm->data;
168 
169   PetscFunctionBegin;
170   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMDA);
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 }
177 
178 /*@
179   DMDAGetCoordinateName - Gets the name of a coordinate direction associated with a `DMDA`.
180 
181   Not Collective; name will contain a common value; No Fortran Support
182 
183   Input Parameters:
184 + dm - the `DMDA`
185 - nf - number for the `DMDA` (0, 1, ... dim-1)
186 
187   Output Parameter:
188 . name - the name of the coordinate direction
189 
190   Level: intermediate
191 
192   Note:
193   It must be called after having called `DMSetUp()`.
194 
195 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMSetUp()`
196 @*/
DMDAGetCoordinateName(DM dm,PetscInt nf,const char * name[])197 PetscErrorCode DMDAGetCoordinateName(DM dm, PetscInt nf, const char *name[])
198 {
199   DM_DA *dd = (DM_DA *)dm->data;
200 
201   PetscFunctionBegin;
202   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMDA);
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 }
209 
210 /*@
211   DMDAGetCorners - Returns the global (`x`,`y`,`z`) indices of the lower left
212   corner and size of the local region, excluding ghost points.
213 
214   Not Collective
215 
216   Input Parameter:
217 . da - the `DMDA`
218 
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)
226 
227   Level: beginner
228 
229   Notes:
230   Any of `y`, `z`, `n`, and `p` can be passed in as `NULL` if not needed.
231 
232   The corner information is independent of the number of degrees of
233   freedom per node set with the `DMDACreateXX()` routine.  Thus the `x`, `y`, and `z`
234   can be thought of as the lower left coordinates of the patch of values on process on a logical grid and `m`, `n`, and `p` as the
235   extent of the patch, where each grid point has (potentially) several degrees of freedom.
236 
237 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMDAGetOwnershipRanges()`, `DMStagGetCorners()`, `DMSTAG`
238 @*/
DMDAGetCorners(DM da,PeOp PetscInt * x,PeOp PetscInt * y,PeOp PetscInt * z,PeOp PetscInt * m,PeOp PetscInt * n,PeOp PetscInt * p)239 PetscErrorCode DMDAGetCorners(DM da, PeOp PetscInt *x, PeOp PetscInt *y, PeOp PetscInt *z, PeOp PetscInt *m, PeOp PetscInt *n, PeOp PetscInt *p)
240 {
241   PetscInt w;
242   DM_DA   *dd = (DM_DA *)da->data;
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA);
246   /* since the xs, xe ... have all been multiplied by the number of degrees
247      of freedom per cell, w = dd->w, we divide that out before returning.*/
248   w = dd->w;
249   if (x) *x = dd->xs / w + dd->xo;
250   /* the y and z have NOT been multiplied by w */
251   if (y) *y = dd->ys + dd->yo;
252   if (z) *z = dd->zs + dd->zo;
253   if (m) *m = (dd->xe - dd->xs) / w;
254   if (n) *n = (dd->ye - dd->ys);
255   if (p) *p = (dd->ze - dd->zs);
256   PetscFunctionReturn(PETSC_SUCCESS);
257 }
258 
DMGetLocalBoundingIndices_DMDA(DM dm,PetscReal lmin[],PetscReal lmax[])259 PetscErrorCode DMGetLocalBoundingIndices_DMDA(DM dm, PetscReal lmin[], PetscReal lmax[])
260 {
261   DMDALocalInfo info;
262 
263   PetscFunctionBegin;
264   PetscCall(DMDAGetLocalInfo(dm, &info));
265   lmin[0] = info.xs;
266   lmin[1] = info.ys;
267   lmin[2] = info.zs;
268   lmax[0] = info.xs + info.xm - 1;
269   lmax[1] = info.ys + info.ym - 1;
270   lmax[2] = info.zs + info.zm - 1;
271   PetscFunctionReturn(PETSC_SUCCESS);
272 }
273 
274 // PetscClangLinter pragma ignore: -fdoc-*
275 /*@
276   DMDAGetReducedDMDA - Deprecated; use DMDACreateCompatibleDMDA()
277 
278   Level: deprecated
279 @*/
DMDAGetReducedDMDA(DM da,PetscInt nfields,DM * nda)280 PetscErrorCode DMDAGetReducedDMDA(DM da, PetscInt nfields, DM *nda)
281 {
282   PetscFunctionBegin;
283   PetscCall(DMDACreateCompatibleDMDA(da, nfields, nda));
284   PetscFunctionReturn(PETSC_SUCCESS);
285 }
286 
287 /*@
288   DMDACreateCompatibleDMDA - Creates a `DMDA` with the same layout as given `DMDA` but with fewer or more fields
289 
290   Collective
291 
292   Input Parameters:
293 + da      - the `DMDA`
294 - nfields - number of fields in new `DMDA`
295 
296   Output Parameter:
297 . nda - the new `DMDA`
298 
299   Level: intermediate
300 
301 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDAGetGhostCorners()`, `DMSetCoordinates()`, `DMDASetUniformCoordinates()`, `DMGetCoordinates()`, `DMDAGetGhostedCoordinates()`,
302           `DMStagCreateCompatibleDMStag()`
303 @*/
DMDACreateCompatibleDMDA(DM da,PetscInt nfields,DM * nda)304 PetscErrorCode DMDACreateCompatibleDMDA(DM da, PetscInt nfields, DM *nda)
305 {
306   DM_DA          *dd = (DM_DA *)da->data;
307   PetscInt        s, m, n, p, M, N, P, dim, Mo, No, Po;
308   const PetscInt *lx, *ly, *lz;
309   DMBoundaryType  bx, by, bz;
310   DMDAStencilType stencil_type;
311   Vec             coords;
312   PetscInt        ox, oy, oz;
313   PetscInt        cl, rl;
314 
315   PetscFunctionBegin;
316   dim = da->dim;
317   M   = dd->M;
318   N   = dd->N;
319   P   = dd->P;
320   m   = dd->m;
321   n   = dd->n;
322   p   = dd->p;
323   s   = dd->s;
324   bx  = dd->bx;
325   by  = dd->by;
326   bz  = dd->bz;
327 
328   stencil_type = dd->stencil_type;
329 
330   PetscCall(DMDAGetOwnershipRanges(da, &lx, &ly, &lz));
331   if (dim == 1) {
332     PetscCall(DMDACreate1d(PetscObjectComm((PetscObject)da), bx, M, nfields, s, dd->lx, nda));
333   } else if (dim == 2) {
334     PetscCall(DMDACreate2d(PetscObjectComm((PetscObject)da), bx, by, stencil_type, M, N, m, n, nfields, s, lx, ly, nda));
335   } else if (dim == 3) {
336     PetscCall(DMDACreate3d(PetscObjectComm((PetscObject)da), bx, by, bz, stencil_type, M, N, P, m, n, p, nfields, s, lx, ly, lz, nda));
337   }
338   PetscCall(DMSetUp(*nda));
339   PetscCall(DMGetCoordinates(da, &coords));
340   PetscCall(DMSetCoordinates(*nda, coords));
341 
342   /* allow for getting a reduced DA corresponding to a domain decomposition */
343   PetscCall(DMDAGetOffset(da, &ox, &oy, &oz, &Mo, &No, &Po));
344   PetscCall(DMDASetOffset(*nda, ox, oy, oz, Mo, No, Po));
345 
346   /* allow for getting a reduced DA corresponding to a coarsened DA */
347   PetscCall(DMGetCoarsenLevel(da, &cl));
348   PetscCall(DMGetRefineLevel(da, &rl));
349 
350   (*nda)->levelup   = rl;
351   (*nda)->leveldown = cl;
352   PetscFunctionReturn(PETSC_SUCCESS);
353 }
354 
355 /*@C
356   DMDAGetCoordinateArray - Gets an array containing the coordinates of the `DMDA`
357 
358   Not Collective; No Fortran Support
359 
360   Input Parameter:
361 . dm - the `DMDA`
362 
363   Output Parameter:
364 . xc - the coordinates
365 
366   Level: intermediate
367 
368   Note:
369   Use  `DMDARestoreCoordinateArray()` to return the array
370 
371 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMDARestoreCoordinateArray()`
372 @*/
DMDAGetCoordinateArray(DM dm,void * xc)373 PetscErrorCode DMDAGetCoordinateArray(DM dm, void *xc)
374 {
375   DM  cdm;
376   Vec x;
377 
378   PetscFunctionBegin;
379   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
380   PetscCall(DMGetCoordinates(dm, &x));
381   PetscCall(DMGetCoordinateDM(dm, &cdm));
382   PetscCall(DMDAVecGetArray(cdm, x, xc));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@C
387   DMDARestoreCoordinateArray - Returns an array containing the coordinates of the `DMDA` obtained with `DMDAGetCoordinateArray()`
388 
389   Not Collective; No Fortran Support
390 
391   Input Parameters:
392 + dm - the `DMDA`
393 - xc - the coordinates
394 
395   Level: intermediate
396 
397 .seealso: [](sec_struct), `DM`, `DMDA`, `DMDASetCoordinateName()`, `DMDASetFieldName()`, `DMDAGetFieldName()`, `DMDAGetCoordinateArray()`
398 @*/
DMDARestoreCoordinateArray(DM dm,void * xc)399 PetscErrorCode DMDARestoreCoordinateArray(DM dm, void *xc)
400 {
401   DM  cdm;
402   Vec x;
403 
404   PetscFunctionBegin;
405   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
406   PetscCall(DMGetCoordinates(dm, &x));
407   PetscCall(DMGetCoordinateDM(dm, &cdm));
408   PetscCall(DMDAVecRestoreArray(cdm, x, xc));
409   PetscFunctionReturn(PETSC_SUCCESS);
410 }
411