Actual source code: dmmbmg.cxx
1: #include <petsc/private/dmmbimpl.h>
2: #include <petscdmmoab.h>
3: #include <MBTagConventions.hpp>
4: #include <moab/NestedRefine.hpp>
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: }
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.
19: Collective
21: Input Parameter:
22: . dm - The `DMMOAB` object
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
28: Level: beginner
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;
39: PetscFunctionBegin;
41: dmmoab = (DM_Moab *)dm->data;
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;
48: /* initialize set level refinement data for hierarchy */
49: dmmoab->nhlevels = nlevels;
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
58: PetscCall(PetscMalloc1(nlevels + 1, &dmmoab->hsets));
60: /* generate the mesh hierarchy */
61: merr = dmmoab->hierarchy->generate_mesh_hierarchy(nlevels, pdegrees, hsets, false);
62: MBERRNM(merr);
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
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];
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
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: }
86: hsets.clear();
87: if (!ldegrees) PetscCall(PetscFree(pdegrees));
88: PetscFunctionReturn(PETSC_SUCCESS);
89: }
91: // PetscClangLinter pragma ignore: -fdoc-*
92: /*
93: DMRefineHierarchy_Moab - Generate a multi-level `DM` hierarchy
94: by succesively refining a coarse mesh.
96: Collective
98: Input Parameter:
99: . dm - The `DMMOAB` object
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
105: Level: beginner
106: */
107: PETSC_EXTERN PetscErrorCode DMRefineHierarchy_Moab(DM dm, PetscInt nlevels, DM dmf[])
108: {
109: PetscInt i;
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: }
117: // PetscClangLinter pragma ignore: -fdoc-*
118: /*
119: DMCoarsenHierarchy_Moab - Generate a multi-level `DM` hierarchy
120: by succesively coarsening a refined mesh.
122: Collective
124: Input Parameter:
125: . dm - The `DMMOAB` object
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
131: Level: beginner
132: */
133: PETSC_EXTERN PetscErrorCode DMCoarsenHierarchy_Moab(DM dm, PetscInt nlevels, DM dmc[])
134: {
135: PetscInt i;
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: }
143: PETSC_EXTERN PetscErrorCode DMMoab_Compute_NNZ_From_Connectivity(DM, PetscInt *, PetscInt *, PetscInt *, PetscInt *, PetscBool);
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.
151: Collective
153: Input Parameters:
154: + dmp - The `DMMOAB` object
155: - dmc - the second, finer `DMMOAB` object
157: Output Parameters:
158: + interpl - The interpolation operator for transferring data between the levels
159: - vec - The scaling vector (optional)
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;
173: PetscFunctionBegin;
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;
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));
189: PetscCall(DMGetDimension(dmp, &dim));
191: /* allocate the nnz, onz arrays based on block size and local nodes */
192: PetscCall(PetscCalloc2(nlsizc, &nnz, nlsizc, &onz));
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;
202: /* store the vertex DoF number */
203: const int ldof = dmbc->lidmap[vhandle - dmbc->seqstart];
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);
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];
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);
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);
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: }
235: for (int i = 0; i < nlsizc; i++) nnz[i] += 1; /* self count the node */
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]);
244: PetscCall(PetscInfo(NULL, " %d: NNZ = %d, ONZ = %d\n", tc, nnz[tc], onz[tc]));
246: innz = (innz < nnz[tc] ? nnz[tc] : innz);
247: ionz = (ionz < onz[tc] ? onz[tc] : ionz);
248: }
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));
256: PetscCall(MatSeqAIJSetPreallocation(*interpl, innz, nnz));
257: PetscCall(MatMPIAIJSetPreallocation(*interpl, innz, nnz, ionz, onz));
259: /* clean up temporary memory */
260: PetscCall(PetscFree2(nnz, onz));
262: /* set up internal matrix data-structures */
263: PetscCall(MatSetUp(*interpl));
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;
271: if (use_consistent_bases) {
272: const moab::EntityHandle ehandle = dmbp->elocal->front();
274: merr = dmbp->hierarchy->parent_to_child(ehandle, dmbp->hlevel, dmbc->hlevel, children);
275: MBERRNM(merr);
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);
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);
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;
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: }
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));
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;
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);
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);
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);
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]));
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).
343: TODO: Fix the above assumption by caching data for families (especially for Tets and mixed meshes)
344: */
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
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: }
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.
396: Collective
398: Input Parameter:
399: . dmb - The `DMMOAB` object
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
405: Level: beginner
406: */
407: PETSC_EXTERN PetscErrorCode DMCreateInjection_Moab(DM dm1, DM dm2, VecScatter *ctx)
408: {
409: PetscFunctionBegin;
412: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[DMCreateInjection_Moab] :: Placeholder\n"));
413: PetscFunctionReturn(PETSC_SUCCESS);
414: }
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;
423: PetscFunctionBegin;
425: PetscAssertPointer(dmref, 4);
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: }
436: PetscCall(DMMoabCreate(PetscObjectComm((PetscObject)dm), &dm2));
437: dd2 = (DM_Moab *)dm2->data;
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;
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: }
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];
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;
470: /* set global ID tag handle */
471: PetscCall(DMMoabSetLocalToGlobalTag(dm2, dmb->ltog_tag));
473: merr = dd2->mbiface->tag_get_handle(MATERIAL_SET_TAG_NAME, dd2->material_tag);
474: MBERRNM(merr);
476: PetscCall(DMSetOptionsPrefix(dm2, ((PetscObject)dm)->prefix));
477: PetscCall(DMGetDimension(dm, &dim));
478: PetscCall(DMSetDimension(dm2, dim));
480: /* allow overloaded (user replaced) operations to be inherited by refinement clones */
481: dm2->ops->creatematrix = dm->ops->creatematrix;
483: /* copy fill information if given */
484: PetscCall(DMMoabSetBlockFills(dm2, dmb->dfill, dmb->ofill));
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));
492: PetscCall(DMSetFromOptions(dm2));
494: /* recreate Dof numbering for the refined DM and make sure the distribution is correctly populated */
495: PetscCall(DMSetUp(dm2));
497: *dmref = dm2;
498: PetscFunctionReturn(PETSC_SUCCESS);
499: }
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.
507: Collective
509: Input Parameters:
510: + dm - The `DMMOAB` object
511: - comm - the communicator to contain the new DM object (or `MPI_COMM_NULL`)
513: Output Parameter:
514: . dmf - the refined `DM`, or `NULL`
516: Level: developer
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;
526: PetscCall(DMMoab_UMR_Private(dm, comm, PETSC_TRUE, dmf));
527: PetscFunctionReturn(PETSC_SUCCESS);
528: }
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.
536: Collective
538: Input Parameters:
539: + dm - The `DMMOAB` object
540: - comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
542: Output Parameter:
543: . dmc - the coarsened `DM`, or `NULL`
545: Level: developer
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;
554: PetscCall(DMMoab_UMR_Private(dm, comm, PETSC_FALSE, dmc));
555: PetscFunctionReturn(PETSC_SUCCESS);
556: }