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