xref: /petsc/src/dm/impls/da/dacreate.c (revision ccfb0f9f40a0131988d7995ed9679700dae2a75a)
1 #include <petsc/private/dmdaimpl.h> /*I   "petscdmda.h"   I*/
2 
3 static PetscErrorCode DMSetFromOptions_DA(DM da, PetscOptionItems PetscOptionsObject)
4 {
5   DM_DA         *dd     = (DM_DA *)da->data;
6   PetscInt       refine = 0, dim = da->dim, maxnlevels = 100, refx[100], refy[100], refz[100], n, i;
7   DMBoundaryType bt = DM_BOUNDARY_NONE;
8   PetscBool      flg;
9 
10   PetscFunctionBegin;
11   PetscCheck(!da->setupcalled, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONGSTATE, "Cannot call DMSetFromOptions() after DMSetUp() for DMDA");
12   PetscCheck(dd->M >= 0, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_OUTOFRANGE, "Dimension must be non-negative, call DMSetFromOptions() if you want to change the value at runtime");
13   PetscCheck(dd->N >= 0, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_OUTOFRANGE, "Dimension must be non-negative, call DMSetFromOptions() if you want to change the value at runtime");
14   PetscCheck(dd->P >= 0, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_OUTOFRANGE, "Dimension must be non-negative, call DMSetFromOptions() if you want to change the value at runtime");
15 
16   PetscOptionsHeadBegin(PetscOptionsObject, "DMDA Options");
17   PetscCall(PetscOptionsBoundedInt("-da_grid_x", "Number of grid points in x direction", "DMDASetSizes", dd->M, &dd->M, NULL, 1));
18   if (dim > 1) PetscCall(PetscOptionsBoundedInt("-da_grid_y", "Number of grid points in y direction", "DMDASetSizes", dd->N, &dd->N, NULL, 1));
19   if (dim > 2) PetscCall(PetscOptionsBoundedInt("-da_grid_z", "Number of grid points in z direction", "DMDASetSizes", dd->P, &dd->P, NULL, 1));
20 
21   PetscCall(PetscOptionsBoundedInt("-da_overlap", "Decomposition overlap in all directions", "DMDASetOverlap", dd->xol, &dd->xol, &flg, 0));
22   if (flg) PetscCall(DMDASetOverlap(da, dd->xol, dd->xol, dd->xol));
23   PetscCall(PetscOptionsBoundedInt("-da_overlap_x", "Decomposition overlap in x direction", "DMDASetOverlap", dd->xol, &dd->xol, NULL, 0));
24   if (dim > 1) PetscCall(PetscOptionsBoundedInt("-da_overlap_y", "Decomposition overlap in y direction", "DMDASetOverlap", dd->yol, &dd->yol, NULL, 0));
25   if (dim > 2) PetscCall(PetscOptionsBoundedInt("-da_overlap_z", "Decomposition overlap in z direction", "DMDASetOverlap", dd->zol, &dd->zol, NULL, 0));
26 
27   PetscCall(PetscOptionsBoundedInt("-da_local_subdomains", "", "DMDASetNumLocalSubdomains", dd->Nsub, &dd->Nsub, &flg, PETSC_DECIDE));
28   if (flg) PetscCall(DMDASetNumLocalSubDomains(da, dd->Nsub));
29 
30   /* Handle DMDA parallel distribution */
31   PetscCall(PetscOptionsBoundedInt("-da_processors_x", "Number of processors in x direction", "DMDASetNumProcs", dd->m, &dd->m, NULL, PETSC_DECIDE));
32   if (dim > 1) PetscCall(PetscOptionsBoundedInt("-da_processors_y", "Number of processors in y direction", "DMDASetNumProcs", dd->n, &dd->n, NULL, PETSC_DECIDE));
33   if (dim > 2) PetscCall(PetscOptionsBoundedInt("-da_processors_z", "Number of processors in z direction", "DMDASetNumProcs", dd->p, &dd->p, NULL, PETSC_DECIDE));
34   // Handle boundaries
35   PetscCall(PetscOptionsEnum("-da_bd_x", "Boundary type for x direction", "DMDASetBoundaryType", DMBoundaryTypes, (PetscEnum)dd->bx, (PetscEnum *)&dd->bx, NULL));
36   if (dim > 1) PetscCall(PetscOptionsEnum("-da_bd_y", "Boundary type for y direction", "DMDASetBoundaryType", DMBoundaryTypes, (PetscEnum)dd->by, (PetscEnum *)&dd->by, NULL));
37   if (dim > 2) PetscCall(PetscOptionsEnum("-da_bd_z", "Boundary type for z direction", "DMDASetBoundaryType", DMBoundaryTypes, (PetscEnum)dd->bz, (PetscEnum *)&dd->bz, NULL));
38   PetscCall(PetscOptionsEnum("-da_bd_all", "Boundary type for every direction", "DMDASetBoundaryType", DMBoundaryTypes, (PetscEnum)bt, (PetscEnum *)&bt, &flg));
39   if (flg) PetscCall(DMDASetBoundaryType(da, bt, bt, bt));
40   /* Handle DMDA refinement */
41   PetscCall(PetscOptionsBoundedInt("-da_refine_x", "Refinement ratio in x direction", "DMDASetRefinementFactor", dd->refine_x, &dd->refine_x, NULL, 1));
42   if (dim > 1) PetscCall(PetscOptionsBoundedInt("-da_refine_y", "Refinement ratio in y direction", "DMDASetRefinementFactor", dd->refine_y, &dd->refine_y, NULL, 1));
43   if (dim > 2) PetscCall(PetscOptionsBoundedInt("-da_refine_z", "Refinement ratio in z direction", "DMDASetRefinementFactor", dd->refine_z, &dd->refine_z, NULL, 1));
44   dd->coarsen_x = dd->refine_x;
45   dd->coarsen_y = dd->refine_y;
46   dd->coarsen_z = dd->refine_z;
47 
48   /* Get refinement factors, defaults taken from the coarse DMDA */
49   PetscCall(DMDAGetRefinementFactor(da, &refx[0], &refy[0], &refz[0]));
50   for (i = 1; i < maxnlevels; i++) {
51     refx[i] = refx[0];
52     refy[i] = refy[0];
53     refz[i] = refz[0];
54   }
55   n = maxnlevels;
56   PetscCall(PetscOptionsIntArray("-da_refine_hierarchy_x", "Refinement factor for each level", "None", refx, &n, &flg));
57   if (flg) {
58     dd->refine_x        = refx[0];
59     dd->refine_x_hier_n = n;
60     PetscCall(PetscMalloc1(n, &dd->refine_x_hier));
61     PetscCall(PetscArraycpy(dd->refine_x_hier, refx, n));
62   }
63   if (dim > 1) {
64     n = maxnlevels;
65     PetscCall(PetscOptionsIntArray("-da_refine_hierarchy_y", "Refinement factor for each level", "None", refy, &n, &flg));
66     if (flg) {
67       dd->refine_y        = refy[0];
68       dd->refine_y_hier_n = n;
69       PetscCall(PetscMalloc1(n, &dd->refine_y_hier));
70       PetscCall(PetscArraycpy(dd->refine_y_hier, refy, n));
71     }
72   }
73   if (dim > 2) {
74     n = maxnlevels;
75     PetscCall(PetscOptionsIntArray("-da_refine_hierarchy_z", "Refinement factor for each level", "None", refz, &n, &flg));
76     if (flg) {
77       dd->refine_z        = refz[0];
78       dd->refine_z_hier_n = n;
79       PetscCall(PetscMalloc1(n, &dd->refine_z_hier));
80       PetscCall(PetscArraycpy(dd->refine_z_hier, refz, n));
81     }
82   }
83 
84   PetscCall(PetscOptionsBoundedInt("-da_refine", "Uniformly refine DA one or more times", "None", refine, &refine, NULL, 0));
85   PetscOptionsHeadEnd();
86 
87   while (refine--) {
88     if (dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
89       PetscCall(PetscIntMultError(dd->refine_x, dd->M, &dd->M));
90     } else {
91       PetscCall(PetscIntMultError(dd->refine_x, dd->M - 1, &dd->M));
92       dd->M += 1;
93     }
94     if (dim > 1 && (dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0)) {
95       PetscCall(PetscIntMultError(dd->refine_y, dd->N, &dd->N));
96     } else if (dim > 1) {
97       PetscCall(PetscIntMultError(dd->refine_y, dd->N - 1, &dd->N));
98       dd->N += 1;
99     }
100     if (dim > 2 && (dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0)) {
101       PetscCall(PetscIntMultError(dd->refine_z, dd->P, &dd->P));
102     } else if (dim > 2) {
103       PetscCall(PetscIntMultError(dd->refine_z, dd->P - 1, &dd->P));
104       dd->P += 1;
105     }
106     da->levelup++;
107     if (da->levelup - da->leveldown >= 0) {
108       dd->refine_x = refx[da->levelup - da->leveldown];
109       dd->refine_y = refy[da->levelup - da->leveldown];
110       dd->refine_z = refz[da->levelup - da->leveldown];
111     }
112     if (da->levelup - da->leveldown >= 1) {
113       dd->coarsen_x = refx[da->levelup - da->leveldown - 1];
114       dd->coarsen_y = refy[da->levelup - da->leveldown - 1];
115       dd->coarsen_z = refz[da->levelup - da->leveldown - 1];
116     }
117   }
118   PetscFunctionReturn(PETSC_SUCCESS);
119 }
120 
121 static PetscErrorCode DMLoad_DA(DM da, PetscViewer viewer)
122 {
123   PetscInt        dim, m, n, p, dof, swidth;
124   DMDAStencilType stencil;
125   DMBoundaryType  bx, by, bz;
126   PetscBool       coors;
127   DM              dac;
128   Vec             c;
129 
130   PetscFunctionBegin;
131   PetscCall(PetscViewerBinaryRead(viewer, &dim, 1, NULL, PETSC_INT));
132   PetscCall(PetscViewerBinaryRead(viewer, &m, 1, NULL, PETSC_INT));
133   PetscCall(PetscViewerBinaryRead(viewer, &n, 1, NULL, PETSC_INT));
134   PetscCall(PetscViewerBinaryRead(viewer, &p, 1, NULL, PETSC_INT));
135   PetscCall(PetscViewerBinaryRead(viewer, &dof, 1, NULL, PETSC_INT));
136   PetscCall(PetscViewerBinaryRead(viewer, &swidth, 1, NULL, PETSC_INT));
137   PetscCall(PetscViewerBinaryRead(viewer, &bx, 1, NULL, PETSC_ENUM));
138   PetscCall(PetscViewerBinaryRead(viewer, &by, 1, NULL, PETSC_ENUM));
139   PetscCall(PetscViewerBinaryRead(viewer, &bz, 1, NULL, PETSC_ENUM));
140   PetscCall(PetscViewerBinaryRead(viewer, &stencil, 1, NULL, PETSC_ENUM));
141 
142   PetscCall(DMSetDimension(da, dim));
143   PetscCall(DMDASetSizes(da, m, n, p));
144   PetscCall(DMDASetBoundaryType(da, bx, by, bz));
145   PetscCall(DMDASetDof(da, dof));
146   PetscCall(DMDASetStencilType(da, stencil));
147   PetscCall(DMDASetStencilWidth(da, swidth));
148   PetscCall(DMSetUp(da));
149   PetscCall(PetscViewerBinaryRead(viewer, &coors, 1, NULL, PETSC_BOOL));
150   if (coors) {
151     PetscCall(DMGetCoordinateDM(da, &dac));
152     PetscCall(DMCreateGlobalVector(dac, &c));
153     PetscCall(VecLoad(c, viewer));
154     PetscCall(DMSetCoordinates(da, c));
155     PetscCall(VecDestroy(&c));
156   }
157   PetscFunctionReturn(PETSC_SUCCESS);
158 }
159 
160 static PetscErrorCode DMCreateSubDM_DA(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
161 {
162   DM_DA *da = (DM_DA *)dm->data;
163 
164   PetscFunctionBegin;
165   if (subdm) {
166     PetscSF sf;
167     Vec     coords;
168     void   *ctx;
169     /* Cannot use DMClone since the dof stuff is mixed in. Ugh
170     PetscCall(DMClone(dm, subdm)); */
171     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), subdm));
172     PetscCall(DMGetPointSF(dm, &sf));
173     PetscCall(DMSetPointSF(*subdm, sf));
174     PetscCall(DMGetApplicationContext(dm, &ctx));
175     PetscCall(DMSetApplicationContext(*subdm, ctx));
176     PetscCall(DMGetCoordinatesLocal(dm, &coords));
177     if (coords) {
178       PetscCall(DMSetCoordinatesLocal(*subdm, coords));
179     } else {
180       PetscCall(DMGetCoordinates(dm, &coords));
181       if (coords) PetscCall(DMSetCoordinates(*subdm, coords));
182     }
183 
184     PetscCall(DMSetType(*subdm, DMDA));
185     PetscCall(DMSetDimension(*subdm, dm->dim));
186     PetscCall(DMDASetSizes(*subdm, da->M, da->N, da->P));
187     PetscCall(DMDASetNumProcs(*subdm, da->m, da->n, da->p));
188     PetscCall(DMDASetBoundaryType(*subdm, da->bx, da->by, da->bz));
189     PetscCall(DMDASetDof(*subdm, numFields));
190     PetscCall(DMDASetStencilType(*subdm, da->stencil_type));
191     PetscCall(DMDASetStencilWidth(*subdm, da->s));
192     PetscCall(DMDASetOwnershipRanges(*subdm, da->lx, da->ly, da->lz));
193   }
194   if (is) {
195     PetscInt *indices, cnt = 0, dof = da->w, i, j;
196 
197     PetscCall(PetscMalloc1(da->Nlocal * numFields / dof, &indices));
198     for (i = da->base / dof; i < (da->base + da->Nlocal) / dof; ++i) {
199       for (j = 0; j < numFields; ++j) indices[cnt++] = dof * i + fields[j];
200     }
201     PetscCheck(cnt == da->Nlocal * numFields / dof, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count %" PetscInt_FMT " does not equal expected value %" PetscInt_FMT, cnt, da->Nlocal * numFields / dof);
202     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), cnt, indices, PETSC_OWN_POINTER, is));
203   }
204   PetscFunctionReturn(PETSC_SUCCESS);
205 }
206 
207 static PetscErrorCode DMCreateFieldDecomposition_DA(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
208 {
209   PetscInt i;
210   DM_DA   *dd  = (DM_DA *)dm->data;
211   PetscInt dof = dd->w;
212 
213   PetscFunctionBegin;
214   if (len) *len = dof;
215   if (islist) {
216     Vec      v;
217     PetscInt rstart, n;
218 
219     PetscCall(DMGetGlobalVector(dm, &v));
220     PetscCall(VecGetOwnershipRange(v, &rstart, NULL));
221     PetscCall(VecGetLocalSize(v, &n));
222     PetscCall(DMRestoreGlobalVector(dm, &v));
223     PetscCall(PetscMalloc1(dof, islist));
224     for (i = 0; i < dof; i++) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)dm), n / dof, rstart + i, dof, &(*islist)[i]));
225   }
226   if (namelist) {
227     PetscCall(PetscMalloc1(dof, namelist));
228     PetscCheck(dd->fieldname, PETSC_COMM_SELF, PETSC_ERR_SUP, "Currently DMDA must have fieldnames");
229     for (i = 0; i < dof; i++) PetscCall(PetscStrallocpy(dd->fieldname[i], &(*namelist)[i]));
230   }
231   if (dmlist) {
232     DM da;
233 
234     PetscCall(DMDACreate(PetscObjectComm((PetscObject)dm), &da));
235     PetscCall(DMSetDimension(da, dm->dim));
236     PetscCall(DMDASetSizes(da, dd->M, dd->N, dd->P));
237     PetscCall(DMDASetNumProcs(da, dd->m, dd->n, dd->p));
238     PetscCall(DMDASetBoundaryType(da, dd->bx, dd->by, dd->bz));
239     PetscCall(DMDASetDof(da, 1));
240     PetscCall(DMDASetStencilType(da, dd->stencil_type));
241     PetscCall(DMDASetStencilWidth(da, dd->s));
242     PetscCall(DMSetUp(da));
243     PetscCall(PetscMalloc1(dof, dmlist));
244     for (i = 0; i < dof - 1; i++) PetscCall(PetscObjectReference((PetscObject)da));
245     for (i = 0; i < dof; i++) (*dmlist)[i] = da;
246   }
247   PetscFunctionReturn(PETSC_SUCCESS);
248 }
249 
250 static PetscErrorCode DMClone_DA(DM dm, DM *newdm)
251 {
252   DM_DA *da = (DM_DA *)dm->data;
253 
254   PetscFunctionBegin;
255   PetscCall(DMSetType(*newdm, DMDA));
256   PetscCall(DMSetDimension(*newdm, dm->dim));
257   PetscCall(DMDASetSizes(*newdm, da->M, da->N, da->P));
258   PetscCall(DMDASetNumProcs(*newdm, da->m, da->n, da->p));
259   PetscCall(DMDASetBoundaryType(*newdm, da->bx, da->by, da->bz));
260   PetscCall(DMDASetDof(*newdm, da->w));
261   PetscCall(DMDASetStencilType(*newdm, da->stencil_type));
262   PetscCall(DMDASetStencilWidth(*newdm, da->s));
263   PetscCall(DMDASetOwnershipRanges(*newdm, da->lx, da->ly, da->lz));
264   PetscCall(DMSetUp(*newdm));
265   PetscFunctionReturn(PETSC_SUCCESS);
266 }
267 
268 static PetscErrorCode DMHasCreateInjection_DA(DM dm, PetscBool *flg)
269 {
270   DM_DA *da = (DM_DA *)dm->data;
271 
272   PetscFunctionBegin;
273   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
274   PetscAssertPointer(flg, 2);
275   *flg = da->interptype == DMDA_Q1 ? PETSC_TRUE : PETSC_FALSE;
276   PetscFunctionReturn(PETSC_SUCCESS);
277 }
278 
279 static PetscErrorCode DMGetDimPoints_DA(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
280 {
281   PetscFunctionBegin;
282   PetscCall(DMDAGetDepthStratum(dm, dim, pStart, pEnd));
283   PetscFunctionReturn(PETSC_SUCCESS);
284 }
285 
286 static PetscErrorCode DMGetNeighbors_DA(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
287 {
288   PetscInt        dim;
289   DMDAStencilType st;
290 
291   PetscFunctionBegin;
292   PetscCall(DMDAGetNeighbors(dm, ranks));
293   PetscCall(DMDAGetInfo(dm, &dim, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &st));
294 
295   switch (dim) {
296   case 1:
297     *nranks = 3;
298     /* if (st == DMDA_STENCIL_STAR) *nranks = 3; */
299     break;
300   case 2:
301     *nranks = 9;
302     /* if (st == DMDA_STENCIL_STAR) *nranks = 5; */
303     break;
304   case 3:
305     *nranks = 27;
306     /* if (st == DMDA_STENCIL_STAR) *nranks = 7; */
307     break;
308   default:
309     break;
310   }
311   PetscFunctionReturn(PETSC_SUCCESS);
312 }
313 
314 /*MC
315    DMDA = "da" - A `DM` object that is used to help solve PDEs on a structured grid (or mesh) in 1, 2, or 3 dimensions.
316 
317    Level: intermediate
318 
319    Notes:
320    In the global representation of the vectors each process stores a non-overlapping rectangular (or slab in 3d) portion of the grid points.
321    In the local representation these rectangular regions (slabs) are extended in all directions by a stencil width set with `DMDASetStencilWidth()`.
322 
323    The vectors can be thought of as either cell centered or vertex centered on the grid (or mesh). But some variables cannot be cell centered and others
324    vertex centered; see the documentation for `DMSTAG`, a similar `DM` implementation which supports more general staggered grids.
325 
326   Periodic boundary conditions can be handled by using a `DMBoundaryType` of `DM_BOUNDARY_PERIODIC` provided with `DMDASetBoundaryType()`.
327   Other `DMBoundaryType`values allow for different handling of terms along the boundary of the grid (or mesh).
328 
329 .seealso: [](sec_struct), `DMType`, `DMCOMPOSITE`, `DMSTAG`, `DMDACreate()`, `DMCreate()`, `DMSetType()`, `DMDASetStencilWidth()`, `DMDASetStencilType()`,
330           `DMDAStencilType`
331 M*/
332 
333 PETSC_EXTERN PetscErrorCode DMCreate_DA(DM da)
334 {
335   DM_DA *dd;
336 
337   PetscFunctionBegin;
338   PetscAssertPointer(da, 1);
339   PetscCall(PetscNew(&dd));
340   da->data = dd;
341 
342   da->dim        = -1;
343   dd->interptype = DMDA_Q1;
344   dd->refine_x   = 2;
345   dd->refine_y   = 2;
346   dd->refine_z   = 2;
347   dd->coarsen_x  = 2;
348   dd->coarsen_y  = 2;
349   dd->coarsen_z  = 2;
350   dd->fieldname  = NULL;
351   dd->nlocal     = -1;
352   dd->Nlocal     = -1;
353   dd->M          = -1;
354   dd->N          = -1;
355   dd->P          = -1;
356   dd->m          = -1;
357   dd->n          = -1;
358   dd->p          = -1;
359   dd->w          = -1;
360   dd->s          = -1;
361 
362   dd->xs = -1;
363   dd->xe = -1;
364   dd->ys = -1;
365   dd->ye = -1;
366   dd->zs = -1;
367   dd->ze = -1;
368   dd->Xs = -1;
369   dd->Xe = -1;
370   dd->Ys = -1;
371   dd->Ye = -1;
372   dd->Zs = -1;
373   dd->Ze = -1;
374 
375   dd->Nsub = 1;
376   dd->xol  = 0;
377   dd->yol  = 0;
378   dd->zol  = 0;
379   dd->xo   = 0;
380   dd->yo   = 0;
381   dd->zo   = 0;
382   dd->Mo   = -1;
383   dd->No   = -1;
384   dd->Po   = -1;
385 
386   dd->gtol = NULL;
387   dd->ltol = NULL;
388   dd->ao   = NULL;
389   PetscCall(PetscStrallocpy(AOBASIC, (char **)&dd->aotype));
390   dd->base         = -1;
391   dd->bx           = DM_BOUNDARY_NONE;
392   dd->by           = DM_BOUNDARY_NONE;
393   dd->bz           = DM_BOUNDARY_NONE;
394   dd->stencil_type = DMDA_STENCIL_BOX;
395   dd->interptype   = DMDA_Q1;
396   dd->lx           = NULL;
397   dd->ly           = NULL;
398   dd->lz           = NULL;
399 
400   dd->elementtype = DMDA_ELEMENT_Q1;
401 
402   da->ops->globaltolocalbegin        = DMGlobalToLocalBegin_DA;
403   da->ops->globaltolocalend          = DMGlobalToLocalEnd_DA;
404   da->ops->localtoglobalbegin        = DMLocalToGlobalBegin_DA;
405   da->ops->localtoglobalend          = DMLocalToGlobalEnd_DA;
406   da->ops->localtolocalbegin         = DMLocalToLocalBegin_DA;
407   da->ops->localtolocalend           = DMLocalToLocalEnd_DA;
408   da->ops->createglobalvector        = DMCreateGlobalVector_DA;
409   da->ops->createlocalvector         = DMCreateLocalVector_DA;
410   da->ops->createinterpolation       = DMCreateInterpolation_DA;
411   da->ops->getcoloring               = DMCreateColoring_DA;
412   da->ops->creatematrix              = DMCreateMatrix_DA;
413   da->ops->refine                    = DMRefine_DA;
414   da->ops->coarsen                   = DMCoarsen_DA;
415   da->ops->refinehierarchy           = DMRefineHierarchy_DA;
416   da->ops->coarsenhierarchy          = DMCoarsenHierarchy_DA;
417   da->ops->createinjection           = DMCreateInjection_DA;
418   da->ops->hascreateinjection        = DMHasCreateInjection_DA;
419   da->ops->destroy                   = DMDestroy_DA;
420   da->ops->view                      = NULL;
421   da->ops->setfromoptions            = DMSetFromOptions_DA;
422   da->ops->setup                     = DMSetUp_DA;
423   da->ops->clone                     = DMClone_DA;
424   da->ops->load                      = DMLoad_DA;
425   da->ops->createcoordinatedm        = DMCreateCoordinateDM_DA;
426   da->ops->createcellcoordinatedm    = NULL;
427   da->ops->createsubdm               = DMCreateSubDM_DA;
428   da->ops->createfielddecomposition  = DMCreateFieldDecomposition_DA;
429   da->ops->createdomaindecomposition = DMCreateDomainDecomposition_DA;
430   da->ops->createddscatters          = DMCreateDomainDecompositionScatters_DA;
431   da->ops->getdimpoints              = DMGetDimPoints_DA;
432   da->ops->getneighbors              = DMGetNeighbors_DA;
433   da->ops->getlocalboundingbox       = DMGetLocalBoundingBox_DA;
434   da->ops->locatepoints              = DMLocatePoints_DA_Regular;
435   da->ops->getcompatibility          = DMGetCompatibility_DA;
436   PetscCall(PetscObjectComposeFunction((PetscObject)da, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_DMDA));
437   PetscFunctionReturn(PETSC_SUCCESS);
438 }
439 
440 /*@
441   DMDACreate - Creates a `DMDA` object for managing structured grids.
442 
443   Collective
444 
445   Input Parameter:
446 . comm - The communicator for the `DMDA` object
447 
448   Output Parameter:
449 . da - the `DMDA` object
450 
451   Level: advanced
452 
453   Notes:
454   See [](sec_struct) for details on the construction of a `DMDA`
455 
456   `DMDACreate1d()`, `DMDACreate2d()`, and `DMDACreate3d()` are convenience routines to quickly completely create a `DMDA`
457 
458 .seealso: [](sec_struct), `DM`, `DMDA`, `DMSetUp()`, `DMDASetSizes()`, `DMClone()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`
459 @*/
460 PetscErrorCode DMDACreate(MPI_Comm comm, DM *da)
461 {
462   PetscFunctionBegin;
463   PetscAssertPointer(da, 2);
464   PetscCall(DMCreate(comm, da));
465   PetscCall(DMSetType(*da, DMDA));
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468