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