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