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