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