1 #include <petsc/private/dmmbimpl.h> 2 #include <petscdmmoab.h> 3 #include <MBTagConventions.hpp> 4 #include <moab/NestedRefine.hpp> 5 6 /*@C 7 DMMoabGenerateHierarchy - Generate a multi-level uniform refinement hierarchy 8 by succesively refining a coarse mesh, already defined in the DM object 9 provided by the user. 10 11 Collective 12 13 Input Parameter: 14 . dmb - The DMMoab object 15 16 Output Parameters: 17 + nlevels - The number of levels of refinement needed to generate the hierarchy 18 - ldegrees - The degree of refinement at each level in the hierarchy 19 20 Level: beginner 21 22 @*/ 23 PetscErrorCode DMMoabGenerateHierarchy(DM dm, PetscInt nlevels, PetscInt *ldegrees) { 24 DM_Moab *dmmoab; 25 moab::ErrorCode merr; 26 PetscInt *pdegrees, ilevel; 27 std::vector<moab::EntityHandle> hsets; 28 29 PetscFunctionBegin; 30 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31 dmmoab = (DM_Moab *)(dm)->data; 32 33 if (!ldegrees) { 34 PetscCall(PetscMalloc1(nlevels, &pdegrees)); 35 for (ilevel = 0; ilevel < nlevels; ilevel++) pdegrees[ilevel] = 2; /* default = Degree 2 refinement */ 36 } else pdegrees = ldegrees; 37 38 /* initialize set level refinement data for hierarchy */ 39 dmmoab->nhlevels = nlevels; 40 41 /* Instantiate the nested refinement class */ 42 #ifdef MOAB_HAVE_MPI 43 dmmoab->hierarchy = new moab::NestedRefine(dynamic_cast<moab::Core *>(dmmoab->mbiface), dmmoab->pcomm, dmmoab->fileset); 44 #else 45 dmmoab->hierarchy = new moab::NestedRefine(dynamic_cast<moab::Core *>(dmmoab->mbiface), NULL, dmmoab->fileset); 46 #endif 47 48 PetscCall(PetscMalloc1(nlevels + 1, &dmmoab->hsets)); 49 50 /* generate the mesh hierarchy */ 51 merr = dmmoab->hierarchy->generate_mesh_hierarchy(nlevels, pdegrees, hsets, false); 52 MBERRNM(merr); 53 54 #ifdef MOAB_HAVE_MPI 55 if (dmmoab->pcomm->size() > 1) { 56 merr = dmmoab->hierarchy->exchange_ghosts(hsets, dmmoab->nghostrings); 57 MBERRNM(merr); 58 } 59 #endif 60 61 /* copy the mesh sets for nested refinement hierarchy */ 62 dmmoab->hsets[0] = hsets[0]; 63 for (ilevel = 1; ilevel <= nlevels; ilevel++) { 64 dmmoab->hsets[ilevel] = hsets[ilevel]; 65 66 #ifdef MOAB_HAVE_MPI 67 merr = dmmoab->pcomm->assign_global_ids(hsets[ilevel], dmmoab->dim, 0, false, true, false); 68 MBERRNM(merr); 69 #endif 70 71 /* Update material and other geometric tags from parent to child sets */ 72 merr = dmmoab->hierarchy->update_special_tags(ilevel, hsets[ilevel]); 73 MBERRNM(merr); 74 } 75 76 hsets.clear(); 77 if (!ldegrees) { PetscCall(PetscFree(pdegrees)); } 78 PetscFunctionReturn(0); 79 } 80 81 /*@C 82 DMRefineHierarchy_Moab - Generate a multi-level DM hierarchy 83 by succesively refining a coarse mesh. 84 85 Collective 86 87 Input Parameter: 88 . dm - The DMMoab object 89 90 Output Parameters: 91 + nlevels - The number of levels of refinement needed to generate the hierarchy 92 - dmf - The DM objects after successive refinement of the hierarchy 93 94 Level: beginner 95 96 @*/ 97 PETSC_EXTERN PetscErrorCode DMRefineHierarchy_Moab(DM dm, PetscInt nlevels, DM dmf[]) { 98 PetscInt i; 99 100 PetscFunctionBegin; 101 102 PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &dmf[0])); 103 for (i = 1; i < nlevels; i++) { PetscCall(DMRefine(dmf[i - 1], PetscObjectComm((PetscObject)dm), &dmf[i])); } 104 PetscFunctionReturn(0); 105 } 106 107 /*@C 108 DMCoarsenHierarchy_Moab - Generate a multi-level DM hierarchy 109 by succesively coarsening a refined mesh. 110 111 Collective 112 113 Input Parameter: 114 . dm - The DMMoab object 115 116 Output Parameters: 117 + nlevels - The number of levels of refinement needed to generate the hierarchy 118 - dmc - The DM objects after successive coarsening of the hierarchy 119 120 Level: beginner 121 122 @*/ 123 PETSC_EXTERN PetscErrorCode DMCoarsenHierarchy_Moab(DM dm, PetscInt nlevels, DM dmc[]) { 124 PetscInt i; 125 126 PetscFunctionBegin; 127 128 PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &dmc[0])); 129 for (i = 1; i < nlevels; i++) { PetscCall(DMCoarsen(dmc[i - 1], PetscObjectComm((PetscObject)dm), &dmc[i])); } 130 PetscFunctionReturn(0); 131 } 132 133 PETSC_EXTERN PetscErrorCode DMMoab_Compute_NNZ_From_Connectivity(DM, PetscInt *, PetscInt *, PetscInt *, PetscInt *, PetscBool); 134 135 /*@C 136 DMCreateInterpolation_Moab - Generate the interpolation operators to transform 137 operators (matrices, vectors) from parent level to child level as defined by 138 the DM inputs provided by the user. 139 140 Collective 141 142 Input Parameters: 143 + dm1 - The DMMoab object 144 - dm2 - the second, finer DMMoab object 145 146 Output Parameters: 147 + interpl - The interpolation operator for transferring data between the levels 148 - vec - The scaling vector (optional) 149 150 Level: developer 151 152 @*/ 153 PETSC_EXTERN PetscErrorCode DMCreateInterpolation_Moab(DM dmp, DM dmc, Mat *interpl, Vec *vec) { 154 DM_Moab *dmbp, *dmbc; 155 moab::ErrorCode merr; 156 PetscInt dim; 157 PetscReal factor; 158 PetscInt innz, *nnz, ionz, *onz; 159 PetscInt nlsizp, nlsizc, nlghsizp, ngsizp, ngsizc; 160 const PetscBool use_consistent_bases = PETSC_TRUE; 161 162 PetscFunctionBegin; 163 PetscValidHeaderSpecific(dmp, DM_CLASSID, 1); 164 PetscValidHeaderSpecific(dmc, DM_CLASSID, 2); 165 dmbp = (DM_Moab *)(dmp)->data; 166 dmbc = (DM_Moab *)(dmc)->data; 167 nlsizp = dmbp->nloc; // *dmb1->numFields; 168 nlsizc = dmbc->nloc; // *dmb2->numFields; 169 ngsizp = dmbp->n; // *dmb1->numFields; 170 ngsizc = dmbc->n; // *dmb2->numFields; 171 nlghsizp = (dmbp->nloc + dmbp->nghost); // *dmb1->numFields; 172 173 // Columns = Parent DoFs ; Rows = Child DoFs 174 // Interpolation matrix: \sum_{i=1}^P Owned(Child) * (Owned(Parent) + Ghosted(Parent)) 175 // Size: nlsizc * nlghsizp 176 PetscInfo(NULL, "Creating interpolation matrix %" PetscInt_FMT " X %" PetscInt_FMT " to apply transformation between levels %" PetscInt_FMT " -> %" PetscInt_FMT ".\n", ngsizc, nlghsizp, dmbp->hlevel, dmbc->hlevel); 177 178 PetscCall(DMGetDimension(dmp, &dim)); 179 180 /* allocate the nnz, onz arrays based on block size and local nodes */ 181 PetscCall(PetscCalloc2(nlsizc, &nnz, nlsizc, &onz)); 182 183 /* Loop through the local elements and compute the relation between the current parent and the refined_level. */ 184 for (moab::Range::iterator iter = dmbc->vowned->begin(); iter != dmbc->vowned->end(); iter++) { 185 const moab::EntityHandle vhandle = *iter; 186 /* define local variables */ 187 moab::EntityHandle parent; 188 std::vector<moab::EntityHandle> adjs; 189 moab::Range found; 190 191 /* store the vertex DoF number */ 192 const int ldof = dmbc->lidmap[vhandle - dmbc->seqstart]; 193 194 /* Get adjacency information for current vertex - i.e., all elements of dimension (dim) that connects 195 to the current vertex. We can then decipher if a vertex is ghosted or not and compute the 196 non-zero pattern accordingly. */ 197 merr = dmbc->hierarchy->get_adjacencies(vhandle, dmbc->dim, adjs); 198 MBERRNM(merr); 199 200 /* loop over vertices and update the number of connectivity */ 201 for (unsigned jter = 0; jter < adjs.size(); jter++) { 202 const moab::EntityHandle jhandle = adjs[jter]; 203 204 /* Get the relation between the current (coarse) parent and its corresponding (finer) children elements */ 205 merr = dmbc->hierarchy->child_to_parent(jhandle, dmbc->hlevel, dmbp->hlevel, &parent); 206 MBERRNM(merr); 207 208 /* Get connectivity information in canonical ordering for the local element */ 209 std::vector<moab::EntityHandle> connp; 210 merr = dmbp->hierarchy->get_connectivity(parent, dmbp->hlevel, connp); 211 MBERRNM(merr); 212 213 for (unsigned ic = 0; ic < connp.size(); ++ic) { 214 /* loop over each element connected to the adjacent vertex and update as needed */ 215 /* find the truly user-expected layer of ghosted entities to decipher NNZ pattern */ 216 if (found.find(connp[ic]) != found.end()) continue; /* make sure we don't double count shared vertices */ 217 if (dmbp->vghost->find(connp[ic]) != dmbp->vghost->end()) onz[ldof]++; /* update out-of-proc onz */ 218 else nnz[ldof]++; /* else local vertex */ 219 found.insert(connp[ic]); 220 } 221 } 222 } 223 224 for (int i = 0; i < nlsizc; i++) nnz[i] += 1; /* self count the node */ 225 226 ionz = onz[0]; 227 innz = nnz[0]; 228 for (int tc = 0; tc < nlsizc; tc++) { 229 // check for maximum allowed sparsity = fully dense 230 nnz[tc] = std::min(nlsizp, nnz[tc]); 231 onz[tc] = std::min(ngsizp - nlsizp, onz[tc]); 232 233 PetscInfo(NULL, " %d: NNZ = %d, ONZ = %d\n", tc, nnz[tc], onz[tc]); 234 235 innz = (innz < nnz[tc] ? nnz[tc] : innz); 236 ionz = (ionz < onz[tc] ? onz[tc] : ionz); 237 } 238 239 /* create interpolation matrix */ 240 PetscCall(MatCreate(PetscObjectComm((PetscObject)dmc), interpl)); 241 PetscCall(MatSetSizes(*interpl, nlsizc, nlsizp, ngsizc, ngsizp)); 242 PetscCall(MatSetType(*interpl, MATAIJ)); 243 PetscCall(MatSetFromOptions(*interpl)); 244 245 PetscCall(MatSeqAIJSetPreallocation(*interpl, innz, nnz)); 246 PetscCall(MatMPIAIJSetPreallocation(*interpl, innz, nnz, ionz, onz)); 247 248 /* clean up temporary memory */ 249 PetscCall(PetscFree2(nnz, onz)); 250 251 /* set up internal matrix data-structures */ 252 PetscCall(MatSetUp(*interpl)); 253 254 /* Define variables for assembly */ 255 std::vector<moab::EntityHandle> children; 256 std::vector<moab::EntityHandle> connp, connc; 257 std::vector<PetscReal> pcoords, ccoords, values_phi; 258 259 if (use_consistent_bases) { 260 const moab::EntityHandle ehandle = dmbp->elocal->front(); 261 262 merr = dmbp->hierarchy->parent_to_child(ehandle, dmbp->hlevel, dmbc->hlevel, children); 263 MBERRNM(merr); 264 265 /* Get connectivity and coordinates of the parent vertices */ 266 merr = dmbp->hierarchy->get_connectivity(ehandle, dmbp->hlevel, connp); 267 MBERRNM(merr); 268 merr = dmbc->mbiface->get_connectivity(&children[0], children.size(), connc); 269 MBERRNM(merr); 270 271 std::vector<PetscReal> natparam(3 * connc.size(), 0.0); 272 pcoords.resize(connp.size() * 3); 273 ccoords.resize(connc.size() * 3); 274 values_phi.resize(connp.size() * connc.size()); 275 /* Get coordinates for connectivity entities in canonical order for both coarse and finer levels */ 276 merr = dmbp->hierarchy->get_coordinates(&connp[0], connp.size(), dmbp->hlevel, &pcoords[0]); 277 MBERRNM(merr); 278 merr = dmbc->hierarchy->get_coordinates(&connc[0], connc.size(), dmbc->hlevel, &ccoords[0]); 279 MBERRNM(merr); 280 281 /* Set values: For each DOF in coarse grid cell, set the contribution or PHI evaluated at each fine grid DOF point */ 282 for (unsigned tc = 0; tc < connc.size(); tc++) { 283 const PetscInt offset = tc * 3; 284 285 /* Scale ccoords relative to pcoords */ 286 PetscCall(DMMoabPToRMapping(dim, connp.size(), &pcoords[0], &ccoords[offset], &natparam[offset], &values_phi[connp.size() * tc])); 287 } 288 } else { 289 factor = std::pow(2.0 /*degree_P_for_refinement*/, (dmbc->hlevel - dmbp->hlevel) * dmbp->dim * 1.0); 290 } 291 292 /* TODO: Decipher the correct non-zero pattern. There is still some issue with onz allocation */ 293 PetscCall(MatSetOption(*interpl, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 294 295 /* Loop through the remaining vertices. These vertices appear only on the current refined_level. */ 296 for (moab::Range::iterator iter = dmbp->elocal->begin(); iter != dmbp->elocal->end(); iter++) { 297 const moab::EntityHandle ehandle = *iter; 298 299 /* Get the relation between the current (coarse) parent and its corresponding (finer) children elements */ 300 children.clear(); 301 connc.clear(); 302 merr = dmbp->hierarchy->parent_to_child(ehandle, dmbp->hlevel, dmbc->hlevel, children); 303 MBERRNM(merr); 304 305 /* Get connectivity and coordinates of the parent vertices */ 306 merr = dmbp->hierarchy->get_connectivity(ehandle, dmbp->hlevel, connp); 307 MBERRNM(merr); 308 merr = dmbc->mbiface->get_connectivity(&children[0], children.size(), connc); 309 MBERRNM(merr); 310 311 pcoords.resize(connp.size() * 3); 312 ccoords.resize(connc.size() * 3); 313 /* Get coordinates for connectivity entities in canonical order for both coarse and finer levels */ 314 merr = dmbp->hierarchy->get_coordinates(&connp[0], connp.size(), dmbp->hlevel, &pcoords[0]); 315 MBERRNM(merr); 316 merr = dmbc->hierarchy->get_coordinates(&connc[0], connc.size(), dmbc->hlevel, &ccoords[0]); 317 MBERRNM(merr); 318 319 std::vector<int> dofsp(connp.size()), dofsc(connc.size()); 320 /* TODO: specific to scalar system - use GetDofs */ 321 PetscCall(DMMoabGetDofsBlocked(dmp, connp.size(), &connp[0], &dofsp[0])); 322 PetscCall(DMMoabGetDofsBlocked(dmc, connc.size(), &connc[0], &dofsc[0])); 323 324 /* Compute the actual interpolation weights when projecting solution/residual between levels */ 325 if (use_consistent_bases) { 326 /* Use the cached values of natural parameteric coordinates and basis pre-evaluated. 327 We are making an assumption here that UMR used in GMG to generate the hierarchy uses 328 the same template for all elements; This will fail for mixed element meshes (TRI/QUAD). 329 330 TODO: Fix the above assumption by caching data for families (especially for Tets and mixed meshes) 331 */ 332 333 /* Set values: For each DOF in coarse grid cell, set the contribution or PHI evaluated at each fine grid DOF point */ 334 for (unsigned tc = 0; tc < connc.size(); tc++) { 335 /* TODO: Check if we should be using INSERT_VALUES instead */ 336 PetscCall(MatSetValues(*interpl, 1, &dofsc[tc], connp.size(), &dofsp[0], &values_phi[connp.size() * tc], ADD_VALUES)); 337 } 338 } else { 339 /* Compute the interpolation weights by determining distance of 1-ring 340 neighbor vertices from current vertex 341 342 This should be used only when FEM basis is not used for the discretization. 343 Else, the consistent interface to compute the basis function for interpolation 344 between the levels should be evaluated correctly to preserve convergence of GMG. 345 Shephard's basis will be terrible for any unsmooth problems. 346 */ 347 values_phi.resize(connp.size()); 348 for (unsigned tc = 0; tc < connc.size(); tc++) { 349 PetscReal normsum = 0.0; 350 for (unsigned tp = 0; tp < connp.size(); tp++) { 351 values_phi[tp] = 0.0; 352 for (unsigned k = 0; k < 3; k++) values_phi[tp] += std::pow(pcoords[tp * 3 + k] - ccoords[k + tc * 3], dim); 353 if (values_phi[tp] < 1e-12) { 354 values_phi[tp] = 1e12; 355 } else { 356 //values_phi[tp] = std::pow(values_phi[tp], -1.0/dim); 357 values_phi[tp] = std::pow(values_phi[tp], -1.0); 358 normsum += values_phi[tp]; 359 } 360 } 361 for (unsigned tp = 0; tp < connp.size(); tp++) { 362 if (values_phi[tp] > 1e11) values_phi[tp] = factor * 0.5 / connp.size(); 363 else values_phi[tp] = factor * values_phi[tp] * 0.5 / (connp.size() * normsum); 364 } 365 PetscCall(MatSetValues(*interpl, 1, &dofsc[tc], connp.size(), &dofsp[0], &values_phi[0], ADD_VALUES)); 366 } 367 } 368 } 369 if (vec) *vec = NULL; 370 PetscCall(MatAssemblyBegin(*interpl, MAT_FINAL_ASSEMBLY)); 371 PetscCall(MatAssemblyEnd(*interpl, MAT_FINAL_ASSEMBLY)); 372 PetscFunctionReturn(0); 373 } 374 375 /*@C 376 DMCreateInjection_Moab - Generate a multi-level uniform refinement hierarchy 377 by succesively refining a coarse mesh, already defined in the DM object 378 provided by the user. 379 380 Collective 381 382 Input Parameter: 383 . dmb - The DMMoab object 384 385 Output Parameters: 386 + nlevels - The number of levels of refinement needed to generate the hierarchy 387 - ldegrees - The degree of refinement at each level in the hierarchy 388 389 Level: beginner 390 391 @*/ 392 PETSC_EXTERN PetscErrorCode DMCreateInjection_Moab(DM dm1, DM dm2, VecScatter *ctx) { 393 //DM_Moab *dmmoab; 394 395 PetscFunctionBegin; 396 PetscValidHeaderSpecific(dm1, DM_CLASSID, 1); 397 PetscValidHeaderSpecific(dm2, DM_CLASSID, 2); 398 //dmmoab = (DM_Moab*)(dm1)->data; 399 400 PetscPrintf(PETSC_COMM_WORLD, "[DMCreateInjection_Moab] :: Placeholder\n"); 401 PetscFunctionReturn(0); 402 } 403 404 static PetscErrorCode DMMoab_UMR_Private(DM dm, MPI_Comm comm, PetscBool refine, DM *dmref) { 405 PetscInt i, dim; 406 DM dm2; 407 moab::ErrorCode merr; 408 DM_Moab *dmb = (DM_Moab *)dm->data, *dd2; 409 410 PetscFunctionBegin; 411 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 412 PetscValidPointer(dmref, 4); 413 414 if ((dmb->hlevel == dmb->nhlevels && refine) || (dmb->hlevel == 0 && !refine)) { 415 if (dmb->hlevel + 1 > dmb->nhlevels && refine) PetscInfo(NULL, "Invalid multigrid refinement hierarchy level specified (%" PetscInt_FMT "). MOAB UMR max levels = %" PetscInt_FMT ". Creating a NULL object.\n", dmb->hlevel + 1, dmb->nhlevels); 416 if (dmb->hlevel - 1 < 0 && !refine) PetscInfo(NULL, "Invalid multigrid coarsen hierarchy level specified (%" PetscInt_FMT "). Creating a NULL object.\n", dmb->hlevel - 1); 417 *dmref = PETSC_NULL; 418 PetscFunctionReturn(0); 419 } 420 421 PetscCall(DMMoabCreate(PetscObjectComm((PetscObject)dm), &dm2)); 422 dd2 = (DM_Moab *)dm2->data; 423 424 dd2->mbiface = dmb->mbiface; 425 #ifdef MOAB_HAVE_MPI 426 dd2->pcomm = dmb->pcomm; 427 #endif 428 dd2->icreatedinstance = PETSC_FALSE; 429 dd2->nghostrings = dmb->nghostrings; 430 431 /* set the new level based on refinement/coarsening */ 432 if (refine) { 433 dd2->hlevel = dmb->hlevel + 1; 434 } else { 435 dd2->hlevel = dmb->hlevel - 1; 436 } 437 438 /* Copy the multilevel hierarchy pointers in MOAB */ 439 dd2->hierarchy = dmb->hierarchy; 440 dd2->nhlevels = dmb->nhlevels; 441 PetscCall(PetscMalloc1(dd2->nhlevels + 1, &dd2->hsets)); 442 for (i = 0; i <= dd2->nhlevels; i++) { dd2->hsets[i] = dmb->hsets[i]; } 443 dd2->fileset = dd2->hsets[dd2->hlevel]; 444 445 /* do the remaining initializations for DMMoab */ 446 dd2->bs = dmb->bs; 447 dd2->numFields = dmb->numFields; 448 dd2->rw_dbglevel = dmb->rw_dbglevel; 449 dd2->partition_by_rank = dmb->partition_by_rank; 450 PetscCall(PetscStrcpy(dd2->extra_read_options, dmb->extra_read_options)); 451 PetscCall(PetscStrcpy(dd2->extra_write_options, dmb->extra_write_options)); 452 dd2->read_mode = dmb->read_mode; 453 dd2->write_mode = dmb->write_mode; 454 455 /* set global ID tag handle */ 456 PetscCall(DMMoabSetLocalToGlobalTag(dm2, dmb->ltog_tag)); 457 458 merr = dd2->mbiface->tag_get_handle(MATERIAL_SET_TAG_NAME, dd2->material_tag); 459 MBERRNM(merr); 460 461 PetscCall(DMSetOptionsPrefix(dm2, ((PetscObject)dm)->prefix)); 462 PetscCall(DMGetDimension(dm, &dim)); 463 PetscCall(DMSetDimension(dm2, dim)); 464 465 /* allow overloaded (user replaced) operations to be inherited by refinement clones */ 466 dm2->ops->creatematrix = dm->ops->creatematrix; 467 468 /* copy fill information if given */ 469 PetscCall(DMMoabSetBlockFills(dm2, dmb->dfill, dmb->ofill)); 470 471 /* copy vector type information */ 472 PetscCall(DMSetMatType(dm2, dm->mattype)); 473 PetscCall(DMSetVecType(dm2, dm->vectype)); 474 dd2->numFields = dmb->numFields; 475 if (dmb->numFields) { PetscCall(DMMoabSetFieldNames(dm2, dmb->numFields, dmb->fieldNames)); } 476 477 PetscCall(DMSetFromOptions(dm2)); 478 479 /* recreate Dof numbering for the refined DM and make sure the distribution is correctly populated */ 480 PetscCall(DMSetUp(dm2)); 481 482 *dmref = dm2; 483 PetscFunctionReturn(0); 484 } 485 486 /*@C 487 DMRefine_Moab - Generate a multi-level uniform refinement hierarchy 488 by succesively refining a coarse mesh, already defined in the DM object 489 provided by the user. 490 491 Collective on dm 492 493 Input Parameters: 494 + dm - The DMMoab object 495 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 496 497 Output Parameter: 498 . dmf - the refined DM, or NULL 499 500 Note: If no refinement was done, the return value is NULL 501 502 Level: developer 503 504 @*/ 505 PETSC_EXTERN PetscErrorCode DMRefine_Moab(DM dm, MPI_Comm comm, DM *dmf) { 506 PetscFunctionBegin; 507 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 508 509 PetscCall(DMMoab_UMR_Private(dm, comm, PETSC_TRUE, dmf)); 510 PetscFunctionReturn(0); 511 } 512 513 /*@C 514 DMCoarsen_Moab - Generate a multi-level uniform refinement hierarchy 515 by succesively refining a coarse mesh, already defined in the DM object 516 provided by the user. 517 518 Collective on dm 519 520 Input Parameters: 521 + dm - The DMMoab object 522 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 523 524 Output Parameter: 525 . dmf - the coarsened DM, or NULL 526 527 Note: If no coarsening was done, the return value is NULL 528 529 Level: developer 530 531 @*/ 532 PETSC_EXTERN PetscErrorCode DMCoarsen_Moab(DM dm, MPI_Comm comm, DM *dmc) { 533 PetscFunctionBegin; 534 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 535 PetscCall(DMMoab_UMR_Private(dm, comm, PETSC_FALSE, dmc)); 536 PetscFunctionReturn(0); 537 } 538