10a96aa3bSJed Brown #include <petscds.h> 20a96aa3bSJed Brown #include <petsc/private/dmimpl.h> 30a96aa3bSJed Brown #include <petsc/private/dmforestimpl.h> 40a96aa3bSJed Brown #include <petsc/private/dmpleximpl.h> 50a96aa3bSJed Brown #include <petsc/private/dmlabelimpl.h> 60a96aa3bSJed Brown #include <petsc/private/viewerimpl.h> 70a96aa3bSJed Brown #include <../src/sys/classes/viewer/impls/vtk/vtkvimpl.h> 80a96aa3bSJed Brown #include "petsc_p4est_package.h" 90a96aa3bSJed Brown 100a96aa3bSJed Brown #if defined(PETSC_HAVE_P4EST) 110a96aa3bSJed Brown 120a96aa3bSJed Brown #if !defined(P4_TO_P8) 130a96aa3bSJed Brown #include <p4est.h> 140a96aa3bSJed Brown #include <p4est_extended.h> 150a96aa3bSJed Brown #include <p4est_geometry.h> 160a96aa3bSJed Brown #include <p4est_ghost.h> 170a96aa3bSJed Brown #include <p4est_lnodes.h> 180a96aa3bSJed Brown #include <p4est_vtk.h> 190a96aa3bSJed Brown #include <p4est_plex.h> 200a96aa3bSJed Brown #include <p4est_bits.h> 210a96aa3bSJed Brown #include <p4est_algorithms.h> 220a96aa3bSJed Brown #else 230a96aa3bSJed Brown #include <p8est.h> 240a96aa3bSJed Brown #include <p8est_extended.h> 250a96aa3bSJed Brown #include <p8est_geometry.h> 260a96aa3bSJed Brown #include <p8est_ghost.h> 270a96aa3bSJed Brown #include <p8est_lnodes.h> 280a96aa3bSJed Brown #include <p8est_vtk.h> 290a96aa3bSJed Brown #include <p8est_plex.h> 300a96aa3bSJed Brown #include <p8est_bits.h> 310a96aa3bSJed Brown #include <p8est_algorithms.h> 320a96aa3bSJed Brown #endif 330a96aa3bSJed Brown 349371c9d4SSatish Balay typedef enum { 359371c9d4SSatish Balay PATTERN_HASH, 369371c9d4SSatish Balay PATTERN_FRACTAL, 379371c9d4SSatish Balay PATTERN_CORNER, 389371c9d4SSatish Balay PATTERN_CENTER, 399371c9d4SSatish Balay PATTERN_COUNT 409371c9d4SSatish Balay } DMRefinePattern; 410a96aa3bSJed Brown static const char *DMRefinePatternName[PATTERN_COUNT] = {"hash", "fractal", "corner", "center"}; 420a96aa3bSJed Brown 439371c9d4SSatish Balay typedef struct _DMRefinePatternCtx { 440a96aa3bSJed Brown PetscInt corner; 450a96aa3bSJed Brown PetscBool fractal[P4EST_CHILDREN]; 460a96aa3bSJed Brown PetscReal hashLikelihood; 470a96aa3bSJed Brown PetscInt maxLevel; 480a96aa3bSJed Brown p4est_refine_t refine_fn; 499371c9d4SSatish Balay } DMRefinePatternCtx; 500a96aa3bSJed Brown 519371c9d4SSatish Balay static int DMRefinePattern_Corner(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) { 520a96aa3bSJed Brown p4est_quadrant_t root, rootcorner; 530a96aa3bSJed Brown DMRefinePatternCtx *ctx; 540a96aa3bSJed Brown 550a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 560a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 570a96aa3bSJed Brown 580a96aa3bSJed Brown root.x = root.y = 0; 590a96aa3bSJed Brown #if defined(P4_TO_P8) 600a96aa3bSJed Brown root.z = 0; 610a96aa3bSJed Brown #endif 620a96aa3bSJed Brown root.level = 0; 630a96aa3bSJed Brown p4est_quadrant_corner_descendant(&root, &rootcorner, ctx->corner, quadrant->level); 640a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant, &rootcorner)) return 1; 650a96aa3bSJed Brown return 0; 660a96aa3bSJed Brown } 670a96aa3bSJed Brown 689371c9d4SSatish Balay static int DMRefinePattern_Center(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) { 690a96aa3bSJed Brown int cid; 700a96aa3bSJed Brown p4est_quadrant_t ancestor, ancestorcorner; 710a96aa3bSJed Brown DMRefinePatternCtx *ctx; 720a96aa3bSJed Brown 730a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 740a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 750a96aa3bSJed Brown if (quadrant->level <= 1) return 1; 760a96aa3bSJed Brown 770a96aa3bSJed Brown p4est_quadrant_ancestor(quadrant, 1, &ancestor); 780a96aa3bSJed Brown cid = p4est_quadrant_child_id(&ancestor); 790a96aa3bSJed Brown p4est_quadrant_corner_descendant(&ancestor, &ancestorcorner, P4EST_CHILDREN - 1 - cid, quadrant->level); 800a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant, &ancestorcorner)) return 1; 810a96aa3bSJed Brown return 0; 820a96aa3bSJed Brown } 830a96aa3bSJed Brown 849371c9d4SSatish Balay static int DMRefinePattern_Fractal(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) { 850a96aa3bSJed Brown int cid; 860a96aa3bSJed Brown DMRefinePatternCtx *ctx; 870a96aa3bSJed Brown 880a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 890a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 900a96aa3bSJed Brown if (!quadrant->level) return 1; 910a96aa3bSJed Brown cid = p4est_quadrant_child_id(quadrant); 920a96aa3bSJed Brown if (ctx->fractal[cid ^ ((int)(quadrant->level % P4EST_CHILDREN))]) return 1; 930a96aa3bSJed Brown return 0; 940a96aa3bSJed Brown } 950a96aa3bSJed Brown 960a96aa3bSJed Brown /* simplified from MurmurHash3 by Austin Appleby */ 970a96aa3bSJed Brown #define DMPROT32(x, y) ((x << y) | (x >> (32 - y))) 989371c9d4SSatish Balay static uint32_t DMPforestHash(const uint32_t *blocks, uint32_t nblocks) { 990a96aa3bSJed Brown uint32_t c1 = 0xcc9e2d51; 1000a96aa3bSJed Brown uint32_t c2 = 0x1b873593; 1010a96aa3bSJed Brown uint32_t r1 = 15; 1020a96aa3bSJed Brown uint32_t r2 = 13; 1030a96aa3bSJed Brown uint32_t m = 5; 1040a96aa3bSJed Brown uint32_t n = 0xe6546b64; 1050a96aa3bSJed Brown uint32_t hash = 0; 1060a96aa3bSJed Brown int len = nblocks * 4; 1070a96aa3bSJed Brown uint32_t i; 1080a96aa3bSJed Brown 1090a96aa3bSJed Brown for (i = 0; i < nblocks; i++) { 1100a96aa3bSJed Brown uint32_t k; 1110a96aa3bSJed Brown 1120a96aa3bSJed Brown k = blocks[i]; 1130a96aa3bSJed Brown k *= c1; 1140a96aa3bSJed Brown k = DMPROT32(k, r1); 1150a96aa3bSJed Brown k *= c2; 1160a96aa3bSJed Brown 1170a96aa3bSJed Brown hash ^= k; 1180a96aa3bSJed Brown hash = DMPROT32(hash, r2) * m + n; 1190a96aa3bSJed Brown } 1200a96aa3bSJed Brown 1210a96aa3bSJed Brown hash ^= len; 1220a96aa3bSJed Brown hash ^= (hash >> 16); 1230a96aa3bSJed Brown hash *= 0x85ebca6b; 1240a96aa3bSJed Brown hash ^= (hash >> 13); 1250a96aa3bSJed Brown hash *= 0xc2b2ae35; 1260a96aa3bSJed Brown hash ^= (hash >> 16); 1270a96aa3bSJed Brown 1280a96aa3bSJed Brown return hash; 1290a96aa3bSJed Brown } 1300a96aa3bSJed Brown 1310a96aa3bSJed Brown #if defined(UINT32_MAX) 1320a96aa3bSJed Brown #define DMP4EST_HASH_MAX UINT32_MAX 1330a96aa3bSJed Brown #else 1340a96aa3bSJed Brown #define DMP4EST_HASH_MAX ((uint32_t)0xffffffff) 1350a96aa3bSJed Brown #endif 1360a96aa3bSJed Brown 1379371c9d4SSatish Balay static int DMRefinePattern_Hash(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) { 1380a96aa3bSJed Brown uint32_t data[5]; 1390a96aa3bSJed Brown uint32_t result; 1400a96aa3bSJed Brown DMRefinePatternCtx *ctx; 1410a96aa3bSJed Brown 1420a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 1430a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 1440a96aa3bSJed Brown data[0] = ((uint32_t)quadrant->level) << 24; 1450a96aa3bSJed Brown data[1] = (uint32_t)which_tree; 1460a96aa3bSJed Brown data[2] = (uint32_t)quadrant->x; 1470a96aa3bSJed Brown data[3] = (uint32_t)quadrant->y; 1480a96aa3bSJed Brown #if defined(P4_TO_P8) 1490a96aa3bSJed Brown data[4] = (uint32_t)quadrant->z; 1500a96aa3bSJed Brown #endif 1510a96aa3bSJed Brown 1520a96aa3bSJed Brown result = DMPforestHash(data, 2 + P4EST_DIM); 1530a96aa3bSJed Brown if (((double)result / (double)DMP4EST_HASH_MAX) < ctx->hashLikelihood) return 1; 1540a96aa3bSJed Brown return 0; 1550a96aa3bSJed Brown } 1560a96aa3bSJed Brown 1570a96aa3bSJed Brown #define DMConvert_pforest_plex _infix_pforest(DMConvert, _plex) 1580a96aa3bSJed Brown static PetscErrorCode DMConvert_pforest_plex(DM, DMType, DM *); 1590a96aa3bSJed Brown 1600a96aa3bSJed Brown #define DMFTopology_pforest _append_pforest(DMFTopology) 1610a96aa3bSJed Brown typedef struct { 1620a96aa3bSJed Brown PetscInt refct; 1630a96aa3bSJed Brown p4est_connectivity_t *conn; 1640a96aa3bSJed Brown p4est_geometry_t *geom; 1650a96aa3bSJed Brown PetscInt *tree_face_to_uniq; /* p4est does not explicitly enumerate facets, but we must to keep track of labels */ 1660a96aa3bSJed Brown } DMFTopology_pforest; 1670a96aa3bSJed Brown 1680a96aa3bSJed Brown #define DM_Forest_pforest _append_pforest(DM_Forest) 1690a96aa3bSJed Brown typedef struct { 1700a96aa3bSJed Brown DMFTopology_pforest *topo; 1710a96aa3bSJed Brown p4est_t *forest; 1720a96aa3bSJed Brown p4est_ghost_t *ghost; 1730a96aa3bSJed Brown p4est_lnodes_t *lnodes; 1740a96aa3bSJed Brown PetscBool partition_for_coarsening; 1750a96aa3bSJed Brown PetscBool coarsen_hierarchy; 1760a96aa3bSJed Brown PetscBool labelsFinalized; 1770a96aa3bSJed Brown PetscBool adaptivitySuccess; 1780a96aa3bSJed Brown PetscInt cLocalStart; 1790a96aa3bSJed Brown PetscInt cLocalEnd; 1800a96aa3bSJed Brown DM plex; 1810a96aa3bSJed Brown char *ghostName; 1820a96aa3bSJed Brown PetscSF pointAdaptToSelfSF; 1830a96aa3bSJed Brown PetscSF pointSelfToAdaptSF; 1840a96aa3bSJed Brown PetscInt *pointAdaptToSelfCids; 1850a96aa3bSJed Brown PetscInt *pointSelfToAdaptCids; 1860a96aa3bSJed Brown } DM_Forest_pforest; 1870a96aa3bSJed Brown 1880a96aa3bSJed Brown #define DM_Forest_geometry_pforest _append_pforest(DM_Forest_geometry) 1890a96aa3bSJed Brown typedef struct { 1900a96aa3bSJed Brown DM base; 1910a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *); 1920a96aa3bSJed Brown void *mapCtx; 1930a96aa3bSJed Brown PetscInt coordDim; 1940a96aa3bSJed Brown p4est_geometry_t *inner; 1959371c9d4SSatish Balay } DM_Forest_geometry_pforest; 1960a96aa3bSJed Brown 1970a96aa3bSJed Brown #define GeometryMapping_pforest _append_pforest(GeometryMapping) 1989371c9d4SSatish Balay static void GeometryMapping_pforest(p4est_geometry_t *geom, p4est_topidx_t which_tree, const double abc[3], double xyz[3]) { 1990a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest *)geom->user; 2000a96aa3bSJed Brown PetscReal PetscABC[3] = {0.}; 2010a96aa3bSJed Brown PetscReal PetscXYZ[3] = {0.}; 2020a96aa3bSJed Brown PetscInt i, d = PetscMin(3, geom_pforest->coordDim); 2030a96aa3bSJed Brown double ABC[3]; 2040a96aa3bSJed Brown PetscErrorCode ierr; 2050a96aa3bSJed Brown 2060a96aa3bSJed Brown (geom_pforest->inner->X)(geom_pforest->inner, which_tree, abc, ABC); 2070a96aa3bSJed Brown 2080a96aa3bSJed Brown for (i = 0; i < d; i++) PetscABC[i] = ABC[i]; 2099371c9d4SSatish Balay ierr = (geom_pforest->map)(geom_pforest->base, (PetscInt)which_tree, geom_pforest->coordDim, PetscABC, PetscXYZ, geom_pforest->mapCtx); 2109371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr); 2110a96aa3bSJed Brown for (i = 0; i < d; i++) xyz[i] = PetscXYZ[i]; 2120a96aa3bSJed Brown } 2130a96aa3bSJed Brown 2140a96aa3bSJed Brown #define GeometryDestroy_pforest _append_pforest(GeometryDestroy) 2159371c9d4SSatish Balay static void GeometryDestroy_pforest(p4est_geometry_t *geom) { 2160a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest *)geom->user; 2170a96aa3bSJed Brown PetscErrorCode ierr; 2180a96aa3bSJed Brown 2190a96aa3bSJed Brown p4est_geometry_destroy(geom_pforest->inner); 2209371c9d4SSatish Balay ierr = PetscFree(geom->user); 2219371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr); 2229371c9d4SSatish Balay ierr = PetscFree(geom); 2239371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr); 2240a96aa3bSJed Brown } 2250a96aa3bSJed Brown 2260a96aa3bSJed Brown #define DMFTopologyDestroy_pforest _append_pforest(DMFTopologyDestroy) 2279371c9d4SSatish Balay static PetscErrorCode DMFTopologyDestroy_pforest(DMFTopology_pforest **topo) { 2280a96aa3bSJed Brown PetscFunctionBegin; 2290a96aa3bSJed Brown if (!(*topo)) PetscFunctionReturn(0); 2300a96aa3bSJed Brown if (--((*topo)->refct) > 0) { 2310a96aa3bSJed Brown *topo = NULL; 2320a96aa3bSJed Brown PetscFunctionReturn(0); 2330a96aa3bSJed Brown } 234792fecdfSBarry Smith if ((*topo)->geom) PetscCallP4est(p4est_geometry_destroy, ((*topo)->geom)); 235792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy, ((*topo)->conn)); 2369566063dSJacob Faibussowitsch PetscCall(PetscFree((*topo)->tree_face_to_uniq)); 2379566063dSJacob Faibussowitsch PetscCall(PetscFree(*topo)); 2380a96aa3bSJed Brown *topo = NULL; 2390a96aa3bSJed Brown PetscFunctionReturn(0); 2400a96aa3bSJed Brown } 2410a96aa3bSJed Brown 2420a96aa3bSJed Brown static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *, PetscInt **); 2430a96aa3bSJed Brown 2440a96aa3bSJed Brown #define DMFTopologyCreateBrick_pforest _append_pforest(DMFTopologyCreateBrick) 2459371c9d4SSatish Balay static PetscErrorCode DMFTopologyCreateBrick_pforest(DM dm, PetscInt N[], PetscInt P[], PetscReal B[], DMFTopology_pforest **topo, PetscBool useMorton) { 2460a96aa3bSJed Brown double *vertices; 2470a96aa3bSJed Brown PetscInt i, numVerts; 2480a96aa3bSJed Brown 2490a96aa3bSJed Brown PetscFunctionBegin; 25028b400f6SJacob Faibussowitsch PetscCheck(useMorton, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Lexicographic ordering not implemented yet"); 251*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(topo)); 2520a96aa3bSJed Brown 2530a96aa3bSJed Brown (*topo)->refct = 1; 2540a96aa3bSJed Brown #if !defined(P4_TO_P8) 255792fecdfSBarry Smith PetscCallP4estReturn((*topo)->conn, p4est_connectivity_new_brick, ((int)N[0], (int)N[1], (P[0] == DM_BOUNDARY_NONE) ? 0 : 1, (P[1] == DM_BOUNDARY_NONE) ? 0 : 1)); 2560a96aa3bSJed Brown #else 257792fecdfSBarry Smith PetscCallP4estReturn((*topo)->conn, p8est_connectivity_new_brick, ((int)N[0], (int)N[1], (int)N[2], (P[0] == DM_BOUNDARY_NONE) ? 0 : 1, (P[1] == DM_BOUNDARY_NONE) ? 0 : 1, (P[2] == DM_BOUNDARY_NONE) ? 0 : 1)); 2580a96aa3bSJed Brown #endif 2590a96aa3bSJed Brown numVerts = (*topo)->conn->num_vertices; 2600a96aa3bSJed Brown vertices = (*topo)->conn->vertices; 2610a96aa3bSJed Brown for (i = 0; i < 3 * numVerts; i++) { 2620a96aa3bSJed Brown PetscInt j = i % 3; 2630a96aa3bSJed Brown 2640a96aa3bSJed Brown vertices[i] = B[2 * j] + (vertices[i] / N[j]) * (B[2 * j + 1] - B[2 * j]); 2650a96aa3bSJed Brown } 2660a96aa3bSJed Brown (*topo)->geom = NULL; 2679566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn, &(*topo)->tree_face_to_uniq)); 2680a96aa3bSJed Brown PetscFunctionReturn(0); 2690a96aa3bSJed Brown } 2700a96aa3bSJed Brown 2710a96aa3bSJed Brown #define DMFTopologyCreate_pforest _append_pforest(DMFTopologyCreate) 2729371c9d4SSatish Balay static PetscErrorCode DMFTopologyCreate_pforest(DM dm, DMForestTopology topologyName, DMFTopology_pforest **topo) { 2730a96aa3bSJed Brown const char *name = (const char *)topologyName; 2740a96aa3bSJed Brown const char *prefix; 2750a96aa3bSJed Brown PetscBool isBrick, isShell, isSphere, isMoebius; 2760a96aa3bSJed Brown 2770a96aa3bSJed Brown PetscFunctionBegin; 2780a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2790a96aa3bSJed Brown PetscValidCharPointer(name, 2); 2800a96aa3bSJed Brown PetscValidPointer(topo, 3); 2819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "brick", &isBrick)); 2829566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "shell", &isShell)); 2839566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "sphere", &isSphere)); 2849566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "moebius", &isMoebius)); 2859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 2860a96aa3bSJed Brown if (isBrick) { 2870a96aa3bSJed Brown PetscBool flgN, flgP, flgM, flgB, useMorton = PETSC_TRUE, periodic = PETSC_FALSE; 2880a96aa3bSJed Brown PetscInt N[3] = {2, 2, 2}, P[3] = {0, 0, 0}, nretN = P4EST_DIM, nretP = P4EST_DIM, nretB = 2 * P4EST_DIM, i; 2894fb89dddSMatthew G. Knepley PetscReal B[6] = {0.0, 1.0, 0.0, 1.0, 0.0, 1.0}, Lstart[3] = {0., 0., 0.}, L[3] = {-1.0, -1.0, -1.0}, maxCell[3] = {-1.0, -1.0, -1.0}; 2900a96aa3bSJed Brown 2910a96aa3bSJed Brown if (dm->setfromoptionscalled) { 2929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_size", N, &nretN, &flgN)); 2939566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_periodicity", P, &nretP, &flgP)); 2949566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_bounds", B, &nretB, &flgB)); 2959566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_use_morton_curve", &useMorton, &flgM)); 2961dca8a05SBarry Smith PetscCheck(!flgN || nretN == P4EST_DIM, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Need to give %d sizes in -dm_p4est_brick_size, gave %" PetscInt_FMT, P4EST_DIM, nretN); 2971dca8a05SBarry Smith PetscCheck(!flgP || nretP == P4EST_DIM, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Need to give %d periodicities in -dm_p4est_brick_periodicity, gave %" PetscInt_FMT, P4EST_DIM, nretP); 2981dca8a05SBarry Smith PetscCheck(!flgB || nretB == 2 * P4EST_DIM, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Need to give %d bounds in -dm_p4est_brick_bounds, gave %" PetscInt_FMT, P4EST_DIM, nretP); 2990a96aa3bSJed Brown } 3000a96aa3bSJed Brown for (i = 0; i < P4EST_DIM; i++) { 3010a96aa3bSJed Brown P[i] = (P[i] ? DM_BOUNDARY_PERIODIC : DM_BOUNDARY_NONE); 3020a96aa3bSJed Brown periodic = (PetscBool)(P[i] || periodic); 3030a96aa3bSJed Brown if (!flgB) B[2 * i + 1] = N[i]; 3046858538eSMatthew G. Knepley if (P[i]) { 3054fb89dddSMatthew G. Knepley Lstart[i] = B[2 * i + 0]; 3064fb89dddSMatthew G. Knepley L[i] = B[2 * i + 1] - B[2 * i + 0]; 3076858538eSMatthew G. Knepley maxCell[i] = 1.1 * (L[i] / N[i]); 3086858538eSMatthew G. Knepley } 3090a96aa3bSJed Brown } 3109566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm, N, P, B, topo, useMorton)); 3114fb89dddSMatthew G. Knepley if (periodic) PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 3120a96aa3bSJed Brown } else { 313*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(topo)); 3140a96aa3bSJed Brown 3150a96aa3bSJed Brown (*topo)->refct = 1; 316792fecdfSBarry Smith PetscCallP4estReturn((*topo)->conn, p4est_connectivity_new_byname, (name)); 3170a96aa3bSJed Brown (*topo)->geom = NULL; 3181baa6e33SBarry Smith if (isMoebius) PetscCall(DMSetCoordinateDim(dm, 3)); 3190a96aa3bSJed Brown #if defined(P4_TO_P8) 3200a96aa3bSJed Brown if (isShell) { 3210a96aa3bSJed Brown PetscReal R2 = 1., R1 = .55; 3220a96aa3bSJed Brown 3230a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3249566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_shell_outer_radius", &R2, NULL)); 3259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_shell_inner_radius", &R1, NULL)); 3260a96aa3bSJed Brown } 327792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom, p8est_geometry_new_shell, ((*topo)->conn, R2, R1)); 3280a96aa3bSJed Brown } else if (isSphere) { 3290a96aa3bSJed Brown PetscReal R2 = 1., R1 = 0.191728, R0 = 0.039856; 3300a96aa3bSJed Brown 3310a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3329566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_outer_radius", &R2, NULL)); 3339566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_inner_radius", &R1, NULL)); 3349566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_core_radius", &R0, NULL)); 3350a96aa3bSJed Brown } 336792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom, p8est_geometry_new_sphere, ((*topo)->conn, R2, R1, R0)); 3370a96aa3bSJed Brown } 3380a96aa3bSJed Brown #endif 3399566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn, &(*topo)->tree_face_to_uniq)); 3400a96aa3bSJed Brown } 3410a96aa3bSJed Brown PetscFunctionReturn(0); 3420a96aa3bSJed Brown } 3430a96aa3bSJed Brown 3440a96aa3bSJed Brown #define DMConvert_plex_pforest _append_pforest(DMConvert_plex) 3459371c9d4SSatish Balay static PetscErrorCode DMConvert_plex_pforest(DM dm, DMType newtype, DM *pforest) { 3460a96aa3bSJed Brown MPI_Comm comm; 3470a96aa3bSJed Brown PetscBool isPlex; 3480a96aa3bSJed Brown PetscInt dim; 3490a96aa3bSJed Brown void *ctx; 3500a96aa3bSJed Brown 3510a96aa3bSJed Brown PetscFunctionBegin; 3520a96aa3bSJed Brown 3530a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3540a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 3559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isPlex)); 35628b400f6SJacob Faibussowitsch PetscCheck(isPlex, comm, PETSC_ERR_ARG_WRONG, "Expected DM type %s, got %s", DMPLEX, ((PetscObject)dm)->type_name); 3579566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 35863a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM, comm, PETSC_ERR_ARG_WRONG, "Expected DM dimension %d, got %" PetscInt_FMT, P4EST_DIM, dim); 3599566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, pforest)); 3609566063dSJacob Faibussowitsch PetscCall(DMSetType(*pforest, DMPFOREST)); 3619566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(*pforest, dm)); 3629566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dm, &ctx)); 3639566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(*pforest, ctx)); 3649566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *pforest)); 3650a96aa3bSJed Brown PetscFunctionReturn(0); 3660a96aa3bSJed Brown } 3670a96aa3bSJed Brown 3680a96aa3bSJed Brown #define DMForestDestroy_pforest _append_pforest(DMForestDestroy) 3699371c9d4SSatish Balay static PetscErrorCode DMForestDestroy_pforest(DM dm) { 3700a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 3710a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 3720a96aa3bSJed Brown 3730a96aa3bSJed Brown PetscFunctionBegin; 3740a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 375792fecdfSBarry Smith if (pforest->lnodes) PetscCallP4est(p4est_lnodes_destroy, (pforest->lnodes)); 3760a96aa3bSJed Brown pforest->lnodes = NULL; 377792fecdfSBarry Smith if (pforest->ghost) PetscCallP4est(p4est_ghost_destroy, (pforest->ghost)); 3780a96aa3bSJed Brown pforest->ghost = NULL; 379792fecdfSBarry Smith if (pforest->forest) PetscCallP4est(p4est_destroy, (pforest->forest)); 3800a96aa3bSJed Brown pforest->forest = NULL; 3819566063dSJacob Faibussowitsch PetscCall(DMFTopologyDestroy_pforest(&pforest->topo)); 3829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_plex_pforest) "_C", NULL)); 3839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_pforest_plex) "_C", NULL)); 3842e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 3859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 3862e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 3872e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 3889566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName)); 3899566063dSJacob Faibussowitsch PetscCall(DMDestroy(&pforest->plex)); 3909566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointAdaptToSelfSF)); 3919566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointSelfToAdaptSF)); 3929566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 3939566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 3949566063dSJacob Faibussowitsch PetscCall(PetscFree(forest->data)); 3950a96aa3bSJed Brown PetscFunctionReturn(0); 3960a96aa3bSJed Brown } 3970a96aa3bSJed Brown 3980a96aa3bSJed Brown #define DMForestTemplate_pforest _append_pforest(DMForestTemplate) 3999371c9d4SSatish Balay static PetscErrorCode DMForestTemplate_pforest(DM dm, DM tdm) { 4000a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 4010a96aa3bSJed Brown DM_Forest_pforest *tpforest = (DM_Forest_pforest *)((DM_Forest *)tdm->data)->data; 4020a96aa3bSJed Brown 4030a96aa3bSJed Brown PetscFunctionBegin; 4040a96aa3bSJed Brown if (pforest->topo) pforest->topo->refct++; 4059566063dSJacob Faibussowitsch PetscCall(DMFTopologyDestroy_pforest(&(tpforest->topo))); 4060a96aa3bSJed Brown tpforest->topo = pforest->topo; 4070a96aa3bSJed Brown PetscFunctionReturn(0); 4080a96aa3bSJed Brown } 4090a96aa3bSJed Brown 4100a96aa3bSJed Brown #define DMPlexCreateConnectivity_pforest _append_pforest(DMPlexCreateConnectivity) 4110a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM, p4est_connectivity_t **, PetscInt **); 4120a96aa3bSJed Brown 4139371c9d4SSatish Balay typedef struct _PforestAdaptCtx { 4140a96aa3bSJed Brown PetscInt maxLevel; 4150a96aa3bSJed Brown PetscInt minLevel; 4160a96aa3bSJed Brown PetscInt currLevel; 4170a96aa3bSJed Brown PetscBool anyChange; 4189371c9d4SSatish Balay } PforestAdaptCtx; 4190a96aa3bSJed Brown 4209371c9d4SSatish Balay static int pforest_coarsen_currlevel(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) { 4210a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4220a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4230a96aa3bSJed Brown PetscInt currLevel = ctx->currLevel; 4240a96aa3bSJed Brown 4250a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4260a96aa3bSJed Brown return (int)((PetscInt)quadrants[0]->level == currLevel); 4270a96aa3bSJed Brown } 4280a96aa3bSJed Brown 4299371c9d4SSatish Balay static int pforest_coarsen_uniform(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) { 4300a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4310a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4320a96aa3bSJed Brown 4330a96aa3bSJed Brown return (int)((PetscInt)quadrants[0]->level > minLevel); 4340a96aa3bSJed Brown } 4350a96aa3bSJed Brown 4369371c9d4SSatish Balay static int pforest_coarsen_flag_any(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) { 4370a96aa3bSJed Brown PetscInt i; 4380a96aa3bSJed Brown PetscBool any = PETSC_FALSE; 4390a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4400a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4410a96aa3bSJed Brown 4420a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4430a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 4440a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_KEEP) { 4450a96aa3bSJed Brown any = PETSC_FALSE; 4460a96aa3bSJed Brown break; 4470a96aa3bSJed Brown } 4480a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_COARSEN) { 4490a96aa3bSJed Brown any = PETSC_TRUE; 4500a96aa3bSJed Brown break; 4510a96aa3bSJed Brown } 4520a96aa3bSJed Brown } 4530a96aa3bSJed Brown return any ? 1 : 0; 4540a96aa3bSJed Brown } 4550a96aa3bSJed Brown 4569371c9d4SSatish Balay static int pforest_coarsen_flag_all(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) { 4570a96aa3bSJed Brown PetscInt i; 4580a96aa3bSJed Brown PetscBool all = PETSC_TRUE; 4590a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4600a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4610a96aa3bSJed Brown 4620a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4630a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 4640a96aa3bSJed Brown if (quadrants[i]->p.user_int != DM_ADAPT_COARSEN) { 4650a96aa3bSJed Brown all = PETSC_FALSE; 4660a96aa3bSJed Brown break; 4670a96aa3bSJed Brown } 4680a96aa3bSJed Brown } 4690a96aa3bSJed Brown return all ? 1 : 0; 4700a96aa3bSJed Brown } 4710a96aa3bSJed Brown 4729371c9d4SSatish Balay static void pforest_init_determine(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) { 4730a96aa3bSJed Brown quadrant->p.user_int = DM_ADAPT_DETERMINE; 4740a96aa3bSJed Brown } 4750a96aa3bSJed Brown 4769371c9d4SSatish Balay static int pforest_refine_uniform(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) { 4770a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4780a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 4790a96aa3bSJed Brown 4800a96aa3bSJed Brown return ((PetscInt)quadrant->level < maxLevel); 4810a96aa3bSJed Brown } 4820a96aa3bSJed Brown 4839371c9d4SSatish Balay static int pforest_refine_flag(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) { 4840a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4850a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 4860a96aa3bSJed Brown 4870a96aa3bSJed Brown if ((PetscInt)quadrant->level >= maxLevel) return 0; 4880a96aa3bSJed Brown 4890a96aa3bSJed Brown return (quadrant->p.user_int == DM_ADAPT_REFINE); 4900a96aa3bSJed Brown } 4910a96aa3bSJed Brown 4929371c9d4SSatish Balay static PetscErrorCode DMPforestComputeLocalCellTransferSF_loop(p4est_t *p4estFrom, PetscInt FromOffset, p4est_t *p4estTo, PetscInt ToOffset, p4est_topidx_t flt, p4est_topidx_t llt, PetscInt *toFineLeavesCount, PetscInt *toLeaves, PetscSFNode *fromRoots, PetscInt *fromFineLeavesCount, PetscInt *fromLeaves, PetscSFNode *toRoots) { 4930a96aa3bSJed Brown PetscMPIInt rank = p4estFrom->mpirank; 4940a96aa3bSJed Brown p4est_topidx_t t; 4950a96aa3bSJed Brown PetscInt toFineLeaves = 0, fromFineLeaves = 0; 4960a96aa3bSJed Brown 4970a96aa3bSJed Brown PetscFunctionBegin; 4980a96aa3bSJed Brown for (t = flt; t <= llt; t++) { /* count roots and leaves */ 4990a96aa3bSJed Brown p4est_tree_t *treeFrom = &(((p4est_tree_t *)p4estFrom->trees->array)[t]); 5000a96aa3bSJed Brown p4est_tree_t *treeTo = &(((p4est_tree_t *)p4estTo->trees->array)[t]); 5010a96aa3bSJed Brown p4est_quadrant_t *firstFrom = &treeFrom->first_desc; 5020a96aa3bSJed Brown p4est_quadrant_t *firstTo = &treeTo->first_desc; 5030a96aa3bSJed Brown PetscInt numFrom = (PetscInt)treeFrom->quadrants.elem_count; 5040a96aa3bSJed Brown PetscInt numTo = (PetscInt)treeTo->quadrants.elem_count; 5050a96aa3bSJed Brown p4est_quadrant_t *quadsFrom = (p4est_quadrant_t *)treeFrom->quadrants.array; 5060a96aa3bSJed Brown p4est_quadrant_t *quadsTo = (p4est_quadrant_t *)treeTo->quadrants.array; 5070a96aa3bSJed Brown PetscInt currentFrom, currentTo; 5080a96aa3bSJed Brown PetscInt treeOffsetFrom = (PetscInt)treeFrom->quadrants_offset; 5090a96aa3bSJed Brown PetscInt treeOffsetTo = (PetscInt)treeTo->quadrants_offset; 5100a96aa3bSJed Brown int comp; 5110a96aa3bSJed Brown 512792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (firstFrom, firstTo)); 51328b400f6SJacob Faibussowitsch PetscCheck(comp, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "non-matching partitions"); 5140a96aa3bSJed Brown 5150a96aa3bSJed Brown for (currentFrom = 0, currentTo = 0; currentFrom < numFrom && currentTo < numTo;) { 5160a96aa3bSJed Brown p4est_quadrant_t *quadFrom = &quadsFrom[currentFrom]; 5170a96aa3bSJed Brown p4est_quadrant_t *quadTo = &quadsTo[currentTo]; 5180a96aa3bSJed Brown 5190a96aa3bSJed Brown if (quadFrom->level == quadTo->level) { 5200a96aa3bSJed Brown if (toLeaves) { 5210a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5220a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5230a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5240a96aa3bSJed Brown } 5250a96aa3bSJed Brown toFineLeaves++; 5260a96aa3bSJed Brown currentFrom++; 5270a96aa3bSJed Brown currentTo++; 5280a96aa3bSJed Brown } else { 5290a96aa3bSJed Brown int fromIsAncestor; 5300a96aa3bSJed Brown 531792fecdfSBarry Smith PetscCallP4estReturn(fromIsAncestor, p4est_quadrant_is_ancestor, (quadFrom, quadTo)); 5320a96aa3bSJed Brown if (fromIsAncestor) { 5330a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5340a96aa3bSJed Brown 5350a96aa3bSJed Brown if (toLeaves) { 5360a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5370a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5380a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5390a96aa3bSJed Brown } 5400a96aa3bSJed Brown toFineLeaves++; 5410a96aa3bSJed Brown currentTo++; 542792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant, (quadFrom, &lastDesc, quadTo->level)); 543792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (quadTo, &lastDesc)); 5440a96aa3bSJed Brown if (comp) currentFrom++; 5450a96aa3bSJed Brown } else { 5460a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5470a96aa3bSJed Brown 5480a96aa3bSJed Brown if (fromLeaves) { 5490a96aa3bSJed Brown fromLeaves[fromFineLeaves] = currentFrom + treeOffsetFrom + FromOffset; 5500a96aa3bSJed Brown toRoots[fromFineLeaves].rank = rank; 5510a96aa3bSJed Brown toRoots[fromFineLeaves].index = currentTo + treeOffsetTo + ToOffset; 5520a96aa3bSJed Brown } 5530a96aa3bSJed Brown fromFineLeaves++; 5540a96aa3bSJed Brown currentFrom++; 555792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant, (quadTo, &lastDesc, quadFrom->level)); 556792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (quadFrom, &lastDesc)); 5570a96aa3bSJed Brown if (comp) currentTo++; 5580a96aa3bSJed Brown } 5590a96aa3bSJed Brown } 5600a96aa3bSJed Brown } 5610a96aa3bSJed Brown } 5620a96aa3bSJed Brown *toFineLeavesCount = toFineLeaves; 5630a96aa3bSJed Brown *fromFineLeavesCount = fromFineLeaves; 5640a96aa3bSJed Brown PetscFunctionReturn(0); 5650a96aa3bSJed Brown } 5660a96aa3bSJed Brown 5670a96aa3bSJed Brown /* Compute the maximum level across all the trees */ 5689371c9d4SSatish Balay static PetscErrorCode DMPforestGetRefinementLevel(DM dm, PetscInt *lev) { 5690a96aa3bSJed Brown p4est_topidx_t t, flt, llt; 5700a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 5710a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 5720a96aa3bSJed Brown PetscInt maxlevelloc = 0; 5730a96aa3bSJed Brown p4est_t *p4est; 5740a96aa3bSJed Brown 5750a96aa3bSJed Brown PetscFunctionBegin; 57628b400f6SJacob Faibussowitsch PetscCheck(pforest, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing DM_Forest_pforest"); 57728b400f6SJacob Faibussowitsch PetscCheck(pforest->forest, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing p4est_t"); 5780a96aa3bSJed Brown p4est = pforest->forest; 5790a96aa3bSJed Brown flt = p4est->first_local_tree; 5800a96aa3bSJed Brown llt = p4est->last_local_tree; 5810a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 5820a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4est->trees->array)[t]); 5830a96aa3bSJed Brown maxlevelloc = PetscMax((PetscInt)tree->maxlevel, maxlevelloc); 5840a96aa3bSJed Brown } 5851c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&maxlevelloc, lev, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 5860a96aa3bSJed Brown PetscFunctionReturn(0); 5870a96aa3bSJed Brown } 5880a96aa3bSJed Brown 5890a96aa3bSJed Brown /* Puts identity in coarseToFine */ 5900a96aa3bSJed Brown /* assumes a matching partition */ 5919371c9d4SSatish Balay static PetscErrorCode DMPforestComputeLocalCellTransferSF(MPI_Comm comm, p4est_t *p4estFrom, PetscInt FromOffset, p4est_t *p4estTo, PetscInt ToOffset, PetscSF *fromCoarseToFine, PetscSF *toCoarseFromFine) { 5920a96aa3bSJed Brown p4est_topidx_t flt, llt; 5930a96aa3bSJed Brown PetscSF fromCoarse, toCoarse; 5940a96aa3bSJed Brown PetscInt numRootsFrom, numRootsTo, numLeavesFrom, numLeavesTo; 5950a96aa3bSJed Brown PetscInt *fromLeaves = NULL, *toLeaves = NULL; 5960a96aa3bSJed Brown PetscSFNode *fromRoots = NULL, *toRoots = NULL; 5970a96aa3bSJed Brown 5980a96aa3bSJed Brown PetscFunctionBegin; 5990a96aa3bSJed Brown flt = p4estFrom->first_local_tree; 6000a96aa3bSJed Brown llt = p4estFrom->last_local_tree; 6019566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &fromCoarse)); 60248a46eb9SPierre Jolivet if (toCoarseFromFine) PetscCall(PetscSFCreate(comm, &toCoarse)); 6030a96aa3bSJed Brown numRootsFrom = p4estFrom->local_num_quadrants + FromOffset; 6040a96aa3bSJed Brown numRootsTo = p4estTo->local_num_quadrants + ToOffset; 6059566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom, FromOffset, p4estTo, ToOffset, flt, llt, &numLeavesTo, NULL, NULL, &numLeavesFrom, NULL, NULL)); 6069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo, &toLeaves)); 6079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo, &fromRoots)); 6080a96aa3bSJed Brown if (toCoarseFromFine) { 6099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom, &fromLeaves)); 6109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom, &fromRoots)); 6110a96aa3bSJed Brown } 6129566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom, FromOffset, p4estTo, ToOffset, flt, llt, &numLeavesTo, toLeaves, fromRoots, &numLeavesFrom, fromLeaves, toRoots)); 6130a96aa3bSJed Brown if (!ToOffset && (numLeavesTo == numRootsTo)) { /* compress */ 6149566063dSJacob Faibussowitsch PetscCall(PetscFree(toLeaves)); 6159566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(fromCoarse, numRootsFrom, numLeavesTo, NULL, PETSC_OWN_POINTER, fromRoots, PETSC_OWN_POINTER)); 6161baa6e33SBarry Smith } else PetscCall(PetscSFSetGraph(fromCoarse, numRootsFrom, numLeavesTo, toLeaves, PETSC_OWN_POINTER, fromRoots, PETSC_OWN_POINTER)); 6170a96aa3bSJed Brown *fromCoarseToFine = fromCoarse; 6180a96aa3bSJed Brown if (toCoarseFromFine) { 6199566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(toCoarse, numRootsTo, numLeavesFrom, fromLeaves, PETSC_OWN_POINTER, toRoots, PETSC_OWN_POINTER)); 6200a96aa3bSJed Brown *toCoarseFromFine = toCoarse; 6210a96aa3bSJed Brown } 6220a96aa3bSJed Brown PetscFunctionReturn(0); 6230a96aa3bSJed Brown } 6240a96aa3bSJed Brown 6250a96aa3bSJed Brown /* range of processes whose B sections overlap this ranks A section */ 6269371c9d4SSatish Balay static PetscErrorCode DMPforestComputeOverlappingRanks(PetscMPIInt size, PetscMPIInt rank, p4est_t *p4estA, p4est_t *p4estB, PetscInt *startB, PetscInt *endB) { 6270a96aa3bSJed Brown p4est_quadrant_t *myCoarseStart = &(p4estA->global_first_position[rank]); 6280a96aa3bSJed Brown p4est_quadrant_t *myCoarseEnd = &(p4estA->global_first_position[rank + 1]); 6290a96aa3bSJed Brown p4est_quadrant_t *globalFirstB = p4estB->global_first_position; 6300a96aa3bSJed Brown 6310a96aa3bSJed Brown PetscFunctionBegin; 6320a96aa3bSJed Brown *startB = -1; 6330a96aa3bSJed Brown *endB = -1; 6340a96aa3bSJed Brown if (p4estA->local_num_quadrants) { 6350a96aa3bSJed Brown PetscInt lo, hi, guess; 6360a96aa3bSJed Brown /* binary search to find interval containing myCoarseStart */ 6370a96aa3bSJed Brown lo = 0; 6380a96aa3bSJed Brown hi = size; 6390a96aa3bSJed Brown guess = rank; 6400a96aa3bSJed Brown while (1) { 6410a96aa3bSJed Brown int startCompMy, myCompEnd; 6420a96aa3bSJed Brown 643792fecdfSBarry Smith PetscCallP4estReturn(startCompMy, p4est_quadrant_compare_piggy, (&globalFirstB[guess], myCoarseStart)); 644792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd, p4est_quadrant_compare_piggy, (myCoarseStart, &globalFirstB[guess + 1])); 6450a96aa3bSJed Brown if (startCompMy <= 0 && myCompEnd < 0) { 6460a96aa3bSJed Brown *startB = guess; 6470a96aa3bSJed Brown break; 6480a96aa3bSJed Brown } else if (startCompMy > 0) { /* guess is to high */ 6490a96aa3bSJed Brown hi = guess; 6500a96aa3bSJed Brown } else { /* guess is to low */ 6510a96aa3bSJed Brown lo = guess + 1; 6520a96aa3bSJed Brown } 6530a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6540a96aa3bSJed Brown } 6550a96aa3bSJed Brown /* reset bounds, but not guess */ 6560a96aa3bSJed Brown lo = 0; 6570a96aa3bSJed Brown hi = size; 6580a96aa3bSJed Brown while (1) { 6590a96aa3bSJed Brown int startCompMy, myCompEnd; 6600a96aa3bSJed Brown 661792fecdfSBarry Smith PetscCallP4estReturn(startCompMy, p4est_quadrant_compare_piggy, (&globalFirstB[guess], myCoarseEnd)); 662792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd, p4est_quadrant_compare_piggy, (myCoarseEnd, &globalFirstB[guess + 1])); 6630a96aa3bSJed Brown if (startCompMy < 0 && myCompEnd <= 0) { /* notice that the comparison operators are different from above */ 6640a96aa3bSJed Brown *endB = guess + 1; 6650a96aa3bSJed Brown break; 6660a96aa3bSJed Brown } else if (startCompMy >= 0) { /* guess is to high */ 6670a96aa3bSJed Brown hi = guess; 6680a96aa3bSJed Brown } else { /* guess is to low */ 6690a96aa3bSJed Brown lo = guess + 1; 6700a96aa3bSJed Brown } 6710a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6720a96aa3bSJed Brown } 6730a96aa3bSJed Brown } 6740a96aa3bSJed Brown PetscFunctionReturn(0); 6750a96aa3bSJed Brown } 6760a96aa3bSJed Brown 6770a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM, DM *); 6780a96aa3bSJed Brown 6790a96aa3bSJed Brown #define DMSetUp_pforest _append_pforest(DMSetUp) 6809371c9d4SSatish Balay static PetscErrorCode DMSetUp_pforest(DM dm) { 6810a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 6820a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 6830a96aa3bSJed Brown DM base, adaptFrom; 6840a96aa3bSJed Brown DMForestTopology topoName; 6850a96aa3bSJed Brown PetscSF preCoarseToFine = NULL, coarseToPreFine = NULL; 6860a96aa3bSJed Brown PforestAdaptCtx ctx; 6870a96aa3bSJed Brown 6880a96aa3bSJed Brown PetscFunctionBegin; 6890a96aa3bSJed Brown ctx.minLevel = PETSC_MAX_INT; 6900a96aa3bSJed Brown ctx.maxLevel = 0; 6910a96aa3bSJed Brown ctx.currLevel = 0; 6920a96aa3bSJed Brown ctx.anyChange = PETSC_FALSE; 6930a96aa3bSJed Brown /* sanity check */ 6949566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm, &adaptFrom)); 6959566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 6969566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm, &topoName)); 6971dca8a05SBarry Smith PetscCheck(adaptFrom || base || topoName, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "A forest needs a topology, a base DM, or a DM to adapt from"); 6980a96aa3bSJed Brown 6990a96aa3bSJed Brown /* === Step 1: DMFTopology === */ 7000a96aa3bSJed Brown if (adaptFrom) { /* reference already created topology */ 7010a96aa3bSJed Brown PetscBool ispforest; 7020a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest *)adaptFrom->data; 7030a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest *)aforest->data; 7040a96aa3bSJed Brown 7059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)adaptFrom, DMPFOREST, &ispforest)); 70628b400f6SJacob Faibussowitsch PetscCheck(ispforest, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NOTSAMETYPE, "Trying to adapt from %s, which is not %s", ((PetscObject)adaptFrom)->type_name, DMPFOREST); 70728b400f6SJacob Faibussowitsch PetscCheck(apforest->topo, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "The pre-adaptation forest must have a topology"); 7089566063dSJacob Faibussowitsch PetscCall(DMSetUp(adaptFrom)); 7099566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 7109566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm, &topoName)); 7110a96aa3bSJed Brown } else if (base) { /* construct a connectivity from base */ 7120a96aa3bSJed Brown PetscBool isPlex, isDA; 7130a96aa3bSJed Brown 7149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)base, &topoName)); 7159566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm, topoName)); 7169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base, DMPLEX, &isPlex)); 7179566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base, DMDA, &isDA)); 7180a96aa3bSJed Brown if (isPlex) { 7190a96aa3bSJed Brown MPI_Comm comm = PetscObjectComm((PetscObject)dm); 7200a96aa3bSJed Brown PetscInt depth; 7210a96aa3bSJed Brown PetscMPIInt size; 7220a96aa3bSJed Brown p4est_connectivity_t *conn = NULL; 7230a96aa3bSJed Brown DMFTopology_pforest *topo; 7240a96aa3bSJed Brown PetscInt *tree_face_to_uniq = NULL; 7250a96aa3bSJed Brown 7269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(base, &depth)); 7270a96aa3bSJed Brown if (depth == 1) { 7280a96aa3bSJed Brown DM connDM; 7290a96aa3bSJed Brown 7309566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(base, &connDM)); 7310a96aa3bSJed Brown base = connDM; 7329566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm, base)); 7339566063dSJacob Faibussowitsch PetscCall(DMDestroy(&connDM)); 73463a3b9bcSJacob Faibussowitsch } else PetscCheck(depth == P4EST_DIM, comm, PETSC_ERR_ARG_WRONG, "Base plex is neither interpolated nor uninterpolated? depth %" PetscInt_FMT ", expected 2 or %d", depth, P4EST_DIM + 1); 7359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 7360a96aa3bSJed Brown if (size > 1) { 7370a96aa3bSJed Brown DM dmRedundant; 7380a96aa3bSJed Brown PetscSF sf; 7390a96aa3bSJed Brown 7409566063dSJacob Faibussowitsch PetscCall(DMPlexGetRedundantDM(base, &sf, &dmRedundant)); 74128b400f6SJacob Faibussowitsch PetscCheck(dmRedundant, comm, PETSC_ERR_PLIB, "Could not create redundant DM"); 7429566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dmRedundant, "_base_migration_sf", (PetscObject)sf)); 7439566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 7440a96aa3bSJed Brown base = dmRedundant; 7459566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm, base)); 7469566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRedundant)); 7470a96aa3bSJed Brown } 7489566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(base, NULL, "-dm_p4est_base_view")); 7499566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConnectivity_pforest(base, &conn, &tree_face_to_uniq)); 750*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&topo)); 7510a96aa3bSJed Brown topo->refct = 1; 7520a96aa3bSJed Brown topo->conn = conn; 7530a96aa3bSJed Brown topo->geom = NULL; 7540a96aa3bSJed Brown { 7550a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *); 7560a96aa3bSJed Brown void *mapCtx; 7570a96aa3bSJed Brown 7589566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx)); 7590a96aa3bSJed Brown if (map) { 7600a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest; 7610a96aa3bSJed Brown p4est_geometry_t *geom; 7620a96aa3bSJed Brown 7639566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom_pforest)); 7649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &geom_pforest->coordDim)); 7650a96aa3bSJed Brown geom_pforest->map = map; 7660a96aa3bSJed Brown geom_pforest->mapCtx = mapCtx; 767792fecdfSBarry Smith PetscCallP4estReturn(geom_pforest->inner, p4est_geometry_new_connectivity, (conn)); 7689566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom)); 7690a96aa3bSJed Brown geom->name = topoName; 7700a96aa3bSJed Brown geom->user = geom_pforest; 7710a96aa3bSJed Brown geom->X = GeometryMapping_pforest; 7720a96aa3bSJed Brown geom->destroy = GeometryDestroy_pforest; 7730a96aa3bSJed Brown topo->geom = geom; 7740a96aa3bSJed Brown } 7750a96aa3bSJed Brown } 7760a96aa3bSJed Brown topo->tree_face_to_uniq = tree_face_to_uniq; 7770a96aa3bSJed Brown pforest->topo = topo; 77828b400f6SJacob Faibussowitsch } else PetscCheck(!isDA, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Not implemented yet"); 7790a96aa3bSJed Brown #if 0 7800a96aa3bSJed Brown PetscInt N[3], P[3]; 7810a96aa3bSJed Brown 7820a96aa3bSJed Brown /* get the sizes, periodicities */ 7830a96aa3bSJed Brown /* ... */ 7840a96aa3bSJed Brown /* don't use Morton order */ 7859566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm,N,P,&pforest->topo,PETSC_FALSE)); 7860a96aa3bSJed Brown #endif 7870a96aa3bSJed Brown { 7880a96aa3bSJed Brown PetscInt numLabels, l; 7890a96aa3bSJed Brown 7909566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(base, &numLabels)); 7910a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 7920a96aa3bSJed Brown PetscBool isDepth, isGhost, isVTK, isDim, isCellType; 7930a96aa3bSJed Brown DMLabel label, labelNew; 7940a96aa3bSJed Brown PetscInt defVal; 7950a96aa3bSJed Brown const char *name; 7960a96aa3bSJed Brown 7979566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(base, l, &name)); 7989566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(base, l, &label)); 7999566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 8000a96aa3bSJed Brown if (isDepth) continue; 8019566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "dim", &isDim)); 8020a96aa3bSJed Brown if (isDim) continue; 8039566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 8040a96aa3bSJed Brown if (isCellType) continue; 8059566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 8060a96aa3bSJed Brown if (isGhost) continue; 8079566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 8080a96aa3bSJed Brown if (isVTK) continue; 8099566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 8109566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &labelNew)); 8119566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defVal)); 8129566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew, defVal)); 8130a96aa3bSJed Brown } 8140a96aa3bSJed Brown /* map dm points (internal plex) to base 8150a96aa3bSJed Brown we currently create the subpoint_map for the entire hierarchy, starting from the finest forest 8160a96aa3bSJed Brown and propagating back to the coarsest 8170a96aa3bSJed Brown This is not an optimal approach, since we need the map only on the coarsest level 8180a96aa3bSJed Brown during DMForestTransferVecFromBase */ 8199566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &l)); 82048a46eb9SPierre Jolivet if (!l) PetscCall(DMCreateLabel(dm, "_forest_base_subpoint_map")); 8210a96aa3bSJed Brown } 8220a96aa3bSJed Brown } else { /* construct from topology name */ 8230a96aa3bSJed Brown DMFTopology_pforest *topo; 8240a96aa3bSJed Brown 8259566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreate_pforest(dm, topoName, &topo)); 8260a96aa3bSJed Brown pforest->topo = topo; 8270a96aa3bSJed Brown /* TODO: construct base? */ 8280a96aa3bSJed Brown } 8290a96aa3bSJed Brown 8300a96aa3bSJed Brown /* === Step 2: get the leaves of the forest === */ 8310a96aa3bSJed Brown if (adaptFrom) { /* start with the old forest */ 8320a96aa3bSJed Brown DMLabel adaptLabel; 8330a96aa3bSJed Brown PetscInt defaultValue; 8340a96aa3bSJed Brown PetscInt numValues, numValuesGlobal, cLocalStart, count; 8350a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest *)adaptFrom->data; 8360a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest *)aforest->data; 8370a96aa3bSJed Brown PetscBool computeAdaptSF; 8380a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 8390a96aa3bSJed Brown 8400a96aa3bSJed Brown flt = apforest->forest->first_local_tree; 8410a96aa3bSJed Brown llt = apforest->forest->last_local_tree; 8420a96aa3bSJed Brown cLocalStart = apforest->cLocalStart; 8439566063dSJacob Faibussowitsch PetscCall(DMForestGetComputeAdaptivitySF(dm, &computeAdaptSF)); 844792fecdfSBarry Smith PetscCallP4estReturn(pforest->forest, p4est_copy, (apforest->forest, 0)); /* 0 indicates no data copying */ 8459566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm, &adaptLabel)); 8460a96aa3bSJed Brown if (adaptLabel) { 8470a96aa3bSJed Brown /* apply the refinement/coarsening by flags, plus minimum/maximum refinement */ 8489566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(adaptLabel, &numValues)); 8499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&numValues, &numValuesGlobal, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)adaptFrom))); 8509566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(adaptLabel, &defaultValue)); 8510a96aa3bSJed Brown if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN_LAST) { /* uniform coarsen of the last level only (equivalent to DM_ADAPT_COARSEN for conforming grids) */ 8529566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel)); 8539566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm, &ctx.currLevel)); 8540a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 855792fecdfSBarry Smith PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_currlevel, NULL)); 8560a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 857792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 8580a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 85948a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), pforest->forest, 0, apforest->forest, apforest->cLocalStart, &coarseToPreFine, NULL)); 8600a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN) { /* uniform coarsen */ 8619566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel)); 8620a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 863792fecdfSBarry Smith PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_uniform, NULL)); 8640a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 865792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 8660a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 86748a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), pforest->forest, 0, apforest->forest, apforest->cLocalStart, &coarseToPreFine, NULL)); 8680a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_REFINE) { /* uniform refine */ 8699566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &ctx.maxLevel)); 8700a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 871792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 0, pforest_refine_uniform, NULL)); 8720a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 873792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 8740a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 87548a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), apforest->forest, apforest->cLocalStart, pforest->forest, 0, &preCoarseToFine, NULL)); 8760a96aa3bSJed Brown } else if (numValuesGlobal) { 8770a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 8780a96aa3bSJed Brown PetscInt *cellFlags; 8790a96aa3bSJed Brown DMForestAdaptivityStrategy strategy; 8800a96aa3bSJed Brown PetscSF cellSF; 8810a96aa3bSJed Brown PetscInt c, cStart, cEnd; 8820a96aa3bSJed Brown PetscBool adaptAny; 8830a96aa3bSJed Brown 8849566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &ctx.maxLevel)); 8859566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel)); 8869566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityStrategy(dm, &strategy)); 8879566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(strategy, "any", 3, &adaptAny)); 8889566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(adaptFrom, &cStart, &cEnd)); 8899566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(adaptFrom, &cellSF)); 8909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cStart, &cellFlags)); 8919566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; c++) PetscCall(DMLabelGetValue(adaptLabel, c, &cellFlags[c - cStart])); 8920a96aa3bSJed Brown if (cellSF) { 8930a96aa3bSJed Brown if (adaptAny) { 8949566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MAX)); 8959566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MAX)); 8960a96aa3bSJed Brown } else { 8979566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MIN)); 8989566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MIN)); 8990a96aa3bSJed Brown } 9000a96aa3bSJed Brown } 9010a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9020a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4est->trees->array)[t]); 9030a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count, i; 9040a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 9050a96aa3bSJed Brown 9060a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9070a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9080a96aa3bSJed Brown q->p.user_int = cellFlags[count++]; 9090a96aa3bSJed Brown } 9100a96aa3bSJed Brown } 9119566063dSJacob Faibussowitsch PetscCall(PetscFree(cellFlags)); 9120a96aa3bSJed Brown 9130a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 914792fecdfSBarry Smith if (adaptAny) PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_flag_any, pforest_init_determine)); 915792fecdfSBarry Smith else PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_flag_all, pforest_init_determine)); 916792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 0, pforest_refine_flag, NULL)); 9170a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 918792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 91948a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), apforest->forest, apforest->cLocalStart, pforest->forest, 0, &preCoarseToFine, &coarseToPreFine)); 9200a96aa3bSJed Brown } 9210a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9220a96aa3bSJed Brown p4est_tree_t *atree = &(((p4est_tree_t *)apforest->forest->trees->array)[t]); 9230a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)pforest->forest->trees->array)[t]); 9240a96aa3bSJed Brown PetscInt anumQuads = (PetscInt)atree->quadrants.elem_count, i; 9250a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 9260a96aa3bSJed Brown p4est_quadrant_t *aquads = (p4est_quadrant_t *)atree->quadrants.array; 9270a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 9280a96aa3bSJed Brown 9290a96aa3bSJed Brown if (anumQuads != numQuads) { 9300a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9310a96aa3bSJed Brown } else { 9320a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9330a96aa3bSJed Brown p4est_quadrant_t *aq = &aquads[i]; 9340a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9350a96aa3bSJed Brown 9360a96aa3bSJed Brown if (aq->level != q->level) { 9370a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9380a96aa3bSJed Brown break; 9390a96aa3bSJed Brown } 9400a96aa3bSJed Brown } 9410a96aa3bSJed Brown } 942ad540459SPierre Jolivet if (ctx.anyChange) break; 9430a96aa3bSJed Brown } 9440a96aa3bSJed Brown } 9450a96aa3bSJed Brown { 9460a96aa3bSJed Brown PetscInt numLabels, l; 9470a96aa3bSJed Brown 9489566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(adaptFrom, &numLabels)); 9490a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 9500a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 9510a96aa3bSJed Brown DMLabel label, labelNew; 9520a96aa3bSJed Brown PetscInt defVal; 9530a96aa3bSJed Brown const char *name; 9540a96aa3bSJed Brown 9559566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(adaptFrom, l, &name)); 9569566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(adaptFrom, l, &label)); 9579566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 9580a96aa3bSJed Brown if (isDepth) continue; 9599566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 9600a96aa3bSJed Brown if (isCellType) continue; 9619566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 9620a96aa3bSJed Brown if (isGhost) continue; 9639566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 9640a96aa3bSJed Brown if (isVTK) continue; 9659566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 9669566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &labelNew)); 9679566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defVal)); 9689566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew, defVal)); 9690a96aa3bSJed Brown } 9700a96aa3bSJed Brown } 9710a96aa3bSJed Brown } else { /* initial */ 9720a96aa3bSJed Brown PetscInt initLevel, minLevel; 97366c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI) 97466c0a4b5SToby Isaac sc_MPI_Comm comm = sc_MPI_COMM_WORLD; 97566c0a4b5SToby Isaac #else 97666c0a4b5SToby Isaac MPI_Comm comm = PetscObjectComm((PetscObject)dm); 97766c0a4b5SToby Isaac #endif 9780a96aa3bSJed Brown 9799566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm, &initLevel)); 9809566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel)); 9819371c9d4SSatish Balay PetscCallP4estReturn(pforest->forest, p4est_new_ext, 9829371c9d4SSatish Balay (comm, pforest->topo->conn, 0, /* minimum number of quadrants per processor */ 9830a96aa3bSJed Brown initLevel, /* level of refinement */ 9840a96aa3bSJed Brown 1, /* uniform refinement */ 9850a96aa3bSJed Brown 0, /* we don't allocate any per quadrant data */ 9860a96aa3bSJed Brown NULL, /* there is no special quadrant initialization */ 9870a96aa3bSJed Brown (void *)dm)); /* this dm is the user context */ 9880a96aa3bSJed Brown 9890a96aa3bSJed Brown if (initLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 9900a96aa3bSJed Brown if (dm->setfromoptionscalled) { 9910a96aa3bSJed Brown PetscBool flgPattern, flgFractal; 9920a96aa3bSJed Brown PetscInt corner = 0; 9930a96aa3bSJed Brown PetscInt corners[P4EST_CHILDREN], ncorner = P4EST_CHILDREN; 9940a96aa3bSJed Brown PetscReal likelihood = 1. / P4EST_DIM; 9950a96aa3bSJed Brown PetscInt pattern; 9960a96aa3bSJed Brown const char *prefix; 9970a96aa3bSJed Brown 9989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 9999566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEList(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_pattern", DMRefinePatternName, PATTERN_COUNT, &pattern, &flgPattern)); 10009566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_corner", &corner, NULL)); 10019566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_fractal_corners", corners, &ncorner, &flgFractal)); 10029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_hash_likelihood", &likelihood, NULL)); 10030a96aa3bSJed Brown 10040a96aa3bSJed Brown if (flgPattern) { 10050a96aa3bSJed Brown DMRefinePatternCtx *ctx; 10060a96aa3bSJed Brown PetscInt maxLevel; 10070a96aa3bSJed Brown 10089566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &maxLevel)); 1009*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ctx)); 10100a96aa3bSJed Brown ctx->maxLevel = PetscMin(maxLevel, P4EST_QMAXLEVEL); 10110a96aa3bSJed Brown if (initLevel + ctx->maxLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 10120a96aa3bSJed Brown switch (pattern) { 10130a96aa3bSJed Brown case PATTERN_HASH: 10140a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Hash; 10150a96aa3bSJed Brown ctx->hashLikelihood = likelihood; 10160a96aa3bSJed Brown break; 10170a96aa3bSJed Brown case PATTERN_CORNER: 10180a96aa3bSJed Brown ctx->corner = corner; 10190a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Corner; 10200a96aa3bSJed Brown break; 10219371c9d4SSatish Balay case PATTERN_CENTER: ctx->refine_fn = DMRefinePattern_Center; break; 10220a96aa3bSJed Brown case PATTERN_FRACTAL: 10230a96aa3bSJed Brown if (flgFractal) { 10240a96aa3bSJed Brown PetscInt i; 10250a96aa3bSJed Brown 10260a96aa3bSJed Brown for (i = 0; i < ncorner; i++) ctx->fractal[corners[i]] = PETSC_TRUE; 10270a96aa3bSJed Brown } else { 10280a96aa3bSJed Brown #if !defined(P4_TO_P8) 10290a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[1] = ctx->fractal[2] = PETSC_TRUE; 10300a96aa3bSJed Brown #else 10310a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[3] = ctx->fractal[5] = ctx->fractal[6] = PETSC_TRUE; 10320a96aa3bSJed Brown #endif 10330a96aa3bSJed Brown } 10340a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Fractal; 10350a96aa3bSJed Brown break; 10369371c9d4SSatish Balay default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Not a valid refinement pattern"); 10370a96aa3bSJed Brown } 10380a96aa3bSJed Brown 10390a96aa3bSJed Brown pforest->forest->user_pointer = (void *)ctx; 1040792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 1, ctx->refine_fn, NULL)); 1041792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 10429566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 10430a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 10440a96aa3bSJed Brown } 10450a96aa3bSJed Brown } 10460a96aa3bSJed Brown } 10470a96aa3bSJed Brown if (pforest->coarsen_hierarchy) { 10480a96aa3bSJed Brown PetscInt initLevel, currLevel, minLevel; 10490a96aa3bSJed Brown 10509566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm, &currLevel)); 10519566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm, &initLevel)); 10529566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel)); 10530a96aa3bSJed Brown if (currLevel > minLevel) { 10540a96aa3bSJed Brown DM_Forest_pforest *coarse_pforest; 10550a96aa3bSJed Brown DMLabel coarsen; 10560a96aa3bSJed Brown DM coarseDM; 10570a96aa3bSJed Brown 10589566063dSJacob Faibussowitsch PetscCall(DMForestTemplate(dm, MPI_COMM_NULL, &coarseDM)); 10599566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityPurpose(coarseDM, DM_ADAPT_COARSEN)); 10609566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "coarsen", &coarsen)); 10619566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(coarsen, DM_ADAPT_COARSEN)); 10629566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityLabel(coarseDM, coarsen)); 10639566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&coarsen)); 10649566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 10659566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 10660a96aa3bSJed Brown initLevel = currLevel == initLevel ? initLevel - 1 : initLevel; 10679566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(coarseDM, initLevel)); 10689566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(coarseDM, minLevel)); 10690a96aa3bSJed Brown coarse_pforest = (DM_Forest_pforest *)((DM_Forest *)coarseDM->data)->data; 10700a96aa3bSJed Brown coarse_pforest->coarsen_hierarchy = PETSC_TRUE; 10710a96aa3bSJed Brown } 10720a96aa3bSJed Brown } 10730a96aa3bSJed Brown 10740a96aa3bSJed Brown { /* repartitioning and overlap */ 10750a96aa3bSJed Brown PetscMPIInt size, rank; 10760a96aa3bSJed Brown 10779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 10789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 10790a96aa3bSJed Brown if ((size > 1) && (pforest->partition_for_coarsening || forest->cellWeights || forest->weightCapacity != 1. || forest->weightsFactor != 1.)) { 10800a96aa3bSJed Brown PetscBool copyForest = PETSC_FALSE; 10810a96aa3bSJed Brown p4est_t *forest_copy = NULL; 10820a96aa3bSJed Brown p4est_gloidx_t shipped = 0; 10830a96aa3bSJed Brown 10840a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) copyForest = PETSC_TRUE; 1085792fecdfSBarry Smith if (copyForest) PetscCallP4estReturn(forest_copy, p4est_copy, (pforest->forest, 0)); 10860a96aa3bSJed Brown 10870a96aa3bSJed Brown if (!forest->cellWeights && forest->weightCapacity == 1. && forest->weightsFactor == 1.) { 1088792fecdfSBarry Smith PetscCallP4estReturn(shipped, p4est_partition_ext, (pforest->forest, (int)pforest->partition_for_coarsening, NULL)); 10890a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Non-uniform partition cases not implemented yet"); 10900a96aa3bSJed Brown if (shipped) ctx.anyChange = PETSC_TRUE; 10910a96aa3bSJed Brown if (forest_copy) { 10920a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 10930a96aa3bSJed Brown PetscSF repartSF; /* repartSF has roots in the old partition */ 10940a96aa3bSJed Brown PetscInt pStart = -1, pEnd = -1, p; 10950a96aa3bSJed Brown PetscInt numRoots, numLeaves; 10960a96aa3bSJed Brown PetscSFNode *repartRoots; 10970a96aa3bSJed Brown p4est_gloidx_t postStart = pforest->forest->global_first_quadrant[rank]; 10980a96aa3bSJed Brown p4est_gloidx_t postEnd = pforest->forest->global_first_quadrant[rank + 1]; 10990a96aa3bSJed Brown p4est_gloidx_t partOffset = postStart; 11000a96aa3bSJed Brown 11010a96aa3bSJed Brown numRoots = (PetscInt)(forest_copy->global_first_quadrant[rank + 1] - forest_copy->global_first_quadrant[rank]); 11020a96aa3bSJed Brown numLeaves = (PetscInt)(postEnd - postStart); 11039566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(size, rank, pforest->forest, forest_copy, &pStart, &pEnd)); 11049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((PetscInt)pforest->forest->local_num_quadrants, &repartRoots)); 11050a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 11060a96aa3bSJed Brown p4est_gloidx_t preStart = forest_copy->global_first_quadrant[p]; 11070a96aa3bSJed Brown p4est_gloidx_t preEnd = forest_copy->global_first_quadrant[p + 1]; 11080a96aa3bSJed Brown PetscInt q; 11090a96aa3bSJed Brown 11100a96aa3bSJed Brown if (preEnd == preStart) continue; 111108401ef6SPierre Jolivet PetscCheck(preStart <= postStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad partition overlap computation"); 11120a96aa3bSJed Brown preEnd = preEnd > postEnd ? postEnd : preEnd; 11130a96aa3bSJed Brown for (q = partOffset; q < preEnd; q++) { 11140a96aa3bSJed Brown repartRoots[q - postStart].rank = p; 11150a96aa3bSJed Brown repartRoots[q - postStart].index = partOffset - preStart; 11160a96aa3bSJed Brown } 11170a96aa3bSJed Brown partOffset = preEnd; 11180a96aa3bSJed Brown } 11199566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &repartSF)); 11209566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(repartSF, numRoots, numLeaves, NULL, PETSC_OWN_POINTER, repartRoots, PETSC_OWN_POINTER)); 11219566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(repartSF)); 11220a96aa3bSJed Brown if (preCoarseToFine) { 11230a96aa3bSJed Brown PetscSF repartSFembed, preCoarseToFineNew; 11240a96aa3bSJed Brown PetscInt nleaves; 11250a96aa3bSJed Brown const PetscInt *leaves; 11260a96aa3bSJed Brown 11279566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 11289566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine, NULL, &nleaves, &leaves, NULL)); 11290a96aa3bSJed Brown if (leaves) { 11309566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(repartSF, nleaves, leaves, &repartSFembed)); 11310a96aa3bSJed Brown } else { 11320a96aa3bSJed Brown repartSFembed = repartSF; 11339566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)repartSFembed)); 11340a96aa3bSJed Brown } 11359566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(preCoarseToFine, repartSFembed, &preCoarseToFineNew)); 11369566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 11379566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFembed)); 11380a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 11390a96aa3bSJed Brown } 11400a96aa3bSJed Brown if (coarseToPreFine) { 11410a96aa3bSJed Brown PetscSF repartSFinv, coarseToPreFineNew; 11420a96aa3bSJed Brown 11439566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(repartSF, &repartSFinv)); 11449566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(repartSFinv, coarseToPreFine, &coarseToPreFineNew)); 11459566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 11469566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFinv)); 11470a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 11480a96aa3bSJed Brown } 11499566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSF)); 11500a96aa3bSJed Brown } 1151792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (forest_copy)); 11520a96aa3bSJed Brown } 11530a96aa3bSJed Brown } 11540a96aa3bSJed Brown if (size > 1) { 11550a96aa3bSJed Brown PetscInt overlap; 11560a96aa3bSJed Brown 11579566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 11580a96aa3bSJed Brown 11590a96aa3bSJed Brown if (adaptFrom) { 11600a96aa3bSJed Brown PetscInt aoverlap; 11610a96aa3bSJed Brown 11629566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(adaptFrom, &aoverlap)); 1163ad540459SPierre Jolivet if (aoverlap != overlap) ctx.anyChange = PETSC_TRUE; 11640a96aa3bSJed Brown } 11650a96aa3bSJed Brown 11660a96aa3bSJed Brown if (overlap > 0) { 11670a96aa3bSJed Brown PetscInt i, cLocalStart; 11680a96aa3bSJed Brown PetscInt cEnd; 11690a96aa3bSJed Brown PetscSF preCellSF = NULL, cellSF = NULL; 11700a96aa3bSJed Brown 1171792fecdfSBarry Smith PetscCallP4estReturn(pforest->ghost, p4est_ghost_new, (pforest->forest, P4EST_CONNECT_FULL)); 1172792fecdfSBarry Smith PetscCallP4estReturn(pforest->lnodes, p4est_lnodes_new, (pforest->forest, pforest->ghost, -P4EST_DIM)); 1173792fecdfSBarry Smith PetscCallP4est(p4est_ghost_support_lnodes, (pforest->forest, pforest->lnodes, pforest->ghost)); 1174792fecdfSBarry Smith for (i = 1; i < overlap; i++) PetscCallP4est(p4est_ghost_expand_by_lnodes, (pforest->forest, pforest->lnodes, pforest->ghost)); 11750a96aa3bSJed Brown 11760a96aa3bSJed Brown cLocalStart = pforest->cLocalStart = pforest->ghost->proc_offsets[rank]; 11770a96aa3bSJed Brown cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[size]; 11780a96aa3bSJed Brown 11790a96aa3bSJed Brown /* shift sfs by cLocalStart, expand by cell SFs */ 11800a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 11819566063dSJacob Faibussowitsch if (adaptFrom) PetscCall(DMForestGetCellSF(adaptFrom, &preCellSF)); 11820a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 11839566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(dm, &cellSF)); 11840a96aa3bSJed Brown } 11850a96aa3bSJed Brown if (preCoarseToFine) { 11860a96aa3bSJed Brown PetscSF preCoarseToFineNew; 11870a96aa3bSJed Brown PetscInt nleaves, nroots, *leavesNew, i, nleavesNew; 11880a96aa3bSJed Brown const PetscInt *leaves; 11890a96aa3bSJed Brown const PetscSFNode *remotes; 11900a96aa3bSJed Brown PetscSFNode *remotesAll; 11910a96aa3bSJed Brown 11929566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 11939566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine, &nroots, &nleaves, &leaves, &remotes)); 11949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd, &remotesAll)); 11950a96aa3bSJed Brown for (i = 0; i < cEnd; i++) { 11960a96aa3bSJed Brown remotesAll[i].rank = -1; 11970a96aa3bSJed Brown remotesAll[i].index = -1; 11980a96aa3bSJed Brown } 11990a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesAll[(leaves ? leaves[i] : i) + cLocalStart] = remotes[i]; 12009566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(cellSF)); 12019566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(cellSF, MPIU_2INT, remotesAll, remotesAll, MPI_REPLACE)); 12029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(cellSF, MPIU_2INT, remotesAll, remotesAll, MPI_REPLACE)); 12030a96aa3bSJed Brown nleavesNew = 0; 12040a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12050a96aa3bSJed Brown if (remotesAll[i].rank >= 0) nleavesNew++; 12060a96aa3bSJed Brown } 12079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesNew, &leavesNew)); 12080a96aa3bSJed Brown nleavesNew = 0; 12090a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12100a96aa3bSJed Brown if (remotesAll[i].rank >= 0) { 12110a96aa3bSJed Brown leavesNew[nleavesNew] = i; 12120a96aa3bSJed Brown if (i > nleavesNew) remotesAll[nleavesNew] = remotesAll[i]; 12130a96aa3bSJed Brown nleavesNew++; 12140a96aa3bSJed Brown } 12150a96aa3bSJed Brown } 12169566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &preCoarseToFineNew)); 12170a96aa3bSJed Brown if (nleavesNew < cEnd) { 12189566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew, nroots, nleavesNew, leavesNew, PETSC_OWN_POINTER, remotesAll, PETSC_COPY_VALUES)); 12190a96aa3bSJed Brown } else { /* all cells are leaves */ 12209566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 12219566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew, nroots, nleavesNew, NULL, PETSC_OWN_POINTER, remotesAll, PETSC_COPY_VALUES)); 12220a96aa3bSJed Brown } 12239566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesAll)); 12249566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 12250a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12260a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12270a96aa3bSJed Brown } 12280a96aa3bSJed Brown if (coarseToPreFine) { 12290a96aa3bSJed Brown PetscSF coarseToPreFineNew; 12300a96aa3bSJed Brown PetscInt nleaves, nroots, i, nleavesCellSF, nleavesExpanded, *leavesNew; 12310a96aa3bSJed Brown const PetscInt *leaves; 12320a96aa3bSJed Brown const PetscSFNode *remotes; 12330a96aa3bSJed Brown PetscSFNode *remotesNew, *remotesNewRoot, *remotesExpanded; 12340a96aa3bSJed Brown 12359566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(coarseToPreFine)); 12369566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToPreFine, &nroots, &nleaves, &leaves, &remotes)); 12379566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCellSF, NULL, &nleavesCellSF, NULL, NULL)); 12389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &remotesNewRoot)); 12399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotesNew)); 12400a96aa3bSJed Brown for (i = 0; i < nroots; i++) { 12410a96aa3bSJed Brown remotesNewRoot[i].rank = rank; 12420a96aa3bSJed Brown remotesNewRoot[i].index = i + cLocalStart; 12430a96aa3bSJed Brown } 12449566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToPreFine, MPIU_2INT, remotesNewRoot, remotesNew, MPI_REPLACE)); 12459566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToPreFine, MPIU_2INT, remotesNewRoot, remotesNew, MPI_REPLACE)); 12469566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNewRoot)); 12479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesCellSF, &remotesExpanded)); 12480a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12490a96aa3bSJed Brown remotesExpanded[i].rank = -1; 12500a96aa3bSJed Brown remotesExpanded[i].index = -1; 12510a96aa3bSJed Brown } 12520a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesExpanded[leaves ? leaves[i] : i] = remotesNew[i]; 12539566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNew)); 12549566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(preCellSF, MPIU_2INT, remotesExpanded, remotesExpanded, MPI_REPLACE)); 12559566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(preCellSF, MPIU_2INT, remotesExpanded, remotesExpanded, MPI_REPLACE)); 12560a96aa3bSJed Brown 12570a96aa3bSJed Brown nleavesExpanded = 0; 12580a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12590a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) nleavesExpanded++; 12600a96aa3bSJed Brown } 12619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesExpanded, &leavesNew)); 12620a96aa3bSJed Brown nleavesExpanded = 0; 12630a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12640a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) { 12650a96aa3bSJed Brown leavesNew[nleavesExpanded] = i; 12660a96aa3bSJed Brown if (i > nleavesExpanded) remotesExpanded[nleavesExpanded] = remotes[i]; 12670a96aa3bSJed Brown nleavesExpanded++; 12680a96aa3bSJed Brown } 12690a96aa3bSJed Brown } 12709566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &coarseToPreFineNew)); 12710a96aa3bSJed Brown if (nleavesExpanded < nleavesCellSF) { 12729566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew, cEnd, nleavesExpanded, leavesNew, PETSC_OWN_POINTER, remotesExpanded, PETSC_COPY_VALUES)); 12730a96aa3bSJed Brown } else { 12749566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 12759566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew, cEnd, nleavesExpanded, NULL, PETSC_OWN_POINTER, remotesExpanded, PETSC_COPY_VALUES)); 12760a96aa3bSJed Brown } 12779566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesExpanded)); 12789566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 12790a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 12800a96aa3bSJed Brown } 12810a96aa3bSJed Brown } 12820a96aa3bSJed Brown } 12830a96aa3bSJed Brown } 12840a96aa3bSJed Brown forest->preCoarseToFine = preCoarseToFine; 12850a96aa3bSJed Brown forest->coarseToPreFine = coarseToPreFine; 12860a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 12879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&ctx.anyChange, &(pforest->adaptivitySuccess), 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 12889566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, NULL)); 12890a96aa3bSJed Brown PetscFunctionReturn(0); 12900a96aa3bSJed Brown } 12910a96aa3bSJed Brown 12920a96aa3bSJed Brown #define DMForestGetAdaptivitySuccess_pforest _append_pforest(DMForestGetAdaptivitySuccess) 12939371c9d4SSatish Balay static PetscErrorCode DMForestGetAdaptivitySuccess_pforest(DM dm, PetscBool *success) { 12940a96aa3bSJed Brown DM_Forest *forest; 12950a96aa3bSJed Brown DM_Forest_pforest *pforest; 12960a96aa3bSJed Brown 12970a96aa3bSJed Brown PetscFunctionBegin; 12980a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 12990a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 13000a96aa3bSJed Brown *success = pforest->adaptivitySuccess; 13010a96aa3bSJed Brown PetscFunctionReturn(0); 13020a96aa3bSJed Brown } 13030a96aa3bSJed Brown 13040a96aa3bSJed Brown #define DMView_ASCII_pforest _append_pforest(DMView_ASCII) 13059371c9d4SSatish Balay static PetscErrorCode DMView_ASCII_pforest(PetscObject odm, PetscViewer viewer) { 13060a96aa3bSJed Brown DM dm = (DM)odm; 13070a96aa3bSJed Brown 13080a96aa3bSJed Brown PetscFunctionBegin; 13090a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13100a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13119566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13120a96aa3bSJed Brown switch (viewer->format) { 13130a96aa3bSJed Brown case PETSC_VIEWER_DEFAULT: 13149371c9d4SSatish Balay case PETSC_VIEWER_ASCII_INFO: { 13150a96aa3bSJed Brown PetscInt dim; 13160a96aa3bSJed Brown const char *name; 13170a96aa3bSJed Brown 13189566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 13199566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 132063a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "Forest %s in %" PetscInt_FMT " dimensions:\n", name, dim)); 132163a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Forest in %" PetscInt_FMT " dimensions:\n", dim)); 13220a96aa3bSJed Brown } 13230a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO_DETAIL: 13249371c9d4SSatish Balay case PETSC_VIEWER_LOAD_BALANCE: { 13250a96aa3bSJed Brown DM plex; 13260a96aa3bSJed Brown 13279566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 13289566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 13299371c9d4SSatish Balay } break; 133098921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 13310a96aa3bSJed Brown } 13320a96aa3bSJed Brown PetscFunctionReturn(0); 13330a96aa3bSJed Brown } 13340a96aa3bSJed Brown 13350a96aa3bSJed Brown #define DMView_VTK_pforest _append_pforest(DMView_VTK) 13369371c9d4SSatish Balay static PetscErrorCode DMView_VTK_pforest(PetscObject odm, PetscViewer viewer) { 13370a96aa3bSJed Brown DM dm = (DM)odm; 13380a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 13390a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 13400a96aa3bSJed Brown PetscBool isvtk; 13410a96aa3bSJed Brown PetscReal vtkScale = 1. - PETSC_MACHINE_EPSILON; 13420a96aa3bSJed Brown PetscViewer_VTK *vtk = (PetscViewer_VTK *)viewer->data; 13430a96aa3bSJed Brown const char *name; 13440a96aa3bSJed Brown char *filenameStrip = NULL; 13450a96aa3bSJed Brown PetscBool hasExt; 13460a96aa3bSJed Brown size_t len; 13470a96aa3bSJed Brown p4est_geometry_t *geom; 13480a96aa3bSJed Brown 13490a96aa3bSJed Brown PetscFunctionBegin; 13500a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13510a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13529566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13530a96aa3bSJed Brown geom = pforest->topo->geom; 13549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 135528b400f6SJacob Faibussowitsch PetscCheck(isvtk, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name); 13560a96aa3bSJed Brown switch (viewer->format) { 13570a96aa3bSJed Brown case PETSC_VIEWER_VTK_VTU: 135828b400f6SJacob Faibussowitsch PetscCheck(pforest->forest, PetscObjectComm(odm), PETSC_ERR_ARG_WRONG, "DM has not been setup with a valid forest"); 13590a96aa3bSJed Brown name = vtk->filename; 13609566063dSJacob Faibussowitsch PetscCall(PetscStrlen(name, &len)); 13619566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(name + len - 4, ".vtu", &hasExt)); 13620a96aa3bSJed Brown if (hasExt) { 13639566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &filenameStrip)); 13640a96aa3bSJed Brown filenameStrip[len - 4] = '\0'; 13650a96aa3bSJed Brown name = filenameStrip; 13660a96aa3bSJed Brown } 1367792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4estReturn(geom, p4est_geometry_new_connectivity, (pforest->topo->conn)); 13680a96aa3bSJed Brown { 13690a96aa3bSJed Brown p4est_vtk_context_t *pvtk; 13700a96aa3bSJed Brown int footerr; 13710a96aa3bSJed Brown 1372792fecdfSBarry Smith PetscCallP4estReturn(pvtk, p4est_vtk_context_new, (pforest->forest, name)); 1373792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_geom, (pvtk, geom)); 1374792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_scale, (pvtk, (double)vtkScale)); 1375792fecdfSBarry Smith PetscCallP4estReturn(pvtk, p4est_vtk_write_header, (pvtk)); 137628b400f6SJacob Faibussowitsch PetscCheck(pvtk, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_header() failed"); 13779371c9d4SSatish Balay PetscCallP4estReturn(pvtk, p4est_vtk_write_cell_dataf, 13789371c9d4SSatish Balay (pvtk, 1, /* write tree */ 13790a96aa3bSJed Brown 1, /* write level */ 13800a96aa3bSJed Brown 1, /* write rank */ 13810a96aa3bSJed Brown 0, /* do not wrap rank */ 13820a96aa3bSJed Brown 0, /* no scalar fields */ 13830a96aa3bSJed Brown 0, /* no vector fields */ 13840a96aa3bSJed Brown pvtk)); 138528b400f6SJacob Faibussowitsch PetscCheck(pvtk, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_cell_dataf() failed"); 1386792fecdfSBarry Smith PetscCallP4estReturn(footerr, p4est_vtk_write_footer, (pvtk)); 138728b400f6SJacob Faibussowitsch PetscCheck(!footerr, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_footer() failed"); 13880a96aa3bSJed Brown } 1389792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4est(p4est_geometry_destroy, (geom)); 13909566063dSJacob Faibussowitsch PetscCall(PetscFree(filenameStrip)); 13910a96aa3bSJed Brown break; 139298921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 13930a96aa3bSJed Brown } 13940a96aa3bSJed Brown PetscFunctionReturn(0); 13950a96aa3bSJed Brown } 13960a96aa3bSJed Brown 13970a96aa3bSJed Brown #define DMView_HDF5_pforest _append_pforest(DMView_HDF5) 13989371c9d4SSatish Balay static PetscErrorCode DMView_HDF5_pforest(DM dm, PetscViewer viewer) { 13990a96aa3bSJed Brown DM plex; 14000a96aa3bSJed Brown 14010a96aa3bSJed Brown PetscFunctionBegin; 14029566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 14039566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 14049566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 14050a96aa3bSJed Brown PetscFunctionReturn(0); 14060a96aa3bSJed Brown } 14070a96aa3bSJed Brown 14080a96aa3bSJed Brown #define DMView_GLVis_pforest _append_pforest(DMView_GLVis) 14099371c9d4SSatish Balay static PetscErrorCode DMView_GLVis_pforest(DM dm, PetscViewer viewer) { 14100a96aa3bSJed Brown DM plex; 14110a96aa3bSJed Brown 14120a96aa3bSJed Brown PetscFunctionBegin; 14139566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 14149566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 14159566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 14160a96aa3bSJed Brown PetscFunctionReturn(0); 14170a96aa3bSJed Brown } 14180a96aa3bSJed Brown 14190a96aa3bSJed Brown #define DMView_pforest _append_pforest(DMView) 14209371c9d4SSatish Balay static PetscErrorCode DMView_pforest(DM dm, PetscViewer viewer) { 14210a96aa3bSJed Brown PetscBool isascii, isvtk, ishdf5, isglvis; 14220a96aa3bSJed Brown 14230a96aa3bSJed Brown PetscFunctionBegin; 14240a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14250a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 14269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 14279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 14289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 14299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 14300a96aa3bSJed Brown if (isascii) { 14319566063dSJacob Faibussowitsch PetscCall(DMView_ASCII_pforest((PetscObject)dm, viewer)); 14320a96aa3bSJed Brown } else if (isvtk) { 14339566063dSJacob Faibussowitsch PetscCall(DMView_VTK_pforest((PetscObject)dm, viewer)); 14340a96aa3bSJed Brown } else if (ishdf5) { 14359566063dSJacob Faibussowitsch PetscCall(DMView_HDF5_pforest(dm, viewer)); 14360a96aa3bSJed Brown } else if (isglvis) { 14379566063dSJacob Faibussowitsch PetscCall(DMView_GLVis_pforest(dm, viewer)); 14380a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer not supported (not VTK, HDF5, or GLVis)"); 14390a96aa3bSJed Brown PetscFunctionReturn(0); 14400a96aa3bSJed Brown } 14410a96aa3bSJed Brown 14429371c9d4SSatish Balay static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *conn, PetscInt **tree_face_to_uniq) { 14430a96aa3bSJed Brown PetscInt *ttf, f, t, g, count; 14440a96aa3bSJed Brown PetscInt numFacets; 14450a96aa3bSJed Brown 14460a96aa3bSJed Brown PetscFunctionBegin; 14470a96aa3bSJed Brown numFacets = conn->num_trees * P4EST_FACES; 14489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFacets, &ttf)); 14490a96aa3bSJed Brown for (f = 0; f < numFacets; f++) ttf[f] = -1; 14500a96aa3bSJed Brown for (g = 0, count = 0, t = 0; t < conn->num_trees; t++) { 14510a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++, g++) { 14520a96aa3bSJed Brown if (ttf[g] == -1) { 14530a96aa3bSJed Brown PetscInt ng; 14540a96aa3bSJed Brown 14550a96aa3bSJed Brown ttf[g] = count++; 14560a96aa3bSJed Brown ng = conn->tree_to_tree[g] * P4EST_FACES + (conn->tree_to_face[g] % P4EST_FACES); 14570a96aa3bSJed Brown ttf[ng] = ttf[g]; 14580a96aa3bSJed Brown } 14590a96aa3bSJed Brown } 14600a96aa3bSJed Brown } 14610a96aa3bSJed Brown *tree_face_to_uniq = ttf; 14620a96aa3bSJed Brown PetscFunctionReturn(0); 14630a96aa3bSJed Brown } 14640a96aa3bSJed Brown 14659371c9d4SSatish Balay static PetscErrorCode DMPlexCreateConnectivity_pforest(DM dm, p4est_connectivity_t **connOut, PetscInt **tree_face_to_uniq) { 14660a96aa3bSJed Brown p4est_topidx_t numTrees, numVerts, numCorns, numCtt; 14670a96aa3bSJed Brown PetscSection ctt; 14680a96aa3bSJed Brown #if defined(P4_TO_P8) 14690a96aa3bSJed Brown p4est_topidx_t numEdges, numEtt; 14700a96aa3bSJed Brown PetscSection ett; 14710a96aa3bSJed Brown PetscInt eStart, eEnd, e, ettSize; 14720a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES + P8EST_EDGES; 14730a96aa3bSJed Brown PetscInt edgeOff = 1 + P4EST_FACES; 14740a96aa3bSJed Brown #else 14750a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES; 14760a96aa3bSJed Brown #endif 14770a96aa3bSJed Brown p4est_connectivity_t *conn; 14780a96aa3bSJed Brown PetscInt cStart, cEnd, c, vStart, vEnd, v, fStart, fEnd, f; 14790a96aa3bSJed Brown PetscInt *star = NULL, *closure = NULL, closureSize, starSize, cttSize; 14800a96aa3bSJed Brown PetscInt *ttf; 14810a96aa3bSJed Brown 14820a96aa3bSJed Brown PetscFunctionBegin; 14830a96aa3bSJed Brown /* 1: count objects, allocate */ 14849566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 14859566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cEnd - cStart, &numTrees)); 14860a96aa3bSJed Brown numVerts = P4EST_CHILDREN * numTrees; 14879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 14889566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(vEnd - vStart, &numCorns)); 14899566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &ctt)); 14909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ctt, vStart, vEnd)); 14910a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 14920a96aa3bSJed Brown PetscInt s; 14930a96aa3bSJed Brown 14949566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 14950a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 14960a96aa3bSJed Brown PetscInt p = star[2 * s]; 14970a96aa3bSJed Brown 14980a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 14990a96aa3bSJed Brown /* we want to count every time cell p references v, so we see how many times it comes up in the closure. This 15000a96aa3bSJed Brown * only protects against periodicity problems */ 15019566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 150263a3b9bcSJacob Faibussowitsch PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell %" PetscInt_FMT " with wrong closure size %" PetscInt_FMT " != %d", p, closureSize, P4EST_INSUL); 15030a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 15040a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 15050a96aa3bSJed Brown 15061dca8a05SBarry Smith PetscCheck(cellVert >= vStart && cellVert < vEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure: vertices"); 150748a46eb9SPierre Jolivet if (cellVert == v) PetscCall(PetscSectionAddDof(ctt, v, 1)); 15080a96aa3bSJed Brown } 15099566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 15100a96aa3bSJed Brown } 15110a96aa3bSJed Brown } 15129566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 15130a96aa3bSJed Brown } 15149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ctt)); 15159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ctt, &cttSize)); 15169566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cttSize, &numCtt)); 15170a96aa3bSJed Brown #if defined(P4_TO_P8) 15189566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, P4EST_DIM - 1, &eStart, &eEnd)); 15199566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(eEnd - eStart, &numEdges)); 15209566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &ett)); 15219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ett, eStart, eEnd)); 15220a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 15230a96aa3bSJed Brown PetscInt s; 15240a96aa3bSJed Brown 15259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 15260a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 15270a96aa3bSJed Brown PetscInt p = star[2 * s]; 15280a96aa3bSJed Brown 15290a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 15300a96aa3bSJed Brown /* we want to count every time cell p references e, so we see how many times it comes up in the closure. This 15310a96aa3bSJed Brown * only protects against periodicity problems */ 15329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 153308401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell with wrong closure size"); 15340a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 15350a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 15360a96aa3bSJed Brown 15371dca8a05SBarry Smith PetscCheck(cellEdge >= eStart && cellEdge < eEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure: edges"); 153848a46eb9SPierre Jolivet if (cellEdge == e) PetscCall(PetscSectionAddDof(ett, e, 1)); 15390a96aa3bSJed Brown } 15409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 15410a96aa3bSJed Brown } 15420a96aa3bSJed Brown } 15439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 15440a96aa3bSJed Brown } 15459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ett)); 15469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ett, &ettSize)); 15479566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(ettSize, &numEtt)); 15480a96aa3bSJed Brown 15490a96aa3bSJed Brown /* This routine allocates space for the arrays, which we fill below */ 1550792fecdfSBarry Smith PetscCallP4estReturn(conn, p8est_connectivity_new, (numVerts, numTrees, numEdges, numEtt, numCorns, numCtt)); 15510a96aa3bSJed Brown #else 1552792fecdfSBarry Smith PetscCallP4estReturn(conn, p4est_connectivity_new, (numVerts, numTrees, numCorns, numCtt)); 15530a96aa3bSJed Brown #endif 15540a96aa3bSJed Brown 15550a96aa3bSJed Brown /* 2: visit every face, determine neighboring cells(trees) */ 15569566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 1, &fStart, &fEnd)); 15579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * P4EST_FACES, &ttf)); 15580a96aa3bSJed Brown for (f = fStart; f < fEnd; f++) { 15590a96aa3bSJed Brown PetscInt numSupp, s; 15600a96aa3bSJed Brown PetscInt myFace[2] = {-1, -1}; 15610a96aa3bSJed Brown PetscInt myOrnt[2] = {PETSC_MIN_INT, PETSC_MIN_INT}; 15620a96aa3bSJed Brown const PetscInt *supp; 15630a96aa3bSJed Brown 15649566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &numSupp)); 15651dca8a05SBarry Smith PetscCheck(numSupp == 1 || numSupp == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "point %" PetscInt_FMT " has facet with %" PetscInt_FMT " sides: must be 1 or 2 (boundary or conformal)", f, numSupp); 15669566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &supp)); 15670a96aa3bSJed Brown 15680a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 15690a96aa3bSJed Brown PetscInt p = supp[s]; 15700a96aa3bSJed Brown 15710a96aa3bSJed Brown if (p >= cEnd) { 15720a96aa3bSJed Brown numSupp--; 15730a96aa3bSJed Brown if (s) supp = &supp[1 - s]; 15740a96aa3bSJed Brown break; 15750a96aa3bSJed Brown } 15760a96aa3bSJed Brown } 15770a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 15780a96aa3bSJed Brown PetscInt p = supp[s], i; 15790a96aa3bSJed Brown PetscInt numCone; 15800a96aa3bSJed Brown DMPolytopeType ct; 15810a96aa3bSJed Brown const PetscInt *cone; 15820a96aa3bSJed Brown const PetscInt *ornt; 15830a96aa3bSJed Brown PetscInt orient = PETSC_MIN_INT; 15840a96aa3bSJed Brown 15859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &numCone)); 158663a3b9bcSJacob Faibussowitsch PetscCheck(numCone == P4EST_FACES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "cell %" PetscInt_FMT " has %" PetscInt_FMT " facets, expect %d", p, numCone, P4EST_FACES); 15879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 15889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[0], &ct)); 15899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 15900a96aa3bSJed Brown for (i = 0; i < P4EST_FACES; i++) { 15910a96aa3bSJed Brown if (cone[i] == f) { 15920a96aa3bSJed Brown orient = DMPolytopeConvertNewOrientation_Internal(ct, ornt[i]); 15930a96aa3bSJed Brown break; 15940a96aa3bSJed Brown } 15950a96aa3bSJed Brown } 159663a3b9bcSJacob Faibussowitsch PetscCheck(i < P4EST_FACES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "cell %" PetscInt_FMT " faced %" PetscInt_FMT " mismatch", p, f); 15970a96aa3bSJed Brown if (p < cStart || p >= cEnd) { 15980a96aa3bSJed Brown DMPolytopeType ct; 15999566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 160063a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "cell %" PetscInt_FMT " (%s) should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, DMPolytopeTypes[ct], cStart, cEnd); 16010a96aa3bSJed Brown } 16020a96aa3bSJed Brown ttf[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = f - fStart; 16030a96aa3bSJed Brown if (numSupp == 1) { 16040a96aa3bSJed Brown /* boundary faces indicated by self reference */ 16050a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = p - cStart; 16060a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = (int8_t)PetscFaceToP4estFace[i]; 16070a96aa3bSJed Brown } else { 16080a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16090a96aa3bSJed Brown 16100a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = supp[1 - s] - cStart; 16110a96aa3bSJed Brown myFace[s] = PetscFaceToP4estFace[i]; 16120a96aa3bSJed Brown /* get the orientation of cell p in p4est-type closure to facet f, by composing the p4est-closure to 16130a96aa3bSJed Brown * petsc-closure permutation and the petsc-closure to facet orientation */ 16140a96aa3bSJed Brown myOrnt[s] = DihedralCompose(N, orient, DMPolytopeConvertNewOrientation_Internal(ct, P4estFaceToPetscOrnt[myFace[s]])); 16150a96aa3bSJed Brown } 16160a96aa3bSJed Brown } 16170a96aa3bSJed Brown if (numSupp == 2) { 16180a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16190a96aa3bSJed Brown PetscInt p = supp[s]; 16200a96aa3bSJed Brown PetscInt orntAtoB; 16210a96aa3bSJed Brown PetscInt p4estOrient; 16220a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16230a96aa3bSJed Brown 16240a96aa3bSJed Brown /* composing the forward permutation with the other cell's inverse permutation gives the self-to-neighbor 16250a96aa3bSJed Brown * permutation of this cell-facet's cone */ 16260a96aa3bSJed Brown orntAtoB = DihedralCompose(N, DihedralInvert(N, myOrnt[1 - s]), myOrnt[s]); 16270a96aa3bSJed Brown 16280a96aa3bSJed Brown /* convert cone-description permutation (i.e., edges around facet) to cap-description permutation (i.e., 16290a96aa3bSJed Brown * vertices around facet) */ 16300a96aa3bSJed Brown #if !defined(P4_TO_P8) 16310a96aa3bSJed Brown p4estOrient = orntAtoB < 0 ? -(orntAtoB + 1) : orntAtoB; 16320a96aa3bSJed Brown #else 16330a96aa3bSJed Brown { 16340a96aa3bSJed Brown PetscInt firstVert = orntAtoB < 0 ? ((-orntAtoB) % N) : orntAtoB; 16350a96aa3bSJed Brown PetscInt p4estFirstVert = firstVert < 2 ? firstVert : (firstVert ^ 1); 16360a96aa3bSJed Brown 16370a96aa3bSJed Brown /* swap bits */ 16380a96aa3bSJed Brown p4estOrient = ((myFace[s] <= myFace[1 - s]) || (orntAtoB < 0)) ? p4estFirstVert : ((p4estFirstVert >> 1) | ((p4estFirstVert & 1) << 1)); 16390a96aa3bSJed Brown } 16400a96aa3bSJed Brown #endif 16410a96aa3bSJed Brown /* encode neighbor face and orientation in tree_to_face per p4est_connectivity standard (see 16420a96aa3bSJed Brown * p4est_connectivity.h, p8est_connectivity.h) */ 16430a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + myFace[s]] = (int8_t)myFace[1 - s] + p4estOrient * P4EST_FACES; 16440a96aa3bSJed Brown } 16450a96aa3bSJed Brown } 16460a96aa3bSJed Brown } 16470a96aa3bSJed Brown 16480a96aa3bSJed Brown #if defined(P4_TO_P8) 16490a96aa3bSJed Brown /* 3: visit every edge */ 16500a96aa3bSJed Brown conn->ett_offset[0] = 0; 16510a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 16520a96aa3bSJed Brown PetscInt off, s; 16530a96aa3bSJed Brown 16549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ett, e, &off)); 16550a96aa3bSJed Brown conn->ett_offset[e - eStart] = (p4est_topidx_t)off; 16569566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 16570a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 16580a96aa3bSJed Brown PetscInt p = star[2 * s]; 16590a96aa3bSJed Brown 16600a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 16619566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 166208401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure"); 16630a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 16640a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 16650a96aa3bSJed Brown PetscInt cellOrnt = closure[2 * (c + edgeOff) + 1]; 16660a96aa3bSJed Brown DMPolytopeType ct; 16670a96aa3bSJed Brown 16689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cellEdge, &ct)); 16690a96aa3bSJed Brown cellOrnt = DMPolytopeConvertNewOrientation_Internal(ct, cellOrnt); 16700a96aa3bSJed Brown if (cellEdge == e) { 16710a96aa3bSJed Brown PetscInt p4estEdge = PetscEdgeToP4estEdge[c]; 16720a96aa3bSJed Brown PetscInt totalOrient; 16730a96aa3bSJed Brown 16740a96aa3bSJed Brown /* compose p4est-closure to petsc-closure permutation and petsc-closure to edge orientation */ 16750a96aa3bSJed Brown totalOrient = DihedralCompose(2, cellOrnt, DMPolytopeConvertNewOrientation_Internal(DM_POLYTOPE_SEGMENT, P4estEdgeToPetscOrnt[p4estEdge])); 16760a96aa3bSJed Brown /* p4est orientations are positive: -2 => 1, -1 => 0 */ 16770a96aa3bSJed Brown totalOrient = (totalOrient < 0) ? -(totalOrient + 1) : totalOrient; 16780a96aa3bSJed Brown conn->edge_to_tree[off] = (p4est_locidx_t)(p - cStart); 16790a96aa3bSJed Brown /* encode cell-edge and orientation in edge_to_edge per p8est_connectivity standart (see 16800a96aa3bSJed Brown * p8est_connectivity.h) */ 16810a96aa3bSJed Brown conn->edge_to_edge[off++] = (int8_t)p4estEdge + P8EST_EDGES * totalOrient; 16820a96aa3bSJed Brown conn->tree_to_edge[P8EST_EDGES * (p - cStart) + p4estEdge] = e - eStart; 16830a96aa3bSJed Brown } 16840a96aa3bSJed Brown } 16859566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 16860a96aa3bSJed Brown } 16870a96aa3bSJed Brown } 16889566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 16890a96aa3bSJed Brown } 16909566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ett)); 16910a96aa3bSJed Brown #endif 16920a96aa3bSJed Brown 16930a96aa3bSJed Brown /* 4: visit every vertex */ 16940a96aa3bSJed Brown conn->ctt_offset[0] = 0; 16950a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 16960a96aa3bSJed Brown PetscInt off, s; 16970a96aa3bSJed Brown 16989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ctt, v, &off)); 16990a96aa3bSJed Brown conn->ctt_offset[v - vStart] = (p4est_topidx_t)off; 17009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 17010a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 17020a96aa3bSJed Brown PetscInt p = star[2 * s]; 17030a96aa3bSJed Brown 17040a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 17059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 170608401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure"); 17070a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 17080a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 17090a96aa3bSJed Brown 17100a96aa3bSJed Brown if (cellVert == v) { 17110a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[c]; 17120a96aa3bSJed Brown 17130a96aa3bSJed Brown conn->corner_to_tree[off] = (p4est_locidx_t)(p - cStart); 17140a96aa3bSJed Brown conn->corner_to_corner[off++] = (int8_t)p4estVert; 17150a96aa3bSJed Brown conn->tree_to_corner[P4EST_CHILDREN * (p - cStart) + p4estVert] = v - vStart; 17160a96aa3bSJed Brown } 17170a96aa3bSJed Brown } 17189566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 17190a96aa3bSJed Brown } 17200a96aa3bSJed Brown } 17219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 17220a96aa3bSJed Brown } 17239566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ctt)); 17240a96aa3bSJed Brown 17250a96aa3bSJed Brown /* 5: Compute the coordinates */ 17260a96aa3bSJed Brown { 17270a96aa3bSJed Brown PetscInt coordDim; 17280a96aa3bSJed Brown 17299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim)); 17306858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 17310a96aa3bSJed Brown for (c = cStart; c < cEnd; c++) { 17320a96aa3bSJed Brown PetscInt dof; 17336858538eSMatthew G. Knepley PetscBool isDG; 17340a96aa3bSJed Brown PetscScalar *cellCoords = NULL; 17356858538eSMatthew G. Knepley const PetscScalar *array; 17360a96aa3bSJed Brown 17376858538eSMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 17386858538eSMatthew G. Knepley PetscCheck(dof == P4EST_CHILDREN * coordDim, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Need coordinates at the corners: (dof) %" PetscInt_FMT " != %d * %" PetscInt_FMT " (sdim)", dof, P4EST_CHILDREN, coordDim); 17390a96aa3bSJed Brown for (v = 0; v < P4EST_CHILDREN; v++) { 17400a96aa3bSJed Brown PetscInt i, lim = PetscMin(3, coordDim); 17410a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[v]; 17420a96aa3bSJed Brown 17430a96aa3bSJed Brown conn->tree_to_vertex[P4EST_CHILDREN * (c - cStart) + v] = P4EST_CHILDREN * (c - cStart) + v; 17440a96aa3bSJed Brown /* p4est vertices are always embedded in R^3 */ 17450a96aa3bSJed Brown for (i = 0; i < 3; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = 0.; 17460a96aa3bSJed Brown for (i = 0; i < lim; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = PetscRealPart(cellCoords[v * coordDim + i]); 17470a96aa3bSJed Brown } 17486858538eSMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 17490a96aa3bSJed Brown } 17500a96aa3bSJed Brown } 17510a96aa3bSJed Brown 17520a96aa3bSJed Brown #if defined(P4EST_ENABLE_DEBUG) 175308401ef6SPierre Jolivet PetscCheck(p4est_connectivity_is_valid(conn), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Plex to p4est conversion failed"); 17540a96aa3bSJed Brown #endif 17550a96aa3bSJed Brown 17560a96aa3bSJed Brown *connOut = conn; 17570a96aa3bSJed Brown 17580a96aa3bSJed Brown *tree_face_to_uniq = ttf; 17590a96aa3bSJed Brown 17600a96aa3bSJed Brown PetscFunctionReturn(0); 17610a96aa3bSJed Brown } 17620a96aa3bSJed Brown 17639371c9d4SSatish Balay static PetscErrorCode locidx_to_PetscInt(sc_array_t *array) { 17640a96aa3bSJed Brown sc_array_t *newarray; 17650a96aa3bSJed Brown size_t zz, count = array->elem_count; 17660a96aa3bSJed Brown 17670a96aa3bSJed Brown PetscFunctionBegin; 176808401ef6SPierre Jolivet PetscCheck(array->elem_size == sizeof(p4est_locidx_t), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong locidx size"); 17690a96aa3bSJed Brown 17700a96aa3bSJed Brown if (sizeof(p4est_locidx_t) == sizeof(PetscInt)) PetscFunctionReturn(0); 17710a96aa3bSJed Brown 17720a96aa3bSJed Brown newarray = sc_array_new_size(sizeof(PetscInt), array->elem_count); 17730a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 17740a96aa3bSJed Brown p4est_locidx_t il = *((p4est_locidx_t *)sc_array_index(array, zz)); 17750a96aa3bSJed Brown PetscInt *ip = (PetscInt *)sc_array_index(newarray, zz); 17760a96aa3bSJed Brown 17770a96aa3bSJed Brown *ip = (PetscInt)il; 17780a96aa3bSJed Brown } 17790a96aa3bSJed Brown 17800a96aa3bSJed Brown sc_array_reset(array); 17810a96aa3bSJed Brown sc_array_init_size(array, sizeof(PetscInt), count); 17820a96aa3bSJed Brown sc_array_copy(array, newarray); 17830a96aa3bSJed Brown sc_array_destroy(newarray); 17840a96aa3bSJed Brown PetscFunctionReturn(0); 17850a96aa3bSJed Brown } 17860a96aa3bSJed Brown 17879371c9d4SSatish Balay static PetscErrorCode coords_double_to_PetscScalar(sc_array_t *array, PetscInt dim) { 17880a96aa3bSJed Brown sc_array_t *newarray; 17890a96aa3bSJed Brown size_t zz, count = array->elem_count; 17900a96aa3bSJed Brown 17910a96aa3bSJed Brown PetscFunctionBegin; 17921dca8a05SBarry Smith PetscCheck(array->elem_size == 3 * sizeof(double), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong coordinate size"); 17930a96aa3bSJed Brown #if !defined(PETSC_USE_COMPLEX) 17940a96aa3bSJed Brown if (sizeof(double) == sizeof(PetscScalar) && dim == 3) PetscFunctionReturn(0); 17950a96aa3bSJed Brown #endif 17960a96aa3bSJed Brown 17970a96aa3bSJed Brown newarray = sc_array_new_size(dim * sizeof(PetscScalar), array->elem_count); 17980a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 17990a96aa3bSJed Brown int i; 18000a96aa3bSJed Brown double *id = (double *)sc_array_index(array, zz); 18010a96aa3bSJed Brown PetscScalar *ip = (PetscScalar *)sc_array_index(newarray, zz); 18020a96aa3bSJed Brown 18030a96aa3bSJed Brown for (i = 0; i < dim; i++) ip[i] = 0.; 18040a96aa3bSJed Brown for (i = 0; i < PetscMin(dim, 3); i++) ip[i] = (PetscScalar)id[i]; 18050a96aa3bSJed Brown } 18060a96aa3bSJed Brown 18070a96aa3bSJed Brown sc_array_reset(array); 18080a96aa3bSJed Brown sc_array_init_size(array, dim * sizeof(PetscScalar), count); 18090a96aa3bSJed Brown sc_array_copy(array, newarray); 18100a96aa3bSJed Brown sc_array_destroy(newarray); 18110a96aa3bSJed Brown PetscFunctionReturn(0); 18120a96aa3bSJed Brown } 18130a96aa3bSJed Brown 18149371c9d4SSatish Balay static PetscErrorCode locidx_pair_to_PetscSFNode(sc_array_t *array) { 18150a96aa3bSJed Brown sc_array_t *newarray; 18160a96aa3bSJed Brown size_t zz, count = array->elem_count; 18170a96aa3bSJed Brown 18180a96aa3bSJed Brown PetscFunctionBegin; 18191dca8a05SBarry Smith PetscCheck(array->elem_size == 2 * sizeof(p4est_locidx_t), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong locidx size"); 18200a96aa3bSJed Brown 18210a96aa3bSJed Brown newarray = sc_array_new_size(sizeof(PetscSFNode), array->elem_count); 18220a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18230a96aa3bSJed Brown p4est_locidx_t *il = (p4est_locidx_t *)sc_array_index(array, zz); 18240a96aa3bSJed Brown PetscSFNode *ip = (PetscSFNode *)sc_array_index(newarray, zz); 18250a96aa3bSJed Brown 18260a96aa3bSJed Brown ip->rank = (PetscInt)il[0]; 18270a96aa3bSJed Brown ip->index = (PetscInt)il[1]; 18280a96aa3bSJed Brown } 18290a96aa3bSJed Brown 18300a96aa3bSJed Brown sc_array_reset(array); 18310a96aa3bSJed Brown sc_array_init_size(array, sizeof(PetscSFNode), count); 18320a96aa3bSJed Brown sc_array_copy(array, newarray); 18330a96aa3bSJed Brown sc_array_destroy(newarray); 18340a96aa3bSJed Brown PetscFunctionReturn(0); 18350a96aa3bSJed Brown } 18360a96aa3bSJed Brown 18379371c9d4SSatish Balay static PetscErrorCode P4estToPlex_Local(p4est_t *p4est, DM *plex) { 18380a96aa3bSJed Brown PetscFunctionBegin; 18390a96aa3bSJed Brown { 18400a96aa3bSJed Brown sc_array_t *points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 18410a96aa3bSJed Brown sc_array_t *cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 18420a96aa3bSJed Brown sc_array_t *cones = sc_array_new(sizeof(p4est_locidx_t)); 18430a96aa3bSJed Brown sc_array_t *cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 18440a96aa3bSJed Brown sc_array_t *coords = sc_array_new(3 * sizeof(double)); 18450a96aa3bSJed Brown sc_array_t *children = sc_array_new(sizeof(p4est_locidx_t)); 18460a96aa3bSJed Brown sc_array_t *parents = sc_array_new(sizeof(p4est_locidx_t)); 18470a96aa3bSJed Brown sc_array_t *childids = sc_array_new(sizeof(p4est_locidx_t)); 18480a96aa3bSJed Brown sc_array_t *leaves = sc_array_new(sizeof(p4est_locidx_t)); 18490a96aa3bSJed Brown sc_array_t *remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 18500a96aa3bSJed Brown p4est_locidx_t first_local_quad; 18510a96aa3bSJed Brown 1852792fecdfSBarry Smith PetscCallP4est(p4est_get_plex_data, (p4est, P4EST_CONNECT_FULL, 0, &first_local_quad, points_per_dim, cone_sizes, cones, cone_orientations, coords, children, parents, childids, leaves, remotes)); 18530a96aa3bSJed Brown 18549566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 18559566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 18569566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 18579566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 18589566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, P4EST_DIM)); 18590a96aa3bSJed Brown 18609566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PETSC_COMM_SELF, plex)); 18619566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*plex, P4EST_DIM)); 18629566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*plex, P4EST_DIM, (PetscInt *)points_per_dim->array, (PetscInt *)cone_sizes->array, (PetscInt *)cones->array, (PetscInt *)cone_orientations->array, (PetscScalar *)coords->array)); 18639566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(*plex)); 18640a96aa3bSJed Brown sc_array_destroy(points_per_dim); 18650a96aa3bSJed Brown sc_array_destroy(cone_sizes); 18660a96aa3bSJed Brown sc_array_destroy(cones); 18670a96aa3bSJed Brown sc_array_destroy(cone_orientations); 18680a96aa3bSJed Brown sc_array_destroy(coords); 18690a96aa3bSJed Brown sc_array_destroy(children); 18700a96aa3bSJed Brown sc_array_destroy(parents); 18710a96aa3bSJed Brown sc_array_destroy(childids); 18720a96aa3bSJed Brown sc_array_destroy(leaves); 18730a96aa3bSJed Brown sc_array_destroy(remotes); 18740a96aa3bSJed Brown } 18750a96aa3bSJed Brown PetscFunctionReturn(0); 18760a96aa3bSJed Brown } 18770a96aa3bSJed Brown 18780a96aa3bSJed Brown #define DMReferenceTreeGetChildSymmetry_pforest _append_pforest(DMReferenceTreeGetChildSymmetry) 18799371c9d4SSatish Balay static PetscErrorCode DMReferenceTreeGetChildSymmetry_pforest(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) { 18800a96aa3bSJed Brown PetscInt coneSize, dStart, dEnd, vStart, vEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 18810a96aa3bSJed Brown 18820a96aa3bSJed Brown PetscFunctionBegin; 18830a96aa3bSJed Brown if (parentOrientA == parentOrientB) { 18840a96aa3bSJed Brown if (childOrientB) *childOrientB = childOrientA; 18850a96aa3bSJed Brown if (childB) *childB = childA; 18860a96aa3bSJed Brown PetscFunctionReturn(0); 18870a96aa3bSJed Brown } 18889566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 18896aad120cSJose E. Roman if (childA >= vStart && childA < vEnd) { /* vertices (always in the middle) are invariant under rotation */ 18900a96aa3bSJed Brown if (childOrientB) *childOrientB = 0; 18910a96aa3bSJed Brown if (childB) *childB = childA; 18920a96aa3bSJed Brown PetscFunctionReturn(0); 18930a96aa3bSJed Brown } 18940a96aa3bSJed Brown for (dim = 0; dim < 3; dim++) { 18959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, &dStart, &dEnd)); 18960a96aa3bSJed Brown if (parent >= dStart && parent <= dEnd) break; 18970a96aa3bSJed Brown } 189863a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot perform child symmetry for %" PetscInt_FMT "-cells", dim); 189928b400f6SJacob Faibussowitsch PetscCheck(dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "A vertex has no children"); 19000a96aa3bSJed Brown if (childA < dStart || childA >= dEnd) { /* a 1-cell in a 2-cell */ 19010a96aa3bSJed Brown /* this is a lower-dimensional child: bootstrap */ 19020a96aa3bSJed Brown PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 19030a96aa3bSJed Brown const PetscInt *supp, *coneA, *coneB, *oA, *oB; 19040a96aa3bSJed Brown 19059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, childA, &size)); 19069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, childA, &supp)); 19070a96aa3bSJed Brown 19080a96aa3bSJed Brown /* find a point sA in supp(childA) that has the same parent */ 19090a96aa3bSJed Brown for (i = 0; i < size; i++) { 19100a96aa3bSJed Brown PetscInt sParent; 19110a96aa3bSJed Brown 19120a96aa3bSJed Brown sA = supp[i]; 19130a96aa3bSJed Brown if (sA == parent) continue; 19149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, sA, &sParent, NULL)); 19150a96aa3bSJed Brown if (sParent == parent) break; 19160a96aa3bSJed Brown } 191708401ef6SPierre Jolivet PetscCheck(i != size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "could not find support in children"); 19180a96aa3bSJed Brown /* find out which point sB is in an equivalent position to sA under 19190a96aa3bSJed Brown * parentOrientB */ 19209566063dSJacob Faibussowitsch PetscCall(DMReferenceTreeGetChildSymmetry_pforest(dm, parent, parentOrientA, 0, sA, parentOrientB, &sOrientB, &sB)); 19219566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, sA, &sConeSize)); 19229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sA, &coneA)); 19239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sB, &coneB)); 19249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sA, &oA)); 19259566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sB, &oB)); 19260a96aa3bSJed Brown /* step through the cone of sA in natural order */ 19270a96aa3bSJed Brown for (i = 0; i < sConeSize; i++) { 19280a96aa3bSJed Brown if (coneA[i] == childA) { 19290a96aa3bSJed Brown /* if childA is at position i in coneA, 19300a96aa3bSJed Brown * then we want the point that is at sOrientB*i in coneB */ 19310a96aa3bSJed Brown PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize - (sOrientB + 1) - i) % sConeSize); 19320a96aa3bSJed Brown if (childB) *childB = coneB[j]; 19330a96aa3bSJed Brown if (childOrientB) { 19340a96aa3bSJed Brown DMPolytopeType ct; 19350a96aa3bSJed Brown PetscInt oBtrue; 19360a96aa3bSJed Brown 19379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, childA, &coneSize)); 19380a96aa3bSJed Brown /* compose sOrientB and oB[j] */ 19391dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected a vertex or an edge"); 19400a96aa3bSJed Brown ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 19410a96aa3bSJed Brown /* we may have to flip an edge */ 19420a96aa3bSJed Brown oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientationInv(ct, -1, oB[j]); 19430a96aa3bSJed Brown oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 19440a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, DMPolytopeConvertNewOrientation_Internal(ct, oA[i]), oBtrue); 19450a96aa3bSJed Brown *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 19460a96aa3bSJed Brown } 19470a96aa3bSJed Brown break; 19480a96aa3bSJed Brown } 19490a96aa3bSJed Brown } 195008401ef6SPierre Jolivet PetscCheck(i != sConeSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "support cone mismatch"); 19510a96aa3bSJed Brown PetscFunctionReturn(0); 19520a96aa3bSJed Brown } 19530a96aa3bSJed Brown /* get the cone size and symmetry swap */ 19549566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 19550a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 19560a96aa3bSJed Brown if (dim == 2) { 19570a96aa3bSJed Brown /* orientations refer to cones: we want them to refer to vertices: 19580a96aa3bSJed Brown * if it's a rotation, they are the same, but if the order is reversed, a 19590a96aa3bSJed Brown * permutation that puts side i first does *not* put vertex i first */ 19600a96aa3bSJed Brown oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 19610a96aa3bSJed Brown oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 19620a96aa3bSJed Brown ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 19630a96aa3bSJed Brown } else { 19640a96aa3bSJed Brown oAvert = parentOrientA; 19650a96aa3bSJed Brown oBvert = parentOrientB; 19660a96aa3bSJed Brown ABswapVert = ABswap; 19670a96aa3bSJed Brown } 19680a96aa3bSJed Brown if (childB) { 19690a96aa3bSJed Brown /* assume that each child corresponds to a vertex, in the same order */ 19700a96aa3bSJed Brown PetscInt p, posA = -1, numChildren, i; 19710a96aa3bSJed Brown const PetscInt *children; 19720a96aa3bSJed Brown 19730a96aa3bSJed Brown /* count which position the child is in */ 19749566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, parent, &numChildren, &children)); 19750a96aa3bSJed Brown for (i = 0; i < numChildren; i++) { 19760a96aa3bSJed Brown p = children[i]; 19770a96aa3bSJed Brown if (p == childA) { 19780a96aa3bSJed Brown if (dim == 1) { 19790a96aa3bSJed Brown posA = i; 19800a96aa3bSJed Brown } else { /* 2D Morton to rotation */ 19810a96aa3bSJed Brown posA = (i & 2) ? (i ^ 1) : i; 19820a96aa3bSJed Brown } 19830a96aa3bSJed Brown break; 19840a96aa3bSJed Brown } 19850a96aa3bSJed Brown } 19860a96aa3bSJed Brown if (posA >= coneSize) { 19870a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find childA in children of parent"); 19880a96aa3bSJed Brown } else { 19890a96aa3bSJed Brown /* figure out position B by applying ABswapVert */ 19900a96aa3bSJed Brown PetscInt posB, childIdB; 19910a96aa3bSJed Brown 19920a96aa3bSJed Brown posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize - (ABswapVert + 1) - posA) % coneSize); 19930a96aa3bSJed Brown if (dim == 1) { 19940a96aa3bSJed Brown childIdB = posB; 19950a96aa3bSJed Brown } else { /* 2D rotation to Morton */ 19960a96aa3bSJed Brown childIdB = (posB & 2) ? (posB ^ 1) : posB; 19970a96aa3bSJed Brown } 19980a96aa3bSJed Brown if (childB) *childB = children[childIdB]; 19990a96aa3bSJed Brown } 20000a96aa3bSJed Brown } 20010a96aa3bSJed Brown if (childOrientB) *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 20020a96aa3bSJed Brown PetscFunctionReturn(0); 20030a96aa3bSJed Brown } 20040a96aa3bSJed Brown 20050a96aa3bSJed Brown #define DMCreateReferenceTree_pforest _append_pforest(DMCreateReferenceTree) 20069371c9d4SSatish Balay static PetscErrorCode DMCreateReferenceTree_pforest(MPI_Comm comm, DM *dm) { 20070a96aa3bSJed Brown p4est_connectivity_t *refcube; 20080a96aa3bSJed Brown p4est_t *root, *refined; 20090a96aa3bSJed Brown DM dmRoot, dmRefined; 20100a96aa3bSJed Brown DM_Plex *mesh; 20110a96aa3bSJed Brown PetscMPIInt rank; 201266c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI) 201366c0a4b5SToby Isaac sc_MPI_Comm comm_self = sc_MPI_COMM_SELF; 201466c0a4b5SToby Isaac #else 201566c0a4b5SToby Isaac MPI_Comm comm_self = PETSC_COMM_SELF; 201666c0a4b5SToby Isaac #endif 20170a96aa3bSJed Brown 20180a96aa3bSJed Brown PetscFunctionBegin; 2019792fecdfSBarry Smith PetscCallP4estReturn(refcube, p4est_connectivity_new_byname, ("unit")); 20200a96aa3bSJed Brown { /* [-1,1]^d geometry */ 20210a96aa3bSJed Brown PetscInt i, j; 20220a96aa3bSJed Brown 20230a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 20240a96aa3bSJed Brown for (j = 0; j < 3; j++) { 20250a96aa3bSJed Brown refcube->vertices[3 * i + j] *= 2.; 20260a96aa3bSJed Brown refcube->vertices[3 * i + j] -= 1.; 20270a96aa3bSJed Brown } 20280a96aa3bSJed Brown } 20290a96aa3bSJed Brown } 2030792fecdfSBarry Smith PetscCallP4estReturn(root, p4est_new, (comm_self, refcube, 0, NULL, NULL)); 2031792fecdfSBarry Smith PetscCallP4estReturn(refined, p4est_new_ext, (comm_self, refcube, 0, 1, 1, 0, NULL, NULL)); 20329566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(root, &dmRoot)); 20339566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(refined, &dmRefined)); 20340a96aa3bSJed Brown { 20350a96aa3bSJed Brown #if !defined(P4_TO_P8) 20360a96aa3bSJed Brown PetscInt nPoints = 25; 20379371c9d4SSatish Balay PetscInt perm[25] = {0, 1, 2, 3, 4, 12, 8, 14, 6, 9, 15, 5, 13, 10, 7, 11, 16, 22, 20, 24, 17, 21, 18, 23, 19}; 20389371c9d4SSatish Balay PetscInt ident[25] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 0, 5, 6, 7, 8, 1, 2, 3, 4, 0}; 20390a96aa3bSJed Brown #else 20400a96aa3bSJed Brown PetscInt nPoints = 125; 20419371c9d4SSatish Balay PetscInt perm[125] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 32, 16, 36, 24, 40, 12, 17, 37, 25, 41, 9, 33, 20, 26, 42, 13, 21, 27, 43, 10, 34, 18, 38, 28, 14, 19, 39, 29, 11, 35, 22, 30, 15, 20429371c9d4SSatish Balay 23, 31, 44, 84, 76, 92, 52, 86, 68, 94, 60, 78, 70, 96, 45, 85, 77, 93, 54, 72, 62, 74, 46, 80, 53, 87, 69, 95, 64, 82, 47, 81, 55, 73, 66, 48, 88, 56, 90, 61, 79, 71, 20439371c9d4SSatish Balay 97, 49, 89, 58, 63, 75, 50, 57, 91, 65, 83, 51, 59, 67, 98, 106, 110, 122, 114, 120, 118, 124, 99, 111, 115, 119, 100, 107, 116, 121, 101, 117, 102, 108, 112, 123, 103, 113, 104, 109, 105}; 20449371c9d4SSatish Balay PetscInt ident[125] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 20459371c9d4SSatish Balay 16, 17, 17, 18, 18, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 19, 20, 21, 22, 23, 24, 25, 26, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1, 2, 3, 4, 5, 6, 0}; 20460a96aa3bSJed Brown 20470a96aa3bSJed Brown #endif 20480a96aa3bSJed Brown IS permIS; 20490a96aa3bSJed Brown DM dmPerm; 20500a96aa3bSJed Brown 20519566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nPoints, perm, PETSC_USE_POINTER, &permIS)); 20529566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dmRefined, permIS, &dmPerm)); 20530a96aa3bSJed Brown if (dmPerm) { 20549566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 20550a96aa3bSJed Brown dmRefined = dmPerm; 20560a96aa3bSJed Brown } 20579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 20580a96aa3bSJed Brown { 20590a96aa3bSJed Brown PetscInt p; 20609566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRoot, "identity")); 20619566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRefined, "identity")); 206248a46eb9SPierre Jolivet for (p = 0; p < P4EST_INSUL; p++) PetscCall(DMSetLabelValue(dmRoot, "identity", p, p)); 206348a46eb9SPierre Jolivet for (p = 0; p < nPoints; p++) PetscCall(DMSetLabelValue(dmRefined, "identity", p, ident[p])); 20640a96aa3bSJed Brown } 20650a96aa3bSJed Brown } 20669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(dmRoot, dmRefined, "identity", dm)); 20670a96aa3bSJed Brown mesh = (DM_Plex *)(*dm)->data; 20680a96aa3bSJed Brown mesh->getchildsymmetry = DMReferenceTreeGetChildSymmetry_pforest; 20699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 20700a96aa3bSJed Brown if (rank == 0) { 20719566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRoot, NULL, "-dm_p4est_ref_root_view")); 20729566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined, NULL, "-dm_p4est_ref_refined_view")); 20739566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined, NULL, "-dm_p4est_ref_tree_view")); 20740a96aa3bSJed Brown } 20759566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 20769566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRoot)); 2077792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (refined)); 2078792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (root)); 2079792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy, (refcube)); 20800a96aa3bSJed Brown PetscFunctionReturn(0); 20810a96aa3bSJed Brown } 20820a96aa3bSJed Brown 20839371c9d4SSatish Balay static PetscErrorCode DMShareDiscretization(DM dmA, DM dmB) { 20840a96aa3bSJed Brown void *ctx; 20850a96aa3bSJed Brown PetscInt num; 20860a96aa3bSJed Brown PetscReal val; 20870a96aa3bSJed Brown 20880a96aa3bSJed Brown PetscFunctionBegin; 20899566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmA, &ctx)); 20909566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(dmB, ctx)); 20919566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmA, dmB)); 20929566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dmA, &num, &val)); 20939566063dSJacob Faibussowitsch PetscCall(DMSetOutputSequenceNumber(dmB, num, val)); 20940a96aa3bSJed Brown if (dmB->localSection != dmA->localSection || dmB->globalSection != dmA->globalSection) { 20959566063dSJacob Faibussowitsch PetscCall(DMClearLocalVectors(dmB)); 20969566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->localSection)); 20979566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->localSection))); 20980a96aa3bSJed Brown dmB->localSection = dmA->localSection; 20999566063dSJacob Faibussowitsch PetscCall(DMClearGlobalVectors(dmB)); 21009566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->globalSection)); 21019566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->globalSection))); 21020a96aa3bSJed Brown dmB->globalSection = dmA->globalSection; 21039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.section)); 21049566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->defaultConstraint.section))); 21053b8ba7d1SJed Brown dmB->defaultConstraint.section = dmA->defaultConstraint.section; 21069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.mat)); 21079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(dmB->defaultConstraint.mat))); 21083b8ba7d1SJed Brown dmB->defaultConstraint.mat = dmA->defaultConstraint.mat; 21099566063dSJacob Faibussowitsch if (dmA->map) PetscCall(PetscLayoutReference(dmA->map, &dmB->map)); 21100a96aa3bSJed Brown } 21110a96aa3bSJed Brown if (dmB->sectionSF != dmA->sectionSF) { 21129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->sectionSF)); 21139566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&dmB->sectionSF)); 21140a96aa3bSJed Brown dmB->sectionSF = dmA->sectionSF; 21150a96aa3bSJed Brown } 21160a96aa3bSJed Brown PetscFunctionReturn(0); 21170a96aa3bSJed Brown } 21180a96aa3bSJed Brown 21190a96aa3bSJed Brown /* Get an SF that broadcasts a coarse-cell covering of the local fine cells */ 21209371c9d4SSatish Balay static PetscErrorCode DMPforestGetCellCoveringSF(MPI_Comm comm, p4est_t *p4estC, p4est_t *p4estF, PetscInt cStart, PetscInt cEnd, PetscSF *coveringSF) { 21210a96aa3bSJed Brown PetscInt startF, endF, startC, endC, p, nLeaves; 21220a96aa3bSJed Brown PetscSFNode *leaves; 21230a96aa3bSJed Brown PetscSF sf; 21240a96aa3bSJed Brown PetscInt *recv, *send; 21250a96aa3bSJed Brown PetscMPIInt tag; 21260a96aa3bSJed Brown MPI_Request *recvReqs, *sendReqs; 21270a96aa3bSJed Brown PetscSection section; 21280a96aa3bSJed Brown 21290a96aa3bSJed Brown PetscFunctionBegin; 21309566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize, p4estC->mpirank, p4estF, p4estC, &startC, &endC)); 21319566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2 * (endC - startC), &recv, endC - startC, &recvReqs)); 21329566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(comm, &tag)); 21330a96aa3bSJed Brown for (p = startC; p < endC; p++) { 21340a96aa3bSJed Brown recvReqs[p - startC] = MPI_REQUEST_NULL; /* just in case we don't initiate a receive */ 21350a96aa3bSJed Brown if (p4estC->global_first_quadrant[p] == p4estC->global_first_quadrant[p + 1]) { /* empty coarse partition */ 21360a96aa3bSJed Brown recv[2 * (p - startC)] = 0; 21370a96aa3bSJed Brown recv[2 * (p - startC) + 1] = 0; 21380a96aa3bSJed Brown continue; 21390a96aa3bSJed Brown } 21400a96aa3bSJed Brown 21419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(&recv[2 * (p - startC)], 2, MPIU_INT, p, tag, comm, &recvReqs[p - startC])); 21420a96aa3bSJed Brown } 21439566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize, p4estC->mpirank, p4estC, p4estF, &startF, &endF)); 21449566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2 * (endF - startF), &send, endF - startF, &sendReqs)); 21450a96aa3bSJed Brown /* count the quadrants rank will send to each of [startF,endF) */ 21460a96aa3bSJed Brown for (p = startF; p < endF; p++) { 21470a96aa3bSJed Brown p4est_quadrant_t *myFineStart = &p4estF->global_first_position[p]; 21480a96aa3bSJed Brown p4est_quadrant_t *myFineEnd = &p4estF->global_first_position[p + 1]; 21490a96aa3bSJed Brown PetscInt tStart = (PetscInt)myFineStart->p.which_tree; 21500a96aa3bSJed Brown PetscInt tEnd = (PetscInt)myFineEnd->p.which_tree; 21510a96aa3bSJed Brown PetscInt firstCell = -1, lastCell = -1; 21520a96aa3bSJed Brown p4est_tree_t *treeStart = &(((p4est_tree_t *)p4estC->trees->array)[tStart]); 21530a96aa3bSJed Brown p4est_tree_t *treeEnd = (size_t)tEnd < p4estC->trees->elem_count ? &(((p4est_tree_t *)p4estC->trees->array)[tEnd]) : NULL; 21540a96aa3bSJed Brown ssize_t overlapIndex; 21550a96aa3bSJed Brown 21560a96aa3bSJed Brown sendReqs[p - startF] = MPI_REQUEST_NULL; /* just in case we don't initiate a send */ 21570a96aa3bSJed Brown if (p4estF->global_first_quadrant[p] == p4estF->global_first_quadrant[p + 1]) continue; 21580a96aa3bSJed Brown 21590a96aa3bSJed Brown /* locate myFineStart in (or before) a cell */ 21600a96aa3bSJed Brown if (treeStart->quadrants.elem_count) { 2161792fecdfSBarry Smith PetscCallP4estReturn(overlapIndex, sc_array_bsearch, (&(treeStart->quadrants), myFineStart, p4est_quadrant_disjoint)); 21620a96aa3bSJed Brown if (overlapIndex < 0) { 21630a96aa3bSJed Brown firstCell = 0; 21640a96aa3bSJed Brown } else { 21650a96aa3bSJed Brown firstCell = treeStart->quadrants_offset + overlapIndex; 21660a96aa3bSJed Brown } 21670a96aa3bSJed Brown } else { 21680a96aa3bSJed Brown firstCell = 0; 21690a96aa3bSJed Brown } 21700a96aa3bSJed Brown if (treeEnd && treeEnd->quadrants.elem_count) { 2171792fecdfSBarry Smith PetscCallP4estReturn(overlapIndex, sc_array_bsearch, (&(treeEnd->quadrants), myFineEnd, p4est_quadrant_disjoint)); 21720a96aa3bSJed Brown if (overlapIndex < 0) { /* all of this local section is overlapped */ 21730a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 21740a96aa3bSJed Brown } else { 21750a96aa3bSJed Brown p4est_quadrant_t *container = &(((p4est_quadrant_t *)treeEnd->quadrants.array)[overlapIndex]); 21760a96aa3bSJed Brown p4est_quadrant_t first_desc; 21770a96aa3bSJed Brown int equal; 21780a96aa3bSJed Brown 2179792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_first_descendant, (container, &first_desc, P4EST_QMAXLEVEL)); 2180792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal, (myFineEnd, &first_desc)); 21810a96aa3bSJed Brown if (equal) { 21820a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex; 21830a96aa3bSJed Brown } else { 21840a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex + 1; 21850a96aa3bSJed Brown } 21860a96aa3bSJed Brown } 21870a96aa3bSJed Brown } else { 21880a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 21890a96aa3bSJed Brown } 21900a96aa3bSJed Brown send[2 * (p - startF)] = firstCell; 21910a96aa3bSJed Brown send[2 * (p - startF) + 1] = lastCell - firstCell; 21929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(&send[2 * (p - startF)], 2, MPIU_INT, p, tag, comm, &sendReqs[p - startF])); 21930a96aa3bSJed Brown } 21949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endC - startC), recvReqs, MPI_STATUSES_IGNORE)); 21959566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 21969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, startC, endC)); 21970a96aa3bSJed Brown for (p = startC; p < endC; p++) { 21980a96aa3bSJed Brown PetscInt numCells = recv[2 * (p - startC) + 1]; 21999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, numCells)); 22000a96aa3bSJed Brown } 22019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 22029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &nLeaves)); 22039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &leaves)); 22040a96aa3bSJed Brown for (p = startC; p < endC; p++) { 22050a96aa3bSJed Brown PetscInt firstCell = recv[2 * (p - startC)]; 22060a96aa3bSJed Brown PetscInt numCells = recv[2 * (p - startC) + 1]; 22070a96aa3bSJed Brown PetscInt off, i; 22080a96aa3bSJed Brown 22099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 22100a96aa3bSJed Brown for (i = 0; i < numCells; i++) { 22110a96aa3bSJed Brown leaves[off + i].rank = p; 22120a96aa3bSJed Brown leaves[off + i].index = firstCell + i; 22130a96aa3bSJed Brown } 22140a96aa3bSJed Brown } 22159566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sf)); 22169566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, cEnd - cStart, nLeaves, NULL, PETSC_OWN_POINTER, leaves, PETSC_OWN_POINTER)); 22179566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 22189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endF - startF), sendReqs, MPI_STATUSES_IGNORE)); 22199566063dSJacob Faibussowitsch PetscCall(PetscFree2(send, sendReqs)); 22209566063dSJacob Faibussowitsch PetscCall(PetscFree2(recv, recvReqs)); 22210a96aa3bSJed Brown *coveringSF = sf; 22220a96aa3bSJed Brown PetscFunctionReturn(0); 22230a96aa3bSJed Brown } 22240a96aa3bSJed Brown 22250a96aa3bSJed Brown /* closure points for locally-owned cells */ 22269371c9d4SSatish Balay static PetscErrorCode DMPforestGetCellSFNodes(DM dm, PetscInt numClosureIndices, PetscInt *numClosurePoints, PetscSFNode **closurePoints, PetscBool redirect) { 22270a96aa3bSJed Brown PetscInt cStart, cEnd; 22280a96aa3bSJed Brown PetscInt count, c; 22290a96aa3bSJed Brown PetscMPIInt rank; 22300a96aa3bSJed Brown PetscInt closureSize = -1; 22310a96aa3bSJed Brown PetscInt *closure = NULL; 22320a96aa3bSJed Brown PetscSF pointSF; 22330a96aa3bSJed Brown PetscInt nleaves, nroots; 22340a96aa3bSJed Brown const PetscInt *ilocal; 22350a96aa3bSJed Brown const PetscSFNode *iremote; 22360a96aa3bSJed Brown DM plex; 22370a96aa3bSJed Brown DM_Forest *forest; 22380a96aa3bSJed Brown DM_Forest_pforest *pforest; 22390a96aa3bSJed Brown 22400a96aa3bSJed Brown PetscFunctionBegin; 22410a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 22420a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 22430a96aa3bSJed Brown cStart = pforest->cLocalStart; 22440a96aa3bSJed Brown cEnd = pforest->cLocalEnd; 22459566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 22469566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &pointSF)); 22479566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &ilocal, &iremote)); 22480a96aa3bSJed Brown nleaves = PetscMax(0, nleaves); 22490a96aa3bSJed Brown nroots = PetscMax(0, nroots); 22500a96aa3bSJed Brown *numClosurePoints = numClosureIndices * (cEnd - cStart); 22519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numClosurePoints, closurePoints)); 22529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 22530a96aa3bSJed Brown for (c = cStart, count = 0; c < cEnd; c++) { 22540a96aa3bSJed Brown PetscInt i; 22559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, c, PETSC_TRUE, &closureSize, &closure)); 22560a96aa3bSJed Brown 22570a96aa3bSJed Brown for (i = 0; i < numClosureIndices; i++, count++) { 22580a96aa3bSJed Brown PetscInt p = closure[2 * i]; 22590a96aa3bSJed Brown PetscInt loc = -1; 22600a96aa3bSJed Brown 22619566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p, nleaves, ilocal, &loc)); 22620a96aa3bSJed Brown if (redirect && loc >= 0) { 22630a96aa3bSJed Brown (*closurePoints)[count].rank = iremote[loc].rank; 22640a96aa3bSJed Brown (*closurePoints)[count].index = iremote[loc].index; 22650a96aa3bSJed Brown } else { 22660a96aa3bSJed Brown (*closurePoints)[count].rank = rank; 22670a96aa3bSJed Brown (*closurePoints)[count].index = p; 22680a96aa3bSJed Brown } 22690a96aa3bSJed Brown } 22709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, c, PETSC_TRUE, &closureSize, &closure)); 22710a96aa3bSJed Brown } 22720a96aa3bSJed Brown PetscFunctionReturn(0); 22730a96aa3bSJed Brown } 22740a96aa3bSJed Brown 22759371c9d4SSatish Balay static void MPIAPI DMPforestMaxSFNode(void *a, void *b, PetscMPIInt *len, MPI_Datatype *type) { 22760a96aa3bSJed Brown PetscMPIInt i; 22770a96aa3bSJed Brown 22780a96aa3bSJed Brown for (i = 0; i < *len; i++) { 22790a96aa3bSJed Brown PetscSFNode *A = (PetscSFNode *)a; 22800a96aa3bSJed Brown PetscSFNode *B = (PetscSFNode *)b; 22810a96aa3bSJed Brown 22820a96aa3bSJed Brown if (B->rank < 0) *B = *A; 22830a96aa3bSJed Brown } 22840a96aa3bSJed Brown } 22850a96aa3bSJed Brown 22869371c9d4SSatish Balay static PetscErrorCode DMPforestGetTransferSF_Point(DM coarse, DM fine, PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) { 22870a96aa3bSJed Brown MPI_Comm comm; 22880a96aa3bSJed Brown PetscMPIInt rank, size; 22890a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 22900a96aa3bSJed Brown p4est_t *p4estC, *p4estF; 22910a96aa3bSJed Brown PetscInt numClosureIndices; 22920a96aa3bSJed Brown PetscInt numClosurePointsC, numClosurePointsF; 22930a96aa3bSJed Brown PetscSFNode *closurePointsC, *closurePointsF; 22940a96aa3bSJed Brown p4est_quadrant_t *coverQuads = NULL; 22950a96aa3bSJed Brown p4est_quadrant_t **treeQuads; 22960a96aa3bSJed Brown PetscInt *treeQuadCounts; 22970a96aa3bSJed Brown MPI_Datatype nodeType; 22980a96aa3bSJed Brown MPI_Datatype nodeClosureType; 22990a96aa3bSJed Brown MPI_Op sfNodeReduce; 23000a96aa3bSJed Brown p4est_topidx_t fltF, lltF, t; 23010a96aa3bSJed Brown DM plexC, plexF; 23020a96aa3bSJed Brown PetscInt pStartF, pEndF, pStartC, pEndC; 23030a96aa3bSJed Brown PetscBool saveInCoarse = PETSC_FALSE; 23040a96aa3bSJed Brown PetscBool saveInFine = PETSC_FALSE; 23050a96aa3bSJed Brown PetscBool formCids = (childIds != NULL) ? PETSC_TRUE : PETSC_FALSE; 23060a96aa3bSJed Brown PetscInt *cids = NULL; 23070a96aa3bSJed Brown 23080a96aa3bSJed Brown PetscFunctionBegin; 23090a96aa3bSJed Brown pforestC = (DM_Forest_pforest *)((DM_Forest *)coarse->data)->data; 23100a96aa3bSJed Brown pforestF = (DM_Forest_pforest *)((DM_Forest *)fine->data)->data; 23110a96aa3bSJed Brown p4estC = pforestC->forest; 23120a96aa3bSJed Brown p4estF = pforestF->forest; 231308401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo, PetscObjectComm((PetscObject)coarse), PETSC_ERR_ARG_INCOMP, "DM's must have the same base DM"); 23140a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 23159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 23169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 23179566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine, &plexF)); 23189566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF, &pStartF, &pEndF)); 23199566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse, &plexC)); 23209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC, &pStartC, &pEndC)); 23210a96aa3bSJed Brown { /* check if the results have been cached */ 23220a96aa3bSJed Brown DM adaptCoarse, adaptFine; 23230a96aa3bSJed Brown 23249566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(coarse, &adaptCoarse)); 23259566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(fine, &adaptFine)); 23260a96aa3bSJed Brown if (adaptCoarse && adaptCoarse->data == fine->data) { /* coarse is adapted from fine */ 23270a96aa3bSJed Brown if (pforestC->pointSelfToAdaptSF) { 23289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(pforestC->pointSelfToAdaptSF))); 23290a96aa3bSJed Brown *sf = pforestC->pointSelfToAdaptSF; 23300a96aa3bSJed Brown if (childIds) { 23319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids)); 23329566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids, pforestC->pointSelfToAdaptCids, pEndF - pStartF)); 23330a96aa3bSJed Brown *childIds = cids; 23340a96aa3bSJed Brown } 23350a96aa3bSJed Brown PetscFunctionReturn(0); 23360a96aa3bSJed Brown } else { 23370a96aa3bSJed Brown saveInCoarse = PETSC_TRUE; 23380a96aa3bSJed Brown formCids = PETSC_TRUE; 23390a96aa3bSJed Brown } 23400a96aa3bSJed Brown } else if (adaptFine && adaptFine->data == coarse->data) { /* fine is adapted from coarse */ 23410a96aa3bSJed Brown if (pforestF->pointAdaptToSelfSF) { 23429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(pforestF->pointAdaptToSelfSF))); 23430a96aa3bSJed Brown *sf = pforestF->pointAdaptToSelfSF; 23440a96aa3bSJed Brown if (childIds) { 23459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids)); 23469566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids, pforestF->pointAdaptToSelfCids, pEndF - pStartF)); 23470a96aa3bSJed Brown *childIds = cids; 23480a96aa3bSJed Brown } 23490a96aa3bSJed Brown PetscFunctionReturn(0); 23500a96aa3bSJed Brown } else { 23510a96aa3bSJed Brown saveInFine = PETSC_TRUE; 23520a96aa3bSJed Brown formCids = PETSC_TRUE; 23530a96aa3bSJed Brown } 23540a96aa3bSJed Brown } 23550a96aa3bSJed Brown } 23560a96aa3bSJed Brown 23570a96aa3bSJed Brown /* count the number of closure points that have dofs and create a list */ 23580a96aa3bSJed Brown numClosureIndices = P4EST_INSUL; 23590a96aa3bSJed Brown /* create the datatype */ 23609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(2, MPIU_INT, &nodeType)); 23619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 23629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(DMPforestMaxSFNode, PETSC_FALSE, &sfNodeReduce)); 23639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(numClosureIndices * 2, MPIU_INT, &nodeClosureType)); 23649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeClosureType)); 23650a96aa3bSJed Brown /* everything has to go through cells: for each cell, create a list of the sfnodes in its closure */ 23660a96aa3bSJed Brown /* get lists of closure point SF nodes for every cell */ 23679566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(coarse, numClosureIndices, &numClosurePointsC, &closurePointsC, PETSC_TRUE)); 23689566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(fine, numClosureIndices, &numClosurePointsF, &closurePointsF, PETSC_FALSE)); 23690a96aa3bSJed Brown /* create pointers for tree lists */ 23700a96aa3bSJed Brown fltF = p4estF->first_local_tree; 23710a96aa3bSJed Brown lltF = p4estF->last_local_tree; 23729566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(lltF + 1 - fltF, &treeQuads, lltF + 1 - fltF, &treeQuadCounts)); 23730a96aa3bSJed Brown /* if the partitions don't match, ship the coarse to cover the fine */ 23740a96aa3bSJed Brown if (size > 1) { 23750a96aa3bSJed Brown PetscInt p; 23760a96aa3bSJed Brown 23770a96aa3bSJed Brown for (p = 0; p < size; p++) { 23780a96aa3bSJed Brown int equal; 23790a96aa3bSJed Brown 2380792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal_piggy, (&p4estC->global_first_position[p], &p4estF->global_first_position[p])); 23810a96aa3bSJed Brown if (!equal) break; 23820a96aa3bSJed Brown } 23830a96aa3bSJed Brown if (p < size) { /* non-matching distribution: send the coarse to cover the fine */ 23840a96aa3bSJed Brown PetscInt cStartC, cEndC; 23850a96aa3bSJed Brown PetscSF coveringSF; 23860a96aa3bSJed Brown PetscInt nleaves; 23870a96aa3bSJed Brown PetscInt count; 23880a96aa3bSJed Brown PetscSFNode *newClosurePointsC; 23890a96aa3bSJed Brown p4est_quadrant_t *coverQuadsSend; 23900a96aa3bSJed Brown p4est_topidx_t fltC = p4estC->first_local_tree; 23910a96aa3bSJed Brown p4est_topidx_t lltC = p4estC->last_local_tree; 23920a96aa3bSJed Brown p4est_topidx_t t; 23930a96aa3bSJed Brown PetscMPIInt blockSizes[4] = {P4EST_DIM, 2, 1, 1}; 23949371c9d4SSatish Balay MPI_Aint blockOffsets[4] = {offsetof(p4est_quadrant_t, x), offsetof(p4est_quadrant_t, level), offsetof(p4est_quadrant_t, pad16), offsetof(p4est_quadrant_t, p)}; 23950a96aa3bSJed Brown MPI_Datatype blockTypes[4] = {MPI_INT32_T, MPI_INT8_T, MPI_INT16_T, MPI_INT32_T /* p.which_tree */}; 23960a96aa3bSJed Brown MPI_Datatype quadStruct, quadType; 23970a96aa3bSJed Brown 23989566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC, 0, &cStartC, &cEndC)); 23999566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellCoveringSF(comm, p4estC, p4estF, pforestC->cLocalStart, pforestC->cLocalEnd, &coveringSF)); 24009566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coveringSF, NULL, &nleaves, NULL, NULL)); 24019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numClosureIndices * nleaves, &newClosurePointsC)); 24029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &coverQuads)); 24039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEndC - cStartC, &coverQuadsSend)); 24040a96aa3bSJed Brown count = 0; 24050a96aa3bSJed Brown for (t = fltC; t <= lltC; t++) { /* unfortunately, we need to pack a send array, since quads are not stored packed in p4est */ 24060a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estC->trees->array)[t]); 24070a96aa3bSJed Brown PetscInt q; 24080a96aa3bSJed Brown 24099566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&coverQuadsSend[count], tree->quadrants.array, tree->quadrants.elem_count * sizeof(p4est_quadrant_t))); 24100a96aa3bSJed Brown for (q = 0; (size_t)q < tree->quadrants.elem_count; q++) coverQuadsSend[count + q].p.which_tree = t; 24110a96aa3bSJed Brown count += tree->quadrants.elem_count; 24120a96aa3bSJed Brown } 24130a96aa3bSJed Brown /* p is of a union type p4est_quadrant_data, but only the p.which_tree field is active at this time. So, we 24140a96aa3bSJed Brown have a simple blockTypes[] to use. Note that quadStruct does not count potential padding in array of 24150a96aa3bSJed Brown p4est_quadrant_t. We have to call MPI_Type_create_resized() to change upper-bound of quadStruct. 24160a96aa3bSJed Brown */ 24179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(4, blockSizes, blockOffsets, blockTypes, &quadStruct)); 24189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_resized(quadStruct, 0, sizeof(p4est_quadrant_t), &quadType)); 24199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&quadType)); 24209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF, nodeClosureType, closurePointsC, newClosurePointsC, MPI_REPLACE)); 24219566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF, quadType, coverQuadsSend, coverQuads, MPI_REPLACE)); 24229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF, nodeClosureType, closurePointsC, newClosurePointsC, MPI_REPLACE)); 24239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF, quadType, coverQuadsSend, coverQuads, MPI_REPLACE)); 24249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadStruct)); 24259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadType)); 24269566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuadsSend)); 24279566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 24289566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coveringSF)); 24290a96aa3bSJed Brown closurePointsC = newClosurePointsC; 24300a96aa3bSJed Brown 24310a96aa3bSJed Brown /* assign tree quads based on locations in coverQuads */ 24320a96aa3bSJed Brown { 24330a96aa3bSJed Brown PetscInt q; 24340a96aa3bSJed Brown for (q = 0; q < nleaves; q++) { 24350a96aa3bSJed Brown p4est_locidx_t t = coverQuads[q].p.which_tree; 24360a96aa3bSJed Brown if (!treeQuadCounts[t - fltF]++) treeQuads[t - fltF] = &coverQuads[q]; 24370a96aa3bSJed Brown } 24380a96aa3bSJed Brown } 24390a96aa3bSJed Brown } 24400a96aa3bSJed Brown } 24410a96aa3bSJed Brown if (!coverQuads) { /* matching partitions: assign tree quads based on locations in p4est native arrays */ 24420a96aa3bSJed Brown for (t = fltF; t <= lltF; t++) { 24430a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estC->trees->array)[t]); 24440a96aa3bSJed Brown 24450a96aa3bSJed Brown treeQuadCounts[t - fltF] = tree->quadrants.elem_count; 24460a96aa3bSJed Brown treeQuads[t - fltF] = (p4est_quadrant_t *)tree->quadrants.array; 24470a96aa3bSJed Brown } 24480a96aa3bSJed Brown } 24490a96aa3bSJed Brown 24500a96aa3bSJed Brown { 24510a96aa3bSJed Brown PetscInt p; 24520a96aa3bSJed Brown PetscInt cLocalStartF; 24530a96aa3bSJed Brown PetscSF pointSF; 24540a96aa3bSJed Brown PetscSFNode *roots; 24550a96aa3bSJed Brown PetscInt *rootType; 24560a96aa3bSJed Brown DM refTree = NULL; 24570a96aa3bSJed Brown DMLabel canonical; 24580a96aa3bSJed Brown PetscInt *childClosures[P4EST_CHILDREN] = {NULL}; 24590a96aa3bSJed Brown PetscInt *rootClosure = NULL; 24600a96aa3bSJed Brown PetscInt coarseOffset; 24610a96aa3bSJed Brown PetscInt numCoarseQuads; 24620a96aa3bSJed Brown 24639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &roots)); 24649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &rootType)); 24659566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(fine, &pointSF)); 24660a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 24670a96aa3bSJed Brown roots[p - pStartF].rank = -1; 24680a96aa3bSJed Brown roots[p - pStartF].index = -1; 24690a96aa3bSJed Brown rootType[p - pStartF] = -1; 24700a96aa3bSJed Brown } 24710a96aa3bSJed Brown if (formCids) { 24720a96aa3bSJed Brown PetscInt child; 24730a96aa3bSJed Brown 24749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids)); 24750a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) cids[p - pStartF] = -2; 24769566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF, &refTree)); 24779566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, 0, PETSC_TRUE, NULL, &rootClosure)); 24780a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { /* get the closures of the child cells in the reference tree */ 24799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child + 1, PETSC_TRUE, NULL, &childClosures[child])); 24800a96aa3bSJed Brown } 24819566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical)); 24820a96aa3bSJed Brown } 24830a96aa3bSJed Brown cLocalStartF = pforestF->cLocalStart; 24840a96aa3bSJed Brown for (t = fltF, coarseOffset = 0, numCoarseQuads = 0; t <= lltF; t++, coarseOffset += numCoarseQuads) { 24850a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estF->trees->array)[t]); 24860a96aa3bSJed Brown PetscInt numFineQuads = tree->quadrants.elem_count; 24870a96aa3bSJed Brown p4est_quadrant_t *coarseQuads = treeQuads[t - fltF]; 24880a96aa3bSJed Brown p4est_quadrant_t *fineQuads = (p4est_quadrant_t *)tree->quadrants.array; 24890a96aa3bSJed Brown PetscInt i, coarseCount = 0; 24900a96aa3bSJed Brown PetscInt offset = tree->quadrants_offset; 24910a96aa3bSJed Brown sc_array_t coarseQuadsArray; 24920a96aa3bSJed Brown 24930a96aa3bSJed Brown numCoarseQuads = treeQuadCounts[t - fltF]; 2494792fecdfSBarry Smith PetscCallP4est(sc_array_init_data, (&coarseQuadsArray, coarseQuads, sizeof(p4est_quadrant_t), (size_t)numCoarseQuads)); 24950a96aa3bSJed Brown for (i = 0; i < numFineQuads; i++) { 24960a96aa3bSJed Brown PetscInt c = i + offset; 24970a96aa3bSJed Brown p4est_quadrant_t *quad = &fineQuads[i]; 24980a96aa3bSJed Brown p4est_quadrant_t *quadCoarse = NULL; 24990a96aa3bSJed Brown ssize_t disjoint = -1; 25000a96aa3bSJed Brown 25010a96aa3bSJed Brown while (disjoint < 0 && coarseCount < numCoarseQuads) { 25020a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2503792fecdfSBarry Smith PetscCallP4estReturn(disjoint, p4est_quadrant_disjoint, (quadCoarse, quad)); 25040a96aa3bSJed Brown if (disjoint < 0) coarseCount++; 25050a96aa3bSJed Brown } 250608401ef6SPierre Jolivet PetscCheck(disjoint == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "did not find overlapping coarse quad"); 25070a96aa3bSJed Brown if (quadCoarse->level > quad->level || (quadCoarse->level == quad->level && !transferIdent)) { /* the "coarse" mesh is finer than the fine mesh at the point: continue */ 25080a96aa3bSJed Brown if (transferIdent) { /* find corners */ 25090a96aa3bSJed Brown PetscInt j = 0; 25100a96aa3bSJed Brown 25110a96aa3bSJed Brown do { 25120a96aa3bSJed Brown if (j < P4EST_CHILDREN) { 25130a96aa3bSJed Brown p4est_quadrant_t cornerQuad; 25140a96aa3bSJed Brown int equal; 25150a96aa3bSJed Brown 2516792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_descendant, (quad, &cornerQuad, j, quadCoarse->level)); 2517792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal, (&cornerQuad, quadCoarse)); 25180a96aa3bSJed Brown if (equal) { 25190a96aa3bSJed Brown PetscInt petscJ = P4estVertToPetscVert[j]; 25200a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + (P4EST_INSUL - P4EST_CHILDREN) + petscJ].index; 25210a96aa3bSJed Brown PetscSFNode q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + (P4EST_INSUL - P4EST_CHILDREN) + petscJ]; 25220a96aa3bSJed Brown 25230a96aa3bSJed Brown roots[p - pStartF] = q; 25240a96aa3bSJed Brown rootType[p - pStartF] = PETSC_MAX_INT; 25250a96aa3bSJed Brown cids[p - pStartF] = -1; 25260a96aa3bSJed Brown j++; 25270a96aa3bSJed Brown } 25280a96aa3bSJed Brown } 25290a96aa3bSJed Brown coarseCount++; 25300a96aa3bSJed Brown disjoint = 1; 25310a96aa3bSJed Brown if (coarseCount < numCoarseQuads) { 25320a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2533792fecdfSBarry Smith PetscCallP4estReturn(disjoint, p4est_quadrant_disjoint, (quadCoarse, quad)); 25340a96aa3bSJed Brown } 25350a96aa3bSJed Brown } while (!disjoint); 25360a96aa3bSJed Brown } 25370a96aa3bSJed Brown continue; 25380a96aa3bSJed Brown } 25390a96aa3bSJed Brown if (quadCoarse->level == quad->level) { /* same quad present in coarse and fine mesh */ 25400a96aa3bSJed Brown PetscInt j; 25410a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 25420a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + j].index; 25430a96aa3bSJed Brown 25440a96aa3bSJed Brown roots[p - pStartF] = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + j]; 25450a96aa3bSJed Brown rootType[p - pStartF] = PETSC_MAX_INT; /* unconditionally accept */ 25460a96aa3bSJed Brown cids[p - pStartF] = -1; 25470a96aa3bSJed Brown } 25480a96aa3bSJed Brown } else { 25490a96aa3bSJed Brown PetscInt levelDiff = quad->level - quadCoarse->level; 25500a96aa3bSJed Brown PetscInt proposedCids[P4EST_INSUL] = {0}; 25510a96aa3bSJed Brown 25520a96aa3bSJed Brown if (formCids) { 25530a96aa3bSJed Brown PetscInt cl; 25540a96aa3bSJed Brown PetscInt *pointClosure = NULL; 25550a96aa3bSJed Brown int cid; 25560a96aa3bSJed Brown 255708401ef6SPierre Jolivet PetscCheck(levelDiff <= 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Recursive child ids not implemented"); 2558792fecdfSBarry Smith PetscCallP4estReturn(cid, p4est_quadrant_child_id, (quad)); 25599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plexF, c + cLocalStartF, PETSC_TRUE, NULL, &pointClosure)); 25600a96aa3bSJed Brown for (cl = 0; cl < P4EST_INSUL; cl++) { 25610a96aa3bSJed Brown PetscInt p = pointClosure[2 * cl]; 25620a96aa3bSJed Brown PetscInt point = childClosures[cid][2 * cl]; 25630a96aa3bSJed Brown PetscInt ornt = childClosures[cid][2 * cl + 1]; 25640a96aa3bSJed Brown PetscInt newcid = -1; 25650a96aa3bSJed Brown DMPolytopeType ct; 25660a96aa3bSJed Brown 25670a96aa3bSJed Brown if (rootType[p - pStartF] == PETSC_MAX_INT) continue; 25689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, point, &ct)); 25690a96aa3bSJed Brown ornt = DMPolytopeConvertNewOrientation_Internal(ct, ornt); 25700a96aa3bSJed Brown if (!cl) { 25710a96aa3bSJed Brown newcid = cid + 1; 25720a96aa3bSJed Brown } else { 25730a96aa3bSJed Brown PetscInt rcl, parent, parentOrnt = 0; 25740a96aa3bSJed Brown 25759566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, point, &parent, NULL)); 25760a96aa3bSJed Brown if (parent == point) { 25770a96aa3bSJed Brown newcid = -1; 25780a96aa3bSJed Brown } else if (!parent) { /* in the root */ 25790a96aa3bSJed Brown newcid = point; 25800a96aa3bSJed Brown } else { 25810a96aa3bSJed Brown DMPolytopeType rct = DM_POLYTOPE_UNKNOWN; 25820a96aa3bSJed Brown 25830a96aa3bSJed Brown for (rcl = 1; rcl < P4EST_INSUL; rcl++) { 25840a96aa3bSJed Brown if (rootClosure[2 * rcl] == parent) { 25859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, parent, &rct)); 25860a96aa3bSJed Brown parentOrnt = DMPolytopeConvertNewOrientation_Internal(rct, rootClosure[2 * rcl + 1]); 25870a96aa3bSJed Brown break; 25880a96aa3bSJed Brown } 25890a96aa3bSJed Brown } 259008401ef6SPierre Jolivet PetscCheck(rcl < P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Couldn't find parent in root closure"); 25919566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(refTree, parent, parentOrnt, ornt, point, DMPolytopeConvertNewOrientation_Internal(rct, pointClosure[2 * rcl + 1]), NULL, &newcid)); 25920a96aa3bSJed Brown } 25930a96aa3bSJed Brown } 25940a96aa3bSJed Brown if (newcid >= 0) { 259548a46eb9SPierre Jolivet if (canonical) PetscCall(DMLabelGetValue(canonical, newcid, &newcid)); 25960a96aa3bSJed Brown proposedCids[cl] = newcid; 25970a96aa3bSJed Brown } 25980a96aa3bSJed Brown } 25999566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plexF, c + cLocalStartF, PETSC_TRUE, NULL, &pointClosure)); 26000a96aa3bSJed Brown } 26019371c9d4SSatish Balay p4est_qcoord_t coarseBound[2][P4EST_DIM] = { 26029371c9d4SSatish Balay {quadCoarse->x, quadCoarse->y, 26030a96aa3bSJed Brown #if defined(P4_TO_P8) 26040a96aa3bSJed Brown quadCoarse->z 26050a96aa3bSJed Brown #endif 26069371c9d4SSatish Balay }, 26079371c9d4SSatish Balay {0 } 26089371c9d4SSatish Balay }; 26099371c9d4SSatish Balay p4est_qcoord_t fineBound[2][P4EST_DIM] = { 26109371c9d4SSatish Balay {quad->x, quad->y, 26110a96aa3bSJed Brown #if defined(P4_TO_P8) 26120a96aa3bSJed Brown quad->z 26130a96aa3bSJed Brown #endif 26149371c9d4SSatish Balay }, 26159371c9d4SSatish Balay {0 } 26169371c9d4SSatish Balay }; 26170a96aa3bSJed Brown PetscInt j; 26180a96aa3bSJed Brown for (j = 0; j < P4EST_DIM; j++) { /* get the coordinates of cell boundaries in each direction */ 26190a96aa3bSJed Brown coarseBound[1][j] = coarseBound[0][j] + P4EST_QUADRANT_LEN(quadCoarse->level); 26200a96aa3bSJed Brown fineBound[1][j] = fineBound[0][j] + P4EST_QUADRANT_LEN(quad->level); 26210a96aa3bSJed Brown } 26220a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 26230a96aa3bSJed Brown PetscInt l, p; 26240a96aa3bSJed Brown PetscSFNode q; 26250a96aa3bSJed Brown 26260a96aa3bSJed Brown p = closurePointsF[numClosureIndices * c + j].index; 26270a96aa3bSJed Brown if (rootType[p - pStartF] == PETSC_MAX_INT) continue; 26280a96aa3bSJed Brown if (j == 0) { /* volume: ancestor is volume */ 26290a96aa3bSJed Brown l = 0; 26300a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES) { /* facet */ 26310a96aa3bSJed Brown PetscInt face = PetscFaceToP4estFace[j - 1]; 26320a96aa3bSJed Brown PetscInt direction = face / 2; 26330a96aa3bSJed Brown PetscInt coarseFace = -1; 26340a96aa3bSJed Brown 26350a96aa3bSJed Brown if (coarseBound[face % 2][direction] == fineBound[face % 2][direction]) { 26360a96aa3bSJed Brown coarseFace = face; 26370a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 26380a96aa3bSJed Brown } else { 26390a96aa3bSJed Brown l = 0; 26400a96aa3bSJed Brown } 26410a96aa3bSJed Brown #if defined(P4_TO_P8) 26420a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES + P8EST_EDGES) { 26430a96aa3bSJed Brown PetscInt edge = PetscEdgeToP4estEdge[j - (1 + P4EST_FACES)]; 26440a96aa3bSJed Brown PetscInt direction = edge / 4; 26450a96aa3bSJed Brown PetscInt mod = edge % 4; 26460a96aa3bSJed Brown PetscInt coarseEdge = -1, coarseFace = -1; 26470a96aa3bSJed Brown PetscInt minDir = PetscMin((direction + 1) % 3, (direction + 2) % 3); 26480a96aa3bSJed Brown PetscInt maxDir = PetscMax((direction + 1) % 3, (direction + 2) % 3); 26490a96aa3bSJed Brown PetscBool dirTest[2]; 26500a96aa3bSJed Brown 26510a96aa3bSJed Brown dirTest[0] = (PetscBool)(coarseBound[mod % 2][minDir] == fineBound[mod % 2][minDir]); 26520a96aa3bSJed Brown dirTest[1] = (PetscBool)(coarseBound[mod / 2][maxDir] == fineBound[mod / 2][maxDir]); 26530a96aa3bSJed Brown 26540a96aa3bSJed Brown if (dirTest[0] && dirTest[1]) { /* fine edge falls on coarse edge */ 26550a96aa3bSJed Brown coarseEdge = edge; 26560a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 26570a96aa3bSJed Brown } else if (dirTest[0]) { /* fine edge falls on a coarse face in the minDir direction */ 26580a96aa3bSJed Brown coarseFace = 2 * minDir + (mod % 2); 26590a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 26600a96aa3bSJed Brown } else if (dirTest[1]) { /* fine edge falls on a coarse face in the maxDir direction */ 26610a96aa3bSJed Brown coarseFace = 2 * maxDir + (mod / 2); 26620a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 26630a96aa3bSJed Brown } else { 26640a96aa3bSJed Brown l = 0; 26650a96aa3bSJed Brown } 26660a96aa3bSJed Brown #endif 26670a96aa3bSJed Brown } else { 26680a96aa3bSJed Brown PetscInt vertex = PetscVertToP4estVert[P4EST_CHILDREN - (P4EST_INSUL - j)]; 26690a96aa3bSJed Brown PetscBool dirTest[P4EST_DIM]; 26700a96aa3bSJed Brown PetscInt m; 26710a96aa3bSJed Brown PetscInt numMatch = 0; 26720a96aa3bSJed Brown PetscInt coarseVertex = -1, coarseFace = -1; 26730a96aa3bSJed Brown #if defined(P4_TO_P8) 26740a96aa3bSJed Brown PetscInt coarseEdge = -1; 26750a96aa3bSJed Brown #endif 26760a96aa3bSJed Brown 26770a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 26780a96aa3bSJed Brown dirTest[m] = (PetscBool)(coarseBound[(vertex >> m) & 1][m] == fineBound[(vertex >> m) & 1][m]); 26790a96aa3bSJed Brown if (dirTest[m]) numMatch++; 26800a96aa3bSJed Brown } 26810a96aa3bSJed Brown if (numMatch == P4EST_DIM) { /* vertex on vertex */ 26820a96aa3bSJed Brown coarseVertex = vertex; 26830a96aa3bSJed Brown l = P4EST_INSUL - (P4EST_CHILDREN - P4estVertToPetscVert[coarseVertex]); 26840a96aa3bSJed Brown } else if (numMatch == 1) { /* vertex on face */ 26850a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 26860a96aa3bSJed Brown if (dirTest[m]) { 26870a96aa3bSJed Brown coarseFace = 2 * m + ((vertex >> m) & 1); 26880a96aa3bSJed Brown break; 26890a96aa3bSJed Brown } 26900a96aa3bSJed Brown } 26910a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 26920a96aa3bSJed Brown #if defined(P4_TO_P8) 26930a96aa3bSJed Brown } else if (numMatch == 2) { /* vertex on edge */ 26940a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 26950a96aa3bSJed Brown if (!dirTest[m]) { 26960a96aa3bSJed Brown PetscInt otherDir1 = (m + 1) % 3; 26970a96aa3bSJed Brown PetscInt otherDir2 = (m + 2) % 3; 26980a96aa3bSJed Brown PetscInt minDir = PetscMin(otherDir1, otherDir2); 26990a96aa3bSJed Brown PetscInt maxDir = PetscMax(otherDir1, otherDir2); 27000a96aa3bSJed Brown 27010a96aa3bSJed Brown coarseEdge = m * 4 + 2 * ((vertex >> maxDir) & 1) + ((vertex >> minDir) & 1); 27020a96aa3bSJed Brown break; 27030a96aa3bSJed Brown } 27040a96aa3bSJed Brown } 27050a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 27060a96aa3bSJed Brown #endif 27070a96aa3bSJed Brown } else { /* volume */ 27080a96aa3bSJed Brown l = 0; 27090a96aa3bSJed Brown } 27100a96aa3bSJed Brown } 27110a96aa3bSJed Brown q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + l]; 27120a96aa3bSJed Brown if (l > rootType[p - pStartF]) { 27130a96aa3bSJed Brown if (l >= P4EST_INSUL - P4EST_CHILDREN) { /* vertex on vertex: unconditional acceptance */ 27140a96aa3bSJed Brown if (transferIdent) { 27150a96aa3bSJed Brown roots[p - pStartF] = q; 27160a96aa3bSJed Brown rootType[p - pStartF] = PETSC_MAX_INT; 27170a96aa3bSJed Brown if (formCids) cids[p - pStartF] = -1; 27180a96aa3bSJed Brown } 27190a96aa3bSJed Brown } else { 27200a96aa3bSJed Brown PetscInt k, thisp = p, limit; 27210a96aa3bSJed Brown 27220a96aa3bSJed Brown roots[p - pStartF] = q; 27230a96aa3bSJed Brown rootType[p - pStartF] = l; 27240a96aa3bSJed Brown if (formCids) cids[p - pStartF] = proposedCids[j]; 27250a96aa3bSJed Brown limit = transferIdent ? levelDiff : (levelDiff - 1); 27260a96aa3bSJed Brown for (k = 0; k < limit; k++) { 27270a96aa3bSJed Brown PetscInt parent; 27280a96aa3bSJed Brown 27299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plexF, thisp, &parent, NULL)); 27300a96aa3bSJed Brown if (parent == thisp) break; 27310a96aa3bSJed Brown 27320a96aa3bSJed Brown roots[parent - pStartF] = q; 27330a96aa3bSJed Brown rootType[parent - pStartF] = PETSC_MAX_INT; 27340a96aa3bSJed Brown if (formCids) cids[parent - pStartF] = -1; 27350a96aa3bSJed Brown thisp = parent; 27360a96aa3bSJed Brown } 27370a96aa3bSJed Brown } 27380a96aa3bSJed Brown } 27390a96aa3bSJed Brown } 27400a96aa3bSJed Brown } 27410a96aa3bSJed Brown } 27420a96aa3bSJed Brown } 27430a96aa3bSJed Brown 27440a96aa3bSJed Brown /* now every cell has labeled the points in its closure, so we first make sure everyone agrees by reducing to roots, and the broadcast the agreements */ 27450a96aa3bSJed Brown if (size > 1) { 27460a96aa3bSJed Brown PetscInt *rootTypeCopy, p; 27470a96aa3bSJed Brown 27489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &rootTypeCopy)); 27499566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(rootTypeCopy, rootType, pEndF - pStartF)); 275057168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_MAX)); 275157168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_MAX)); 27529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_REPLACE)); 27539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_REPLACE)); 27540a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 27550a96aa3bSJed Brown if (rootTypeCopy[p - pStartF] > rootType[p - pStartF]) { /* another process found a root of higher type (e.g. vertex instead of edge), which we want to accept, so nullify this */ 27560a96aa3bSJed Brown roots[p - pStartF].rank = -1; 27570a96aa3bSJed Brown roots[p - pStartF].index = -1; 27580a96aa3bSJed Brown } 27599371c9d4SSatish Balay if (formCids && rootTypeCopy[p - pStartF] == PETSC_MAX_INT) { cids[p - pStartF] = -1; /* we have found an antecedent that is the same: no child id */ } 27600a96aa3bSJed Brown } 27619566063dSJacob Faibussowitsch PetscCall(PetscFree(rootTypeCopy)); 27629566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF, nodeType, roots, roots, sfNodeReduce)); 27639566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF, nodeType, roots, roots, sfNodeReduce)); 27649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, nodeType, roots, roots, MPI_REPLACE)); 27659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, nodeType, roots, roots, MPI_REPLACE)); 27660a96aa3bSJed Brown } 27679566063dSJacob Faibussowitsch PetscCall(PetscFree(rootType)); 27680a96aa3bSJed Brown 27690a96aa3bSJed Brown { 27700a96aa3bSJed Brown PetscInt numRoots; 27710a96aa3bSJed Brown PetscInt numLeaves; 27720a96aa3bSJed Brown PetscInt *leaves; 27730a96aa3bSJed Brown PetscSFNode *iremote; 27740a96aa3bSJed Brown /* count leaves */ 27750a96aa3bSJed Brown 27760a96aa3bSJed Brown numRoots = pEndC - pStartC; 27770a96aa3bSJed Brown 27780a96aa3bSJed Brown numLeaves = 0; 27790a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 27800a96aa3bSJed Brown if (roots[p - pStartF].index >= 0) numLeaves++; 27810a96aa3bSJed Brown } 27829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &leaves)); 27839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &iremote)); 27840a96aa3bSJed Brown numLeaves = 0; 27850a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 27860a96aa3bSJed Brown if (roots[p - pStartF].index >= 0) { 27870a96aa3bSJed Brown leaves[numLeaves] = p - pStartF; 27880a96aa3bSJed Brown iremote[numLeaves] = roots[p - pStartF]; 27890a96aa3bSJed Brown numLeaves++; 27900a96aa3bSJed Brown } 27910a96aa3bSJed Brown } 27929566063dSJacob Faibussowitsch PetscCall(PetscFree(roots)); 27939566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sf)); 27940a96aa3bSJed Brown if (numLeaves == (pEndF - pStartF)) { 27959566063dSJacob Faibussowitsch PetscCall(PetscFree(leaves)); 27969566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, numRoots, numLeaves, NULL, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 27970a96aa3bSJed Brown } else { 27989566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, numRoots, numLeaves, leaves, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 27990a96aa3bSJed Brown } 28000a96aa3bSJed Brown } 28010a96aa3bSJed Brown if (formCids) { 28020a96aa3bSJed Brown PetscSF pointSF; 28030a96aa3bSJed Brown PetscInt child; 28040a96aa3bSJed Brown 28059566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF, &refTree)); 28069566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plexF, &pointSF)); 280757168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, cids, cids, MPI_MAX)); 280857168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, cids, cids, MPI_MAX)); 28090a96aa3bSJed Brown if (childIds) *childIds = cids; 281048a46eb9SPierre Jolivet for (child = 0; child < P4EST_CHILDREN; child++) PetscCall(DMPlexRestoreTransitiveClosure(refTree, child + 1, PETSC_TRUE, NULL, &childClosures[child])); 28119566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, 0, PETSC_TRUE, NULL, &rootClosure)); 28120a96aa3bSJed Brown } 28130a96aa3bSJed Brown } 28140a96aa3bSJed Brown if (saveInCoarse) { /* cache results */ 28159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 28160a96aa3bSJed Brown pforestC->pointSelfToAdaptSF = *sf; 28170a96aa3bSJed Brown if (!childIds) { 28180a96aa3bSJed Brown pforestC->pointSelfToAdaptCids = cids; 28190a96aa3bSJed Brown } else { 28209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &pforestC->pointSelfToAdaptCids)); 28219566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestC->pointSelfToAdaptCids, cids, pEndF - pStartF)); 28220a96aa3bSJed Brown } 28230a96aa3bSJed Brown } else if (saveInFine) { 28249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 28250a96aa3bSJed Brown pforestF->pointAdaptToSelfSF = *sf; 28260a96aa3bSJed Brown if (!childIds) { 28270a96aa3bSJed Brown pforestF->pointAdaptToSelfCids = cids; 28280a96aa3bSJed Brown } else { 28299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &pforestF->pointAdaptToSelfCids)); 28309566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestF->pointAdaptToSelfCids, cids, pEndF - pStartF)); 28310a96aa3bSJed Brown } 28320a96aa3bSJed Brown } 28339566063dSJacob Faibussowitsch PetscCall(PetscFree2(treeQuads, treeQuadCounts)); 28349566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuads)); 28359566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 28369566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsF)); 28379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeClosureType)); 28389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&sfNodeReduce)); 28399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 28400a96aa3bSJed Brown PetscFunctionReturn(0); 28410a96aa3bSJed Brown } 28420a96aa3bSJed Brown 28430a96aa3bSJed Brown /* children are sf leaves of parents */ 28449371c9d4SSatish Balay static PetscErrorCode DMPforestGetTransferSF_Internal(DM coarse, DM fine, const PetscInt dofPerDim[], PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) { 28450a96aa3bSJed Brown MPI_Comm comm; 2846d70f29a3SPierre Jolivet PetscMPIInt rank; 28470a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 28480a96aa3bSJed Brown DM plexC, plexF; 28490a96aa3bSJed Brown PetscInt pStartC, pEndC, pStartF, pEndF; 28500a96aa3bSJed Brown PetscSF pointTransferSF; 28510a96aa3bSJed Brown PetscBool allOnes = PETSC_TRUE; 28520a96aa3bSJed Brown 28530a96aa3bSJed Brown PetscFunctionBegin; 28540a96aa3bSJed Brown pforestC = (DM_Forest_pforest *)((DM_Forest *)coarse->data)->data; 28550a96aa3bSJed Brown pforestF = (DM_Forest_pforest *)((DM_Forest *)fine->data)->data; 285608401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo, PetscObjectComm((PetscObject)coarse), PETSC_ERR_ARG_INCOMP, "DM's must have the same base DM"); 28570a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 28589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 28590a96aa3bSJed Brown 28600a96aa3bSJed Brown { 28610a96aa3bSJed Brown PetscInt i; 28620a96aa3bSJed Brown for (i = 0; i <= P4EST_DIM; i++) { 28630a96aa3bSJed Brown if (dofPerDim[i] != 1) { 28640a96aa3bSJed Brown allOnes = PETSC_FALSE; 28650a96aa3bSJed Brown break; 28660a96aa3bSJed Brown } 28670a96aa3bSJed Brown } 28680a96aa3bSJed Brown } 28699566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Point(coarse, fine, &pointTransferSF, transferIdent, childIds)); 28700a96aa3bSJed Brown if (allOnes) { 28710a96aa3bSJed Brown *sf = pointTransferSF; 28720a96aa3bSJed Brown PetscFunctionReturn(0); 28730a96aa3bSJed Brown } 28740a96aa3bSJed Brown 28759566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine, &plexF)); 28769566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF, &pStartF, &pEndF)); 28779566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse, &plexC)); 28789566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC, &pStartC, &pEndC)); 28790a96aa3bSJed Brown { 28800a96aa3bSJed Brown PetscInt numRoots; 28810a96aa3bSJed Brown PetscInt numLeaves; 28820a96aa3bSJed Brown const PetscInt *leaves; 28830a96aa3bSJed Brown const PetscSFNode *iremote; 28840a96aa3bSJed Brown PetscInt d; 28850a96aa3bSJed Brown PetscSection leafSection, rootSection; 28860a96aa3bSJed Brown /* count leaves */ 28870a96aa3bSJed Brown 28889566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointTransferSF, &numRoots, &numLeaves, &leaves, &iremote)); 28899566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &rootSection)); 28909566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &leafSection)); 28919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, pStartC, pEndC)); 28929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafSection, pStartF, pEndF)); 28930a96aa3bSJed Brown 28940a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 28950a96aa3bSJed Brown PetscInt startC, endC, e; 28960a96aa3bSJed Brown 28979566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC, P4EST_DIM - d, &startC, &endC)); 289848a46eb9SPierre Jolivet for (e = startC; e < endC; e++) PetscCall(PetscSectionSetDof(rootSection, e, dofPerDim[d])); 28990a96aa3bSJed Brown } 29000a96aa3bSJed Brown 29010a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 29020a96aa3bSJed Brown PetscInt startF, endF, e; 29030a96aa3bSJed Brown 29049566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexF, P4EST_DIM - d, &startF, &endF)); 290548a46eb9SPierre Jolivet for (e = startF; e < endF; e++) PetscCall(PetscSectionSetDof(leafSection, e, dofPerDim[d])); 29060a96aa3bSJed Brown } 29070a96aa3bSJed Brown 29089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 29099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSection)); 29100a96aa3bSJed Brown { 29110a96aa3bSJed Brown PetscInt nroots, nleaves; 29120a96aa3bSJed Brown PetscInt *mine, i, p; 29130a96aa3bSJed Brown PetscInt *offsets, *offsetsRoot; 29140a96aa3bSJed Brown PetscSFNode *remote; 29150a96aa3bSJed Brown 29169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &offsets)); 29179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &offsetsRoot)); 291848a46eb9SPierre Jolivet for (p = pStartC; p < pEndC; p++) PetscCall(PetscSectionGetOffset(rootSection, p, &offsetsRoot[p - pStartC])); 29199566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointTransferSF, MPIU_INT, offsetsRoot, offsets, MPI_REPLACE)); 29209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointTransferSF, MPIU_INT, offsetsRoot, offsets, MPI_REPLACE)); 29219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &nroots)); 29220a96aa3bSJed Brown nleaves = 0; 29230a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 29240a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 29250a96aa3bSJed Brown PetscInt dof; 29260a96aa3bSJed Brown 29279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, leaf, &dof)); 29280a96aa3bSJed Brown nleaves += dof; 29290a96aa3bSJed Brown } 29309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &mine)); 29319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remote)); 29320a96aa3bSJed Brown nleaves = 0; 29330a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 29340a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 29350a96aa3bSJed Brown PetscInt dof; 29360a96aa3bSJed Brown PetscInt off, j; 29370a96aa3bSJed Brown 29389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, leaf, &dof)); 29399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection, leaf, &off)); 29400a96aa3bSJed Brown for (j = 0; j < dof; j++) { 29410a96aa3bSJed Brown remote[nleaves].rank = iremote[i].rank; 29420a96aa3bSJed Brown remote[nleaves].index = offsets[leaf] + j; 29430a96aa3bSJed Brown mine[nleaves++] = off + j; 29440a96aa3bSJed Brown } 29450a96aa3bSJed Brown } 29469566063dSJacob Faibussowitsch PetscCall(PetscFree(offsetsRoot)); 29479566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 29489566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sf)); 29499566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, nroots, nleaves, mine, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER)); 29500a96aa3bSJed Brown } 29519566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 29529566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 29539566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointTransferSF)); 29540a96aa3bSJed Brown } 29550a96aa3bSJed Brown PetscFunctionReturn(0); 29560a96aa3bSJed Brown } 29570a96aa3bSJed Brown 29589371c9d4SSatish Balay static PetscErrorCode DMPforestGetTransferSF(DM dmA, DM dmB, const PetscInt dofPerDim[], PetscSF *sfAtoB, PetscSF *sfBtoA) { 29590a96aa3bSJed Brown DM adaptA, adaptB; 29600a96aa3bSJed Brown DMAdaptFlag purpose; 29610a96aa3bSJed Brown 29620a96aa3bSJed Brown PetscFunctionBegin; 29639566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmA, &adaptA)); 29649566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmB, &adaptB)); 29650a96aa3bSJed Brown /* it is more efficient when the coarser mesh is the first argument: reorder if we know one is coarser than the other */ 29660a96aa3bSJed Brown if (adaptA && adaptA->data == dmB->data) { /* dmA was adapted from dmB */ 29679566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmA, &purpose)); 29680a96aa3bSJed Brown if (purpose == DM_ADAPT_REFINE) { 29699566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 29700a96aa3bSJed Brown PetscFunctionReturn(0); 29710a96aa3bSJed Brown } 29720a96aa3bSJed Brown } else if (adaptB && adaptB->data == dmA->data) { /* dmB was adapted from dmA */ 29739566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmB, &purpose)); 29740a96aa3bSJed Brown if (purpose == DM_ADAPT_COARSEN) { 29759566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 29760a96aa3bSJed Brown PetscFunctionReturn(0); 29770a96aa3bSJed Brown } 29780a96aa3bSJed Brown } 29791baa6e33SBarry Smith if (sfAtoB) PetscCall(DMPforestGetTransferSF_Internal(dmA, dmB, dofPerDim, sfAtoB, PETSC_TRUE, NULL)); 29801baa6e33SBarry Smith if (sfBtoA) PetscCall(DMPforestGetTransferSF_Internal(dmB, dmA, dofPerDim, sfBtoA, (PetscBool)(sfAtoB == NULL), NULL)); 29810a96aa3bSJed Brown PetscFunctionReturn(0); 29820a96aa3bSJed Brown } 29830a96aa3bSJed Brown 29849371c9d4SSatish Balay static PetscErrorCode DMPforestLabelsInitialize(DM dm, DM plex) { 29850a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 29860a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 29870a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, cStart, cEnd, fStart, fEnd, eStart, eEnd, vStart, vEnd; 29880a96aa3bSJed Brown PetscInt cStartBase, cEndBase, fStartBase, fEndBase, vStartBase, vEndBase, eStartBase, eEndBase; 29890a96aa3bSJed Brown PetscInt pStart, pEnd, pStartBase, pEndBase, p; 29900a96aa3bSJed Brown DM base; 29910a96aa3bSJed Brown PetscInt *star = NULL, starSize; 29920a96aa3bSJed Brown DMLabelLink next = dm->labels; 29930a96aa3bSJed Brown PetscInt guess = 0; 29940a96aa3bSJed Brown p4est_topidx_t num_trees = pforest->topo->conn->num_trees; 29950a96aa3bSJed Brown 29960a96aa3bSJed Brown PetscFunctionBegin; 29970a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 29980a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 29990a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 30009566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 30010a96aa3bSJed Brown if (!base) { 30020a96aa3bSJed Brown if (pforest->ghostName) { /* insert a label to make the boundaries, with stratum values denoting which face of the element touches the boundary */ 30030a96aa3bSJed Brown p4est_connectivity_t *conn = pforest->topo->conn; 30040a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 30050a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t *)p4est->trees->array; 30060a96aa3bSJed Brown p4est_topidx_t t, flt = p4est->first_local_tree; 30070a96aa3bSJed Brown p4est_topidx_t llt = pforest->forest->last_local_tree; 30080a96aa3bSJed Brown DMLabel ghostLabel; 30090a96aa3bSJed Brown PetscInt c; 30100a96aa3bSJed Brown 30119566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(plex, pforest->ghostName)); 30129566063dSJacob Faibussowitsch PetscCall(DMGetLabel(plex, pforest->ghostName, &ghostLabel)); 30130a96aa3bSJed Brown for (c = cLocalStart, t = flt; t <= llt; t++) { 30140a96aa3bSJed Brown p4est_tree_t *tree = &trees[t]; 30150a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 30160a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 30170a96aa3bSJed Brown PetscInt q; 30180a96aa3bSJed Brown 30190a96aa3bSJed Brown for (q = 0; q < numQuads; q++, c++) { 30200a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[q]; 30210a96aa3bSJed Brown PetscInt f; 30220a96aa3bSJed Brown 30230a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++) { 30240a96aa3bSJed Brown p4est_quadrant_t neigh; 30250a96aa3bSJed Brown int isOutside; 30260a96aa3bSJed Brown 3027792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor, (quad, f, &neigh)); 3028792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p4est_quadrant_is_outside_face, (&neigh)); 30290a96aa3bSJed Brown if (isOutside) { 30300a96aa3bSJed Brown p4est_topidx_t nt; 30310a96aa3bSJed Brown PetscInt nf; 30320a96aa3bSJed Brown 30330a96aa3bSJed Brown nt = conn->tree_to_tree[t * P4EST_FACES + f]; 30340a96aa3bSJed Brown nf = (PetscInt)conn->tree_to_face[t * P4EST_FACES + f]; 30350a96aa3bSJed Brown nf = nf % P4EST_FACES; 30360a96aa3bSJed Brown if (nt == t && nf == f) { 30370a96aa3bSJed Brown PetscInt plexF = P4estFaceToPetscFace[f]; 30380a96aa3bSJed Brown const PetscInt *cone; 30390a96aa3bSJed Brown 30409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(plex, c, &cone)); 30419566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ghostLabel, cone[plexF], plexF + 1)); 30420a96aa3bSJed Brown } 30430a96aa3bSJed Brown } 30440a96aa3bSJed Brown } 30450a96aa3bSJed Brown } 30460a96aa3bSJed Brown } 30470a96aa3bSJed Brown } 30480a96aa3bSJed Brown PetscFunctionReturn(0); 30490a96aa3bSJed Brown } 30509566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, 0, &cStartBase, &cEndBase)); 30519566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, 1, &fStartBase, &fEndBase)); 30529566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, P4EST_DIM - 1, &eStartBase, &eEndBase)); 30539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(base, 0, &vStartBase, &vEndBase)); 30540a96aa3bSJed Brown 30559566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, 0, &cStart, &cEnd)); 30569566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, 1, &fStart, &fEnd)); 30579566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, P4EST_DIM - 1, &eStart, &eEnd)); 30589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd)); 30590a96aa3bSJed Brown 30609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &pStart, &pEnd)); 30619566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(base, &pStartBase, &pEndBase)); 30620a96aa3bSJed Brown /* go through the mesh: use star to find a quadrant that borders a point. Use the closure to determine the 30630a96aa3bSJed Brown * orientation of the quadrant relative to that point. Use that to relate the point to the numbering in the base 30640a96aa3bSJed Brown * mesh, and extract a label value (since the base mesh is redundantly distributed, can be found locally). */ 30650a96aa3bSJed Brown while (next) { 30660a96aa3bSJed Brown DMLabel baseLabel; 30670a96aa3bSJed Brown DMLabel label = next->label; 30680a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK, isSpmap; 30690a96aa3bSJed Brown const char *name; 30700a96aa3bSJed Brown 30719566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name)); 30729566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 30730a96aa3bSJed Brown if (isDepth) { 30740a96aa3bSJed Brown next = next->next; 30750a96aa3bSJed Brown continue; 30760a96aa3bSJed Brown } 30779566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 30780a96aa3bSJed Brown if (isCellType) { 30790a96aa3bSJed Brown next = next->next; 30800a96aa3bSJed Brown continue; 30810a96aa3bSJed Brown } 30829566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 30830a96aa3bSJed Brown if (isGhost) { 30840a96aa3bSJed Brown next = next->next; 30850a96aa3bSJed Brown continue; 30860a96aa3bSJed Brown } 30879566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 30880a96aa3bSJed Brown if (isVTK) { 30890a96aa3bSJed Brown next = next->next; 30900a96aa3bSJed Brown continue; 30910a96aa3bSJed Brown } 30929566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "_forest_base_subpoint_map", &isSpmap)); 30930a96aa3bSJed Brown if (!isSpmap) { 30949566063dSJacob Faibussowitsch PetscCall(DMGetLabel(base, name, &baseLabel)); 30950a96aa3bSJed Brown if (!baseLabel) { 30960a96aa3bSJed Brown next = next->next; 30970a96aa3bSJed Brown continue; 30980a96aa3bSJed Brown } 30999566063dSJacob Faibussowitsch PetscCall(DMLabelCreateIndex(baseLabel, pStartBase, pEndBase)); 31000a96aa3bSJed Brown } else baseLabel = NULL; 31010a96aa3bSJed Brown 31020a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 31030a96aa3bSJed Brown PetscInt s, c = -1, l; 31040a96aa3bSJed Brown PetscInt *closure = NULL, closureSize; 31050a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 31060a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t *)pforest->forest->trees->array; 31070a96aa3bSJed Brown p4est_quadrant_t *q; 31080a96aa3bSJed Brown PetscInt t, val; 31090a96aa3bSJed Brown PetscBool zerosupportpoint = PETSC_FALSE; 31100a96aa3bSJed Brown 31119566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star)); 31120a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 31130a96aa3bSJed Brown PetscInt point = star[2 * s]; 31140a96aa3bSJed Brown 31150a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 31169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, point, PETSC_TRUE, &closureSize, &closure)); 31170a96aa3bSJed Brown for (l = 0; l < closureSize; l++) { 31180a96aa3bSJed Brown PetscInt qParent = closure[2 * l], q, pp = p, pParent = p; 31190a96aa3bSJed Brown do { /* check parents of q */ 31200a96aa3bSJed Brown q = qParent; 31210a96aa3bSJed Brown if (q == p) { 31220a96aa3bSJed Brown c = point; 31230a96aa3bSJed Brown break; 31240a96aa3bSJed Brown } 31259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &qParent, NULL)); 31260a96aa3bSJed Brown } while (qParent != q); 31270a96aa3bSJed Brown if (c != -1) break; 31289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, pp, &pParent, NULL)); 31290a96aa3bSJed Brown q = closure[2 * l]; 31300a96aa3bSJed Brown while (pParent != pp) { /* check parents of p */ 31310a96aa3bSJed Brown pp = pParent; 31320a96aa3bSJed Brown if (pp == q) { 31330a96aa3bSJed Brown c = point; 31340a96aa3bSJed Brown break; 31350a96aa3bSJed Brown } 31369566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, pp, &pParent, NULL)); 31370a96aa3bSJed Brown } 31380a96aa3bSJed Brown if (c != -1) break; 31390a96aa3bSJed Brown } 31409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, point, PETSC_TRUE, NULL, &closure)); 31410a96aa3bSJed Brown if (l < closureSize) break; 31420a96aa3bSJed Brown } else { 31430a96aa3bSJed Brown PetscInt supportSize; 31440a96aa3bSJed Brown 31459566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(plex, point, &supportSize)); 31460a96aa3bSJed Brown zerosupportpoint = (PetscBool)(zerosupportpoint || !supportSize); 31470a96aa3bSJed Brown } 31480a96aa3bSJed Brown } 31490a96aa3bSJed Brown if (c < 0) { 31500a96aa3bSJed Brown const char *prefix; 31510a96aa3bSJed Brown PetscBool print = PETSC_FALSE; 31520a96aa3bSJed Brown 31539566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 31549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, prefix, "-dm_forest_print_label_error", &print, NULL)); 31550a96aa3bSJed Brown if (print) { 31560a96aa3bSJed Brown PetscInt i; 31570a96aa3bSJed Brown 315863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Failed to find cell with point %" PetscInt_FMT " in its closure for label %s (starSize %" PetscInt_FMT ")\n", PetscGlobalRank, p, baseLabel ? ((PetscObject)baseLabel)->name : "_forest_base_subpoint_map", starSize)); 315963a3b9bcSJacob Faibussowitsch for (i = 0; i < starSize; i++) PetscCall(PetscPrintf(PETSC_COMM_SELF, " star[%" PetscInt_FMT "] = %" PetscInt_FMT ",%" PetscInt_FMT "\n", i, star[2 * i], star[2 * i + 1])); 31600a96aa3bSJed Brown } 31619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, NULL, &star)); 31620a96aa3bSJed Brown if (zerosupportpoint) continue; 31639371c9d4SSatish Balay else 31649371c9d4SSatish Balay SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed to find cell with point %" PetscInt_FMT " in its closure for label %s. Rerun with -dm_forest_print_label_error for more information", p, baseLabel ? ((PetscObject)baseLabel)->name : "_forest_base_subpoint_map"); 31650a96aa3bSJed Brown } 31669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, NULL, &star)); 31670a96aa3bSJed Brown 31680a96aa3bSJed Brown if (c < cLocalStart) { 31690a96aa3bSJed Brown /* get from the beginning of the ghost layer */ 31700a96aa3bSJed Brown q = &(ghosts[c]); 31710a96aa3bSJed Brown t = (PetscInt)q->p.which_tree; 31720a96aa3bSJed Brown } else if (c < cLocalEnd) { 31730a96aa3bSJed Brown PetscInt lo = 0, hi = num_trees; 31740a96aa3bSJed Brown /* get from local quadrants: have to find the right tree */ 31750a96aa3bSJed Brown 31760a96aa3bSJed Brown c -= cLocalStart; 31770a96aa3bSJed Brown 31780a96aa3bSJed Brown do { 31790a96aa3bSJed Brown p4est_tree_t *tree; 31800a96aa3bSJed Brown 31811dca8a05SBarry Smith PetscCheck(guess >= lo && guess < num_trees && lo < hi, PETSC_COMM_SELF, PETSC_ERR_PLIB, "failed binary search"); 31820a96aa3bSJed Brown tree = &trees[guess]; 31830a96aa3bSJed Brown if (c < tree->quadrants_offset) { 31840a96aa3bSJed Brown hi = guess; 31850a96aa3bSJed Brown } else if (c < tree->quadrants_offset + (PetscInt)tree->quadrants.elem_count) { 31860a96aa3bSJed Brown q = &((p4est_quadrant_t *)tree->quadrants.array)[c - (PetscInt)tree->quadrants_offset]; 31870a96aa3bSJed Brown t = guess; 31880a96aa3bSJed Brown break; 31890a96aa3bSJed Brown } else { 31900a96aa3bSJed Brown lo = guess + 1; 31910a96aa3bSJed Brown } 31920a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 31930a96aa3bSJed Brown } while (1); 31940a96aa3bSJed Brown } else { 31950a96aa3bSJed Brown /* get from the end of the ghost layer */ 31960a96aa3bSJed Brown c -= (cLocalEnd - cLocalStart); 31970a96aa3bSJed Brown 31980a96aa3bSJed Brown q = &(ghosts[c]); 31990a96aa3bSJed Brown t = (PetscInt)q->p.which_tree; 32000a96aa3bSJed Brown } 32010a96aa3bSJed Brown 32020a96aa3bSJed Brown if (l == 0) { /* cell */ 32030a96aa3bSJed Brown if (baseLabel) { 32049566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 32050a96aa3bSJed Brown } else { 32060a96aa3bSJed Brown val = t + cStartBase; 32070a96aa3bSJed Brown } 32089566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32090a96aa3bSJed Brown } else if (l >= 1 && l < 1 + P4EST_FACES) { /* facet */ 32100a96aa3bSJed Brown p4est_quadrant_t nq; 32110a96aa3bSJed Brown int isInside; 32120a96aa3bSJed Brown 32130a96aa3bSJed Brown l = PetscFaceToP4estFace[l - 1]; 3214792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor, (q, l, &nq)); 3215792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq)); 32160a96aa3bSJed Brown if (isInside) { 32170a96aa3bSJed Brown /* this facet is in the interior of a tree, so it inherits the label of the tree */ 32180a96aa3bSJed Brown if (baseLabel) { 32199566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 32200a96aa3bSJed Brown } else { 32210a96aa3bSJed Brown val = t + cStartBase; 32220a96aa3bSJed Brown } 32239566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32240a96aa3bSJed Brown } else { 32250a96aa3bSJed Brown PetscInt f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + l]; 32260a96aa3bSJed Brown 32270a96aa3bSJed Brown if (baseLabel) { 32289566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val)); 32290a96aa3bSJed Brown } else { 32300a96aa3bSJed Brown val = f + fStartBase; 32310a96aa3bSJed Brown } 32329566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32330a96aa3bSJed Brown } 32340a96aa3bSJed Brown #if defined(P4_TO_P8) 32350a96aa3bSJed Brown } else if (l >= 1 + P4EST_FACES && l < 1 + P4EST_FACES + P8EST_EDGES) { /* edge */ 32360a96aa3bSJed Brown p4est_quadrant_t nq; 32370a96aa3bSJed Brown int isInside; 32380a96aa3bSJed Brown 32390a96aa3bSJed Brown l = PetscEdgeToP4estEdge[l - (1 + P4EST_FACES)]; 3240792fecdfSBarry Smith PetscCallP4est(p8est_quadrant_edge_neighbor, (q, l, &nq)); 3241792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq)); 32420a96aa3bSJed Brown if (isInside) { 32430a96aa3bSJed Brown /* this edge is in the interior of a tree, so it inherits the label of the tree */ 32440a96aa3bSJed Brown if (baseLabel) { 32459566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 32460a96aa3bSJed Brown } else { 32470a96aa3bSJed Brown val = t + cStartBase; 32480a96aa3bSJed Brown } 32499566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32500a96aa3bSJed Brown } else { 32510a96aa3bSJed Brown int isOutsideFace; 32520a96aa3bSJed Brown 3253792fecdfSBarry Smith PetscCallP4estReturn(isOutsideFace, p4est_quadrant_is_outside_face, (&nq)); 32540a96aa3bSJed Brown if (isOutsideFace) { 32550a96aa3bSJed Brown PetscInt f; 32560a96aa3bSJed Brown 32570a96aa3bSJed Brown if (nq.x < 0) { 32580a96aa3bSJed Brown f = 0; 32590a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 32600a96aa3bSJed Brown f = 1; 32610a96aa3bSJed Brown } else if (nq.y < 0) { 32620a96aa3bSJed Brown f = 2; 32630a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 32640a96aa3bSJed Brown f = 3; 32650a96aa3bSJed Brown } else if (nq.z < 0) { 32660a96aa3bSJed Brown f = 4; 32670a96aa3bSJed Brown } else { 32680a96aa3bSJed Brown f = 5; 32690a96aa3bSJed Brown } 32700a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 32710a96aa3bSJed Brown if (baseLabel) { 32729566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val)); 32730a96aa3bSJed Brown } else { 32740a96aa3bSJed Brown val = f + fStartBase; 32750a96aa3bSJed Brown } 32769566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32770a96aa3bSJed Brown } else { /* the quadrant edge corresponds to the tree edge */ 32780a96aa3bSJed Brown PetscInt e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + l]; 32790a96aa3bSJed Brown 32800a96aa3bSJed Brown if (baseLabel) { 32819566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, e + eStartBase, &val)); 32820a96aa3bSJed Brown } else { 32830a96aa3bSJed Brown val = e + eStartBase; 32840a96aa3bSJed Brown } 32859566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32860a96aa3bSJed Brown } 32870a96aa3bSJed Brown } 32880a96aa3bSJed Brown #endif 32890a96aa3bSJed Brown } else { /* vertex */ 32900a96aa3bSJed Brown p4est_quadrant_t nq; 32910a96aa3bSJed Brown int isInside; 32920a96aa3bSJed Brown 32930a96aa3bSJed Brown #if defined(P4_TO_P8) 32940a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES + P8EST_EDGES)]; 32950a96aa3bSJed Brown #else 32960a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES)]; 32970a96aa3bSJed Brown #endif 3298792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_neighbor, (q, l, &nq)); 3299792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq)); 33000a96aa3bSJed Brown if (isInside) { 33010a96aa3bSJed Brown if (baseLabel) { 33029566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 33030a96aa3bSJed Brown } else { 33040a96aa3bSJed Brown val = t + cStartBase; 33050a96aa3bSJed Brown } 33069566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33070a96aa3bSJed Brown } else { 33080a96aa3bSJed Brown int isOutside; 33090a96aa3bSJed Brown 3310792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p4est_quadrant_is_outside_face, (&nq)); 33110a96aa3bSJed Brown if (isOutside) { 33120a96aa3bSJed Brown PetscInt f = -1; 33130a96aa3bSJed Brown 33140a96aa3bSJed Brown if (nq.x < 0) { 33150a96aa3bSJed Brown f = 0; 33160a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 33170a96aa3bSJed Brown f = 1; 33180a96aa3bSJed Brown } else if (nq.y < 0) { 33190a96aa3bSJed Brown f = 2; 33200a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 33210a96aa3bSJed Brown f = 3; 33220a96aa3bSJed Brown #if defined(P4_TO_P8) 33230a96aa3bSJed Brown } else if (nq.z < 0) { 33240a96aa3bSJed Brown f = 4; 33250a96aa3bSJed Brown } else { 33260a96aa3bSJed Brown f = 5; 33270a96aa3bSJed Brown #endif 33280a96aa3bSJed Brown } 33290a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 33300a96aa3bSJed Brown if (baseLabel) { 33319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val)); 33320a96aa3bSJed Brown } else { 33330a96aa3bSJed Brown val = f + fStartBase; 33340a96aa3bSJed Brown } 33359566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33360a96aa3bSJed Brown continue; 33370a96aa3bSJed Brown } 33380a96aa3bSJed Brown #if defined(P4_TO_P8) 3339792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p8est_quadrant_is_outside_edge, (&nq)); 33400a96aa3bSJed Brown if (isOutside) { 33410a96aa3bSJed Brown /* outside edge */ 33420a96aa3bSJed Brown PetscInt e = -1; 33430a96aa3bSJed Brown 33440a96aa3bSJed Brown if (nq.x >= 0 && nq.x < P4EST_ROOT_LEN) { 33450a96aa3bSJed Brown if (nq.z < 0) { 33460a96aa3bSJed Brown if (nq.y < 0) { 33470a96aa3bSJed Brown e = 0; 33480a96aa3bSJed Brown } else { 33490a96aa3bSJed Brown e = 1; 33500a96aa3bSJed Brown } 33510a96aa3bSJed Brown } else { 33520a96aa3bSJed Brown if (nq.y < 0) { 33530a96aa3bSJed Brown e = 2; 33540a96aa3bSJed Brown } else { 33550a96aa3bSJed Brown e = 3; 33560a96aa3bSJed Brown } 33570a96aa3bSJed Brown } 33580a96aa3bSJed Brown } else if (nq.y >= 0 && nq.y < P4EST_ROOT_LEN) { 33590a96aa3bSJed Brown if (nq.z < 0) { 33600a96aa3bSJed Brown if (nq.x < 0) { 33610a96aa3bSJed Brown e = 4; 33620a96aa3bSJed Brown } else { 33630a96aa3bSJed Brown e = 5; 33640a96aa3bSJed Brown } 33650a96aa3bSJed Brown } else { 33660a96aa3bSJed Brown if (nq.x < 0) { 33670a96aa3bSJed Brown e = 6; 33680a96aa3bSJed Brown } else { 33690a96aa3bSJed Brown e = 7; 33700a96aa3bSJed Brown } 33710a96aa3bSJed Brown } 33720a96aa3bSJed Brown } else { 33730a96aa3bSJed Brown if (nq.y < 0) { 33740a96aa3bSJed Brown if (nq.x < 0) { 33750a96aa3bSJed Brown e = 8; 33760a96aa3bSJed Brown } else { 33770a96aa3bSJed Brown e = 9; 33780a96aa3bSJed Brown } 33790a96aa3bSJed Brown } else { 33800a96aa3bSJed Brown if (nq.x < 0) { 33810a96aa3bSJed Brown e = 10; 33820a96aa3bSJed Brown } else { 33830a96aa3bSJed Brown e = 11; 33840a96aa3bSJed Brown } 33850a96aa3bSJed Brown } 33860a96aa3bSJed Brown } 33870a96aa3bSJed Brown 33880a96aa3bSJed Brown e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + e]; 33890a96aa3bSJed Brown if (baseLabel) { 33909566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, e + eStartBase, &val)); 33910a96aa3bSJed Brown } else { 33920a96aa3bSJed Brown val = e + eStartBase; 33930a96aa3bSJed Brown } 33949566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33950a96aa3bSJed Brown continue; 33960a96aa3bSJed Brown } 33970a96aa3bSJed Brown #endif 33980a96aa3bSJed Brown { 33990a96aa3bSJed Brown /* outside vertex: same corner as quadrant corner */ 34000a96aa3bSJed Brown PetscInt v = pforest->topo->conn->tree_to_corner[P4EST_CHILDREN * t + l]; 34010a96aa3bSJed Brown 34020a96aa3bSJed Brown if (baseLabel) { 34039566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, v + vStartBase, &val)); 34040a96aa3bSJed Brown } else { 34050a96aa3bSJed Brown val = v + vStartBase; 34060a96aa3bSJed Brown } 34079566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 34080a96aa3bSJed Brown } 34090a96aa3bSJed Brown } 34100a96aa3bSJed Brown } 34110a96aa3bSJed Brown } 34120a96aa3bSJed Brown next = next->next; 34130a96aa3bSJed Brown } 34140a96aa3bSJed Brown PetscFunctionReturn(0); 34150a96aa3bSJed Brown } 34160a96aa3bSJed Brown 34179371c9d4SSatish Balay static PetscErrorCode DMPforestLabelsFinalize(DM dm, DM plex) { 34180a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 34190a96aa3bSJed Brown DM adapt; 34200a96aa3bSJed Brown 34210a96aa3bSJed Brown PetscFunctionBegin; 34220a96aa3bSJed Brown if (pforest->labelsFinalized) PetscFunctionReturn(0); 34230a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 34249566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm, &adapt)); 34250a96aa3bSJed Brown if (!adapt) { 34260a96aa3bSJed Brown /* Initialize labels from the base dm */ 34279566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsInitialize(dm, plex)); 34280a96aa3bSJed Brown } else { 34290a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1}; 34300a96aa3bSJed Brown PetscSF transferForward, transferBackward, pointSF; 34310a96aa3bSJed Brown PetscInt pStart, pEnd, pStartA, pEndA; 34320a96aa3bSJed Brown PetscInt *values, *adaptValues; 34330a96aa3bSJed Brown DMLabelLink next = adapt->labels; 34340a96aa3bSJed Brown DMLabel adaptLabel; 34350a96aa3bSJed Brown DM adaptPlex; 34360a96aa3bSJed Brown 34379566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm, &adaptLabel)); 34389566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(adapt, &adaptPlex)); 34399566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(adapt, dm, dofPerDim, &transferForward, &transferBackward)); 34409566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &pStart, &pEnd)); 34419566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(adaptPlex, &pStartA, &pEndA)); 34429566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &values, pEndA - pStartA, &adaptValues)); 34439566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plex, &pointSF)); 34440a96aa3bSJed Brown if (PetscDefined(USE_DEBUG)) { 34450a96aa3bSJed Brown PetscInt p; 34460a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) adaptValues[p - pStartA] = -1; 34470a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p - pStart] = -2; 34480a96aa3bSJed Brown if (transferForward) { 34499566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 34509566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 34510a96aa3bSJed Brown } 34520a96aa3bSJed Brown if (transferBackward) { 345357168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 345457168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 34550a96aa3bSJed Brown } 34560a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 34570a96aa3bSJed Brown PetscInt q = p, parent; 34580a96aa3bSJed Brown 34599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 34600a96aa3bSJed Brown while (parent != q) { 34610a96aa3bSJed Brown if (values[parent] == -2) values[parent] = values[q]; 34620a96aa3bSJed Brown q = parent; 34639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 34640a96aa3bSJed Brown } 34650a96aa3bSJed Brown } 346657168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, values, values, MPI_MAX)); 346757168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, values, values, MPI_MAX)); 34689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 34699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 3470ad540459SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCheck(values[p - pStart] != -2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "uncovered point %" PetscInt_FMT, p); 34710a96aa3bSJed Brown } 34720a96aa3bSJed Brown while (next) { 34730a96aa3bSJed Brown DMLabel nextLabel = next->label; 34740a96aa3bSJed Brown const char *name; 34750a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 34760a96aa3bSJed Brown DMLabel label; 34770a96aa3bSJed Brown PetscInt p; 34780a96aa3bSJed Brown 34799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)nextLabel, &name)); 34809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 34810a96aa3bSJed Brown if (isDepth) { 34820a96aa3bSJed Brown next = next->next; 34830a96aa3bSJed Brown continue; 34840a96aa3bSJed Brown } 34859566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 34860a96aa3bSJed Brown if (isCellType) { 34870a96aa3bSJed Brown next = next->next; 34880a96aa3bSJed Brown continue; 34890a96aa3bSJed Brown } 34909566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 34910a96aa3bSJed Brown if (isGhost) { 34920a96aa3bSJed Brown next = next->next; 34930a96aa3bSJed Brown continue; 34940a96aa3bSJed Brown } 34959566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 34960a96aa3bSJed Brown if (isVTK) { 34970a96aa3bSJed Brown next = next->next; 34980a96aa3bSJed Brown continue; 34990a96aa3bSJed Brown } 35000a96aa3bSJed Brown if (nextLabel == adaptLabel) { 35010a96aa3bSJed Brown next = next->next; 35020a96aa3bSJed Brown continue; 35030a96aa3bSJed Brown } 35040a96aa3bSJed Brown /* label was created earlier */ 35059566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 350648a46eb9SPierre Jolivet for (p = pStartA; p < pEndA; p++) PetscCall(DMLabelGetValue(nextLabel, p, &adaptValues[p])); 35070a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p] = PETSC_MIN_INT; 35080a96aa3bSJed Brown 35091baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastBegin(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 351057168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceBegin(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 35111baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastEnd(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 351257168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceEnd(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 35130a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 35140a96aa3bSJed Brown PetscInt q = p, parent; 35150a96aa3bSJed Brown 35169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35170a96aa3bSJed Brown while (parent != q) { 35180a96aa3bSJed Brown if (values[parent] == PETSC_MIN_INT) values[parent] = values[q]; 35190a96aa3bSJed Brown q = parent; 35209566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35210a96aa3bSJed Brown } 35220a96aa3bSJed Brown } 352357168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, values, values, MPI_MAX)); 352457168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, values, values, MPI_MAX)); 35259566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 35269566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 35270a96aa3bSJed Brown 352848a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMLabelSetValue(label, p, values[p])); 35290a96aa3bSJed Brown next = next->next; 35300a96aa3bSJed Brown } 35319566063dSJacob Faibussowitsch PetscCall(PetscFree2(values, adaptValues)); 35329566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferForward)); 35339566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferBackward)); 35340a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 35350a96aa3bSJed Brown } 35360a96aa3bSJed Brown PetscFunctionReturn(0); 35370a96aa3bSJed Brown } 35380a96aa3bSJed Brown 35399371c9d4SSatish Balay static PetscErrorCode DMPforestMapCoordinates_Cell(DM plex, p4est_geometry_t *geom, PetscInt cell, p4est_quadrant_t *q, p4est_topidx_t t, p4est_connectivity_t *conn, PetscScalar *coords) { 35400a96aa3bSJed Brown PetscInt closureSize, c, coordStart, coordEnd, coordDim; 35410a96aa3bSJed Brown PetscInt *closure = NULL; 35420a96aa3bSJed Brown PetscSection coordSec; 35430a96aa3bSJed Brown 35440a96aa3bSJed Brown PetscFunctionBegin; 35459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &coordSec)); 35469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec, &coordStart, &coordEnd)); 35479566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex, &coordDim)); 35489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, cell, PETSC_TRUE, &closureSize, &closure)); 35490a96aa3bSJed Brown for (c = 0; c < closureSize; c++) { 35500a96aa3bSJed Brown PetscInt point = closure[2 * c]; 35510a96aa3bSJed Brown 35520a96aa3bSJed Brown if (point >= coordStart && point < coordEnd) { 35530a96aa3bSJed Brown PetscInt dof, off; 35540a96aa3bSJed Brown PetscInt nCoords, i; 35559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec, point, &dof)); 355608401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Did not understand coordinate layout"); 35570a96aa3bSJed Brown nCoords = dof / coordDim; 35589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec, point, &off)); 35590a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 35600a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 35610a96aa3bSJed Brown double coordP4est[3] = {0.}; 35620a96aa3bSJed Brown double coordP4estMapped[3] = {0.}; 35630a96aa3bSJed Brown PetscInt j; 35640a96aa3bSJed Brown PetscReal treeCoords[P4EST_CHILDREN][3] = {{0.}}; 35650a96aa3bSJed Brown PetscReal eta[3] = {0.}; 35660a96aa3bSJed Brown PetscInt numRounds = 10; 35670a96aa3bSJed Brown PetscReal coordGuess[3] = {0.}; 35680a96aa3bSJed Brown 35690a96aa3bSJed Brown eta[0] = (PetscReal)q->x / (PetscReal)P4EST_ROOT_LEN; 35700a96aa3bSJed Brown eta[1] = (PetscReal)q->y / (PetscReal)P4EST_ROOT_LEN; 35710a96aa3bSJed Brown #if defined(P4_TO_P8) 35720a96aa3bSJed Brown eta[2] = (PetscReal)q->z / (PetscReal)P4EST_ROOT_LEN; 35730a96aa3bSJed Brown #endif 35740a96aa3bSJed Brown 35750a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 35760a96aa3bSJed Brown PetscInt k; 35770a96aa3bSJed Brown 35780a96aa3bSJed Brown for (k = 0; k < 3; k++) treeCoords[j][k] = conn->vertices[3 * conn->tree_to_vertex[P4EST_CHILDREN * t + j] + k]; 35790a96aa3bSJed Brown } 35800a96aa3bSJed Brown 35810a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 35820a96aa3bSJed Brown PetscInt k; 35830a96aa3bSJed Brown PetscReal prod = 1.; 35840a96aa3bSJed Brown 35850a96aa3bSJed Brown for (k = 0; k < P4EST_DIM; k++) prod *= (j & (1 << k)) ? eta[k] : (1. - eta[k]); 35860a96aa3bSJed Brown for (k = 0; k < 3; k++) coordGuess[k] += prod * treeCoords[j][k]; 35870a96aa3bSJed Brown } 35880a96aa3bSJed Brown 35890a96aa3bSJed Brown for (j = 0; j < numRounds; j++) { 35900a96aa3bSJed Brown PetscInt dir; 35910a96aa3bSJed Brown 35920a96aa3bSJed Brown for (dir = 0; dir < P4EST_DIM; dir++) { 35930a96aa3bSJed Brown PetscInt k; 35940a96aa3bSJed Brown PetscReal diff[3]; 35950a96aa3bSJed Brown PetscReal dXdeta[3] = {0.}; 35960a96aa3bSJed Brown PetscReal rhs, scale, update; 35970a96aa3bSJed Brown 35980a96aa3bSJed Brown for (k = 0; k < 3; k++) diff[k] = coordP4est[k] - coordGuess[k]; 35990a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 36000a96aa3bSJed Brown PetscInt l; 36010a96aa3bSJed Brown PetscReal prod = 1.; 36020a96aa3bSJed Brown 36030a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) { 36040a96aa3bSJed Brown if (l == dir) { 36050a96aa3bSJed Brown prod *= (k & (1 << l)) ? 1. : -1.; 36060a96aa3bSJed Brown } else { 36070a96aa3bSJed Brown prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 36080a96aa3bSJed Brown } 36090a96aa3bSJed Brown } 36100a96aa3bSJed Brown for (l = 0; l < 3; l++) dXdeta[l] += prod * treeCoords[k][l]; 36110a96aa3bSJed Brown } 36120a96aa3bSJed Brown rhs = 0.; 36130a96aa3bSJed Brown scale = 0; 36140a96aa3bSJed Brown for (k = 0; k < 3; k++) { 36150a96aa3bSJed Brown rhs += diff[k] * dXdeta[k]; 36160a96aa3bSJed Brown scale += dXdeta[k] * dXdeta[k]; 36170a96aa3bSJed Brown } 36180a96aa3bSJed Brown update = rhs / scale; 36190a96aa3bSJed Brown eta[dir] += update; 36200a96aa3bSJed Brown eta[dir] = PetscMin(eta[dir], 1.); 36210a96aa3bSJed Brown eta[dir] = PetscMax(eta[dir], 0.); 36220a96aa3bSJed Brown 36230a96aa3bSJed Brown coordGuess[0] = coordGuess[1] = coordGuess[2] = 0.; 36240a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 36250a96aa3bSJed Brown PetscInt l; 36260a96aa3bSJed Brown PetscReal prod = 1.; 36270a96aa3bSJed Brown 36280a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 36290a96aa3bSJed Brown for (l = 0; l < 3; l++) coordGuess[l] += prod * treeCoords[k][l]; 36300a96aa3bSJed Brown } 36310a96aa3bSJed Brown } 36320a96aa3bSJed Brown } 36330a96aa3bSJed Brown for (j = 0; j < 3; j++) coordP4est[j] = (double)eta[j]; 36340a96aa3bSJed Brown 36350a96aa3bSJed Brown if (geom) { 36360a96aa3bSJed Brown (geom->X)(geom, t, coordP4est, coordP4estMapped); 36370a96aa3bSJed Brown for (j = 0; j < coordDim; j++) coord[j] = (PetscScalar)coordP4estMapped[j]; 36380a96aa3bSJed Brown } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded"); 36390a96aa3bSJed Brown } 36400a96aa3bSJed Brown } 36410a96aa3bSJed Brown } 36429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, cell, PETSC_TRUE, &closureSize, &closure)); 36430a96aa3bSJed Brown PetscFunctionReturn(0); 36440a96aa3bSJed Brown } 36450a96aa3bSJed Brown 36469371c9d4SSatish Balay static PetscErrorCode DMPforestMapCoordinates(DM dm, DM plex) { 36470a96aa3bSJed Brown DM_Forest *forest; 36480a96aa3bSJed Brown DM_Forest_pforest *pforest; 36490a96aa3bSJed Brown p4est_geometry_t *geom; 36500a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd; 36510a96aa3bSJed Brown Vec coordLocalVec; 36520a96aa3bSJed Brown PetscScalar *coords; 36530a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 36540a96aa3bSJed Brown p4est_tree_t *trees; 36550a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *); 36560a96aa3bSJed Brown void *mapCtx; 36570a96aa3bSJed Brown 36580a96aa3bSJed Brown PetscFunctionBegin; 36590a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 36600a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 36610a96aa3bSJed Brown geom = pforest->topo->geom; 36629566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx)); 36630a96aa3bSJed Brown if (!geom && !map) PetscFunctionReturn(0); 36649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(plex, &coordLocalVec)); 36659566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordLocalVec, &coords)); 36660a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 36670a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 36680a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 36690a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 36700a96aa3bSJed Brown trees = (p4est_tree_t *)pforest->forest->trees->array; 36710a96aa3bSJed Brown if (map) { /* apply the map directly to the existing coordinates */ 36720a96aa3bSJed Brown PetscSection coordSec; 36730a96aa3bSJed Brown PetscInt coordStart, coordEnd, p, coordDim, p4estCoordDim, cStart, cEnd, cEndInterior; 36740a96aa3bSJed Brown DM base; 36750a96aa3bSJed Brown 36769566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 36779566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(plex, &cEndInterior, NULL)); 36780a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 36799566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 36809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &coordSec)); 36819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec, &coordStart, &coordEnd)); 36829566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex, &coordDim)); 36830a96aa3bSJed Brown p4estCoordDim = PetscMin(coordDim, 3); 36840a96aa3bSJed Brown for (p = coordStart; p < coordEnd; p++) { 36850a96aa3bSJed Brown PetscInt *star = NULL, starSize; 36860a96aa3bSJed Brown PetscInt dof, off, cell = -1, coarsePoint = -1; 36870a96aa3bSJed Brown PetscInt nCoords, i; 36889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec, p, &dof)); 368908401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Did not understand coordinate layout"); 36900a96aa3bSJed Brown nCoords = dof / coordDim; 36919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec, p, &off)); 36929566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star)); 36930a96aa3bSJed Brown for (i = 0; i < starSize; i++) { 36940a96aa3bSJed Brown PetscInt point = star[2 * i]; 36950a96aa3bSJed Brown 36960a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 36970a96aa3bSJed Brown cell = point; 36980a96aa3bSJed Brown break; 36990a96aa3bSJed Brown } 37000a96aa3bSJed Brown } 37019566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star)); 37020a96aa3bSJed Brown if (cell >= 0) { 37030a96aa3bSJed Brown if (cell < cLocalStart) { 37040a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37050a96aa3bSJed Brown 37060a96aa3bSJed Brown coarsePoint = ghosts[cell].p.which_tree; 37070a96aa3bSJed Brown } else if (cell < cLocalEnd) { 37080a96aa3bSJed Brown cell -= cLocalStart; 37090a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 37100a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 37110a96aa3bSJed Brown 37120a96aa3bSJed Brown if (cell >= tree->quadrants_offset && (size_t)cell < tree->quadrants_offset + tree->quadrants.elem_count) { 37130a96aa3bSJed Brown coarsePoint = t; 37140a96aa3bSJed Brown break; 37150a96aa3bSJed Brown } 37160a96aa3bSJed Brown } 37170a96aa3bSJed Brown } else { 37180a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37190a96aa3bSJed Brown 37200a96aa3bSJed Brown coarsePoint = ghosts[cell - cLocalEnd].p.which_tree; 37210a96aa3bSJed Brown } 37220a96aa3bSJed Brown } 37230a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 37240a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 37250a96aa3bSJed Brown PetscReal coordP4est[3] = {0.}; 37260a96aa3bSJed Brown PetscReal coordP4estMapped[3] = {0.}; 37270a96aa3bSJed Brown PetscInt j; 37280a96aa3bSJed Brown 37290a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coordP4est[j] = PetscRealPart(coord[j]); 37309566063dSJacob Faibussowitsch PetscCall((map)(base, coarsePoint, p4estCoordDim, coordP4est, coordP4estMapped, mapCtx)); 37310a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coord[j] = (PetscScalar)coordP4estMapped[j]; 37320a96aa3bSJed Brown } 37330a96aa3bSJed Brown } 37340a96aa3bSJed Brown } else { /* we have to transform coordinates back to the unit cube (where geom is defined), and then apply geom */ 37350a96aa3bSJed Brown PetscInt cStart, cEnd, cEndInterior; 37360a96aa3bSJed Brown 37379566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 37389566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(plex, &cEndInterior, NULL)); 37390a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 37400a96aa3bSJed Brown if (cLocalStart > 0) { 37410a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37420a96aa3bSJed Brown PetscInt count; 37430a96aa3bSJed Brown 37440a96aa3bSJed Brown for (count = 0; count < cLocalStart; count++) { 37450a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count]; 37460a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 37470a96aa3bSJed Brown 37489566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count, quad, t, pforest->topo->conn, coords)); 37490a96aa3bSJed Brown } 37500a96aa3bSJed Brown } 37510a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 37520a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 37530a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset, i; 37540a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 37550a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 37560a96aa3bSJed Brown 37570a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 37580a96aa3bSJed Brown PetscInt count = i + offset; 37590a96aa3bSJed Brown 37609566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count, &quads[i], t, pforest->topo->conn, coords)); 37610a96aa3bSJed Brown } 37620a96aa3bSJed Brown } 37630a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 37640a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37650a96aa3bSJed Brown PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count; 37660a96aa3bSJed Brown PetscInt count; 37670a96aa3bSJed Brown 37680a96aa3bSJed Brown for (count = 0; count < numGhosts - cLocalStart; count++) { 37690a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 37700a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 37710a96aa3bSJed Brown 37729566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count + cLocalEnd, quad, t, pforest->topo->conn, coords)); 37730a96aa3bSJed Brown } 37740a96aa3bSJed Brown } 37750a96aa3bSJed Brown } 37769566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordLocalVec, &coords)); 37770a96aa3bSJed Brown PetscFunctionReturn(0); 37780a96aa3bSJed Brown } 37790a96aa3bSJed Brown 37809371c9d4SSatish Balay static PetscErrorCode PforestQuadrantIsInterior(p4est_quadrant_t *quad, PetscBool *is_interior) { 3781852b71a7SToby Isaac PetscFunctionBegin; 3782852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level); 3783852b71a7SToby Isaac if ((quad->x > 0) && (quad->x + h < P4EST_ROOT_LEN) 3784852b71a7SToby Isaac #ifdef P4_TO_P8 3785852b71a7SToby Isaac && (quad->z > 0) && (quad->z + h < P4EST_ROOT_LEN) 3786852b71a7SToby Isaac #endif 3787852b71a7SToby Isaac && (quad->y > 0) && (quad->y + h < P4EST_ROOT_LEN)) { 3788852b71a7SToby Isaac *is_interior = PETSC_TRUE; 3789852b71a7SToby Isaac } else { 3790852b71a7SToby Isaac *is_interior = PETSC_FALSE; 3791852b71a7SToby Isaac } 3792852b71a7SToby Isaac PetscFunctionReturn(0); 3793852b71a7SToby Isaac } 3794852b71a7SToby Isaac 3795852b71a7SToby Isaac /* We always use DG coordinates with p4est: if they do not match the vertex 3796852b71a7SToby Isaac coordinates, add space for them in the section */ 37979371c9d4SSatish Balay static PetscErrorCode PforestCheckLocalizeCell(DM plex, PetscInt cDim, Vec cVecOld, DM_Forest_pforest *pforest, PetscSection oldSection, PetscSection newSection, PetscInt cell, PetscInt coarsePoint, p4est_quadrant_t *quad) { 3798852b71a7SToby Isaac PetscBool is_interior; 3799852b71a7SToby Isaac 3800852b71a7SToby Isaac PetscFunctionBegin; 3801852b71a7SToby Isaac PetscCall(PforestQuadrantIsInterior(quad, &is_interior)); 3802852b71a7SToby Isaac if (is_interior) { // quads in the interior of a coarse cell can't touch periodic interfaces 3803852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3804852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3805852b71a7SToby Isaac } else { 3806852b71a7SToby Isaac PetscInt cSize; 3807852b71a7SToby Isaac PetscScalar *values = NULL; 3808852b71a7SToby Isaac PetscBool same_coords = PETSC_TRUE; 3809852b71a7SToby Isaac 3810852b71a7SToby Isaac PetscCall(DMPlexVecGetClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3811852b71a7SToby Isaac PetscAssert(cSize == cDim * P4EST_CHILDREN, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected closure size"); 3812852b71a7SToby Isaac for (int c = 0; c < P4EST_CHILDREN; c++) { 3813852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3814852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level); 3815852b71a7SToby Isaac double corner_coords[3]; 3816852b71a7SToby Isaac double vert_coords[3]; 3817852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 3818852b71a7SToby Isaac 3819ad540459SPierre Jolivet for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) vert_coords[d] = PetscRealPart(values[c * cDim + d]); 3820852b71a7SToby Isaac 3821852b71a7SToby Isaac quad_coords[0] = quad->x; 3822852b71a7SToby Isaac quad_coords[1] = quad->y; 3823852b71a7SToby Isaac #ifdef P4_TO_P8 3824852b71a7SToby Isaac quad_coords[2] = quad->z; 3825852b71a7SToby Isaac #endif 3826ad540459SPierre Jolivet for (int d = 0; d < 3; d++) quad_coords[d] += (corner & (1 << d)) ? h : 0; 3827852b71a7SToby Isaac #ifndef P4_TO_P8 3828648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 3829852b71a7SToby Isaac #else 3830648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 3831852b71a7SToby Isaac #endif 3832852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) { 3833852b71a7SToby Isaac if (fabs(vert_coords[d] - corner_coords[d]) > PETSC_SMALL) { 3834852b71a7SToby Isaac same_coords = PETSC_FALSE; 3835852b71a7SToby Isaac break; 3836852b71a7SToby Isaac } 3837852b71a7SToby Isaac } 3838852b71a7SToby Isaac } 3839852b71a7SToby Isaac if (same_coords) { 3840852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3841852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3842852b71a7SToby Isaac } else { 3843852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, cSize)); 3844852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, cSize)); 3845852b71a7SToby Isaac } 3846852b71a7SToby Isaac PetscCall(DMPlexVecRestoreClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3847852b71a7SToby Isaac } 3848852b71a7SToby Isaac PetscFunctionReturn(0); 3849852b71a7SToby Isaac } 3850852b71a7SToby Isaac 38519371c9d4SSatish Balay static PetscErrorCode PforestLocalizeCell(DM plex, PetscInt cDim, DM_Forest_pforest *pforest, PetscSection newSection, PetscInt cell, PetscInt coarsePoint, p4est_quadrant_t *quad, PetscScalar coords[]) { 3852852b71a7SToby Isaac PetscInt cdof, off; 3853852b71a7SToby Isaac 3854852b71a7SToby Isaac PetscFunctionBegin; 3855852b71a7SToby Isaac PetscCall(PetscSectionGetDof(newSection, cell, &cdof)); 3856852b71a7SToby Isaac if (!cdof) PetscFunctionReturn(0); 3857852b71a7SToby Isaac 3858852b71a7SToby Isaac PetscCall(PetscSectionGetOffset(newSection, cell, &off)); 3859852b71a7SToby Isaac for (PetscInt c = 0, pos = off; c < P4EST_CHILDREN; c++) { 3860852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3861852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level); 3862852b71a7SToby Isaac double corner_coords[3]; 3863852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 3864852b71a7SToby Isaac 3865852b71a7SToby Isaac quad_coords[0] = quad->x; 3866852b71a7SToby Isaac quad_coords[1] = quad->y; 3867852b71a7SToby Isaac #ifdef P4_TO_P8 3868852b71a7SToby Isaac quad_coords[2] = quad->z; 3869852b71a7SToby Isaac #endif 3870ad540459SPierre Jolivet for (int d = 0; d < 3; d++) quad_coords[d] += (corner & (1 << d)) ? h : 0; 3871852b71a7SToby Isaac #ifndef P4_TO_P8 3872648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 3873852b71a7SToby Isaac #else 3874648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 3875852b71a7SToby Isaac #endif 3876ad540459SPierre Jolivet for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) coords[pos++] = corner_coords[d]; 3877ad540459SPierre Jolivet for (PetscInt d = PetscMin(cDim, 3); d < cDim; d++) coords[pos++] = 0.; 3878852b71a7SToby Isaac } 3879852b71a7SToby Isaac PetscFunctionReturn(0); 3880852b71a7SToby Isaac } 3881852b71a7SToby Isaac 38829371c9d4SSatish Balay static PetscErrorCode DMPforestLocalizeCoordinates(DM dm, DM plex) { 38830a96aa3bSJed Brown DM_Forest *forest; 38840a96aa3bSJed Brown DM_Forest_pforest *pforest; 38856858538eSMatthew G. Knepley DM base, cdm, cdmCell; 3886852b71a7SToby Isaac Vec cVec, cVecOld; 3887852b71a7SToby Isaac PetscSection oldSection, newSection; 38880a96aa3bSJed Brown PetscScalar *coords2; 38896858538eSMatthew G. Knepley const PetscReal *L; 38900a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, coarsePoint; 3891852b71a7SToby Isaac PetscInt cDim, newStart, newEnd; 3892852b71a7SToby Isaac PetscInt v, vStart, vEnd, cp, cStart, cEnd, cEndInterior; 38930a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 38940a96aa3bSJed Brown p4est_tree_t *trees; 38956858538eSMatthew G. Knepley PetscBool baseLocalized = PETSC_FALSE; 38960a96aa3bSJed Brown 38970a96aa3bSJed Brown PetscFunctionBegin; 38984fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, NULL, NULL, &L)); 38990a96aa3bSJed Brown /* we localize on all cells if we don't have a base DM or the base DM coordinates have not been localized */ 39009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cDim)); 39019566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 39026858538eSMatthew G. Knepley if (base) PetscCall(DMGetCoordinatesLocalized(base, &baseLocalized)); 39030a96aa3bSJed Brown if (!baseLocalized) base = NULL; 39046858538eSMatthew G. Knepley if (!baseLocalized && !L) PetscFunctionReturn(0); 39059566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &newStart, &newEnd)); 39060a96aa3bSJed Brown 39079566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newSection)); 39089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(newSection, 1)); 39099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(newSection, 0, cDim)); 39109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSection, newStart, newEnd)); 39110a96aa3bSJed Brown 39129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &oldSection)); 39139566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd)); 3914852b71a7SToby Isaac PetscCall(DMGetCoordinatesLocal(plex, &cVecOld)); 39150a96aa3bSJed Brown 39160a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 39170a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 39180a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 39190a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 39200a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 39210a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 39220a96aa3bSJed Brown trees = (p4est_tree_t *)pforest->forest->trees->array; 39230a96aa3bSJed Brown 39249566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 39259566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(plex, &cEndInterior, NULL)); 39260a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 3927852b71a7SToby Isaac cp = 0; 39280a96aa3bSJed Brown if (cLocalStart > 0) { 39290a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 3930852b71a7SToby Isaac PetscInt cell; 39310a96aa3bSJed Brown 3932852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 3933852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 3934852b71a7SToby Isaac 39350a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 3936852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 39370a96aa3bSJed Brown } 39380a96aa3bSJed Brown } 39390a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 39400a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 39410a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 39420a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 3943852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 39440a96aa3bSJed Brown PetscInt i; 39450a96aa3bSJed Brown 39460a96aa3bSJed Brown if (!numQuads) continue; 39470a96aa3bSJed Brown coarsePoint = t; 3948852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 3949852b71a7SToby Isaac PetscInt cell = i + offset; 3950852b71a7SToby Isaac p4est_quadrant_t *quad = &quads[i]; 39510a96aa3bSJed Brown 3952852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 39530a96aa3bSJed Brown } 39540a96aa3bSJed Brown } 39550a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 39560a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 39570a96aa3bSJed Brown PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count; 39580a96aa3bSJed Brown PetscInt count; 39590a96aa3bSJed Brown 3960852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 39610a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 39620a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 3963852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 39640a96aa3bSJed Brown 3965852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 39660a96aa3bSJed Brown } 39670a96aa3bSJed Brown } 3968852b71a7SToby Isaac PetscAssert(cp == cEnd - cStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected number of fine cells %" PetscInt_FMT " != %" PetscInt_FMT, cp, cEnd - cStart); 39690a96aa3bSJed Brown 39709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSection)); 39716858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(plex, &cdm)); 39726858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 39736858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(plex, cdmCell)); 39746858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 39756858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(plex, cDim, newSection)); 39769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &v)); 39779566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &cVec)); 39789566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)cVec, "coordinates")); 39799566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(cVec, cDim)); 39809566063dSJacob Faibussowitsch PetscCall(VecSetSizes(cVec, v, PETSC_DETERMINE)); 39819566063dSJacob Faibussowitsch PetscCall(VecSetType(cVec, VECSTANDARD)); 39829566063dSJacob Faibussowitsch PetscCall(VecSet(cVec, PETSC_MIN_REAL)); 39830a96aa3bSJed Brown 39840a96aa3bSJed Brown /* Localize coordinates on cells if needed */ 39856858538eSMatthew G. Knepley PetscCall(VecGetArray(cVec, &coords2)); 3986852b71a7SToby Isaac cp = 0; 3987852b71a7SToby Isaac if (cLocalStart > 0) { 3988852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 3989852b71a7SToby Isaac PetscInt cell; 3990852b71a7SToby Isaac 3991852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 3992852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 3993852b71a7SToby Isaac 3994852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 3995852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 3996852b71a7SToby Isaac } 3997852b71a7SToby Isaac } 39980a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 39990a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 40000a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 40010a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 4002852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 4003852b71a7SToby Isaac PetscInt i; 40040a96aa3bSJed Brown 40050a96aa3bSJed Brown if (!numQuads) continue; 4006852b71a7SToby Isaac coarsePoint = t; 4007852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 4008852b71a7SToby Isaac PetscInt cell = i + offset; 40090a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[i]; 40100a96aa3bSJed Brown 4011852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 4012852b71a7SToby Isaac } 4013852b71a7SToby Isaac } 4014852b71a7SToby Isaac if (cLocalEnd - cLocalStart < cEnd - cStart) { 4015852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 4016852b71a7SToby Isaac PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count; 4017852b71a7SToby Isaac PetscInt count; 40180a96aa3bSJed Brown 4019852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 4020852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 4021852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 4022852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 40230a96aa3bSJed Brown 4024852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 40250a96aa3bSJed Brown } 40260a96aa3bSJed Brown } 40279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cVec, &coords2)); 40286858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(plex, cVec)); 40299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cVec)); 40309566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newSection)); 40310a96aa3bSJed Brown PetscFunctionReturn(0); 40320a96aa3bSJed Brown } 40330a96aa3bSJed Brown 40340a96aa3bSJed Brown #define DMForestClearAdaptivityForest_pforest _append_pforest(DMForestClearAdaptivityForest) 40359371c9d4SSatish Balay static PetscErrorCode DMForestClearAdaptivityForest_pforest(DM dm) { 40360a96aa3bSJed Brown DM_Forest *forest; 40370a96aa3bSJed Brown DM_Forest_pforest *pforest; 40380a96aa3bSJed Brown 40390a96aa3bSJed Brown PetscFunctionBegin; 40400a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 40410a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 40429566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&(pforest->pointAdaptToSelfSF))); 40439566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&(pforest->pointSelfToAdaptSF))); 40449566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 40459566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 40460a96aa3bSJed Brown PetscFunctionReturn(0); 40470a96aa3bSJed Brown } 40480a96aa3bSJed Brown 40499371c9d4SSatish Balay static PetscErrorCode DMConvert_pforest_plex(DM dm, DMType newtype, DM *plex) { 40500a96aa3bSJed Brown DM_Forest *forest; 40510a96aa3bSJed Brown DM_Forest_pforest *pforest; 40520a96aa3bSJed Brown DM refTree, newPlex, base; 40530a96aa3bSJed Brown PetscInt adjDim, adjCodim, coordDim; 40540a96aa3bSJed Brown MPI_Comm comm; 40550a96aa3bSJed Brown PetscBool isPforest; 40560a96aa3bSJed Brown PetscInt dim; 40570a96aa3bSJed Brown PetscInt overlap; 40580a96aa3bSJed Brown p4est_connect_type_t ctype; 40590a96aa3bSJed Brown p4est_locidx_t first_local_quad = -1; 40600a96aa3bSJed Brown sc_array_t *points_per_dim, *cone_sizes, *cones, *cone_orientations, *coords, *children, *parents, *childids, *leaves, *remotes; 40610a96aa3bSJed Brown PetscSection parentSection; 40620a96aa3bSJed Brown PetscSF pointSF; 40630a96aa3bSJed Brown size_t zz, count; 40640a96aa3bSJed Brown PetscInt pStart, pEnd; 40650a96aa3bSJed Brown DMLabel ghostLabelBase = NULL; 40660a96aa3bSJed Brown 40670a96aa3bSJed Brown PetscFunctionBegin; 40680a96aa3bSJed Brown 40690a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40700a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 40719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPFOREST, &isPforest)); 407228b400f6SJacob Faibussowitsch PetscCheck(isPforest, comm, PETSC_ERR_ARG_WRONG, "Expected DM type %s, got %s", DMPFOREST, ((PetscObject)dm)->type_name); 40739566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 407463a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM, comm, PETSC_ERR_ARG_WRONG, "Expected DM dimension %d, got %" PetscInt_FMT, P4EST_DIM, dim); 40750a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 40760a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 40779566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 407848a46eb9SPierre Jolivet if (base) PetscCall(DMGetLabel(base, "ghost", &ghostLabelBase)); 40790a96aa3bSJed Brown if (!pforest->plex) { 40800a96aa3bSJed Brown PetscMPIInt size; 40810a96aa3bSJed Brown 40829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 40839566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &newPlex)); 40849566063dSJacob Faibussowitsch PetscCall(DMSetType(newPlex, DMPLEX)); 40859566063dSJacob Faibussowitsch PetscCall(DMSetMatType(newPlex, dm->mattype)); 40860a96aa3bSJed Brown /* share labels */ 40879566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, newPlex, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 40889566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyDimension(dm, &adjDim)); 40899566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyCodimension(dm, &adjCodim)); 40909566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim)); 40910a96aa3bSJed Brown if (adjDim == 0) { 40920a96aa3bSJed Brown ctype = P4EST_CONNECT_FULL; 40930a96aa3bSJed Brown } else if (adjCodim == 1) { 40940a96aa3bSJed Brown ctype = P4EST_CONNECT_FACE; 40950a96aa3bSJed Brown #if defined(P4_TO_P8) 40960a96aa3bSJed Brown } else if (adjDim == 1) { 40970a96aa3bSJed Brown ctype = P8EST_CONNECT_EDGE; 40980a96aa3bSJed Brown #endif 40990a96aa3bSJed Brown } else { 410063a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid adjacency dimension %" PetscInt_FMT, adjDim); 41010a96aa3bSJed Brown } 410263a3b9bcSJacob Faibussowitsch PetscCheck(ctype == P4EST_CONNECT_FULL, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Adjacency dimension %" PetscInt_FMT " / codimension %" PetscInt_FMT " not supported yet", adjDim, adjCodim); 41039566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 410460667520SVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(newPlex, NULL, overlap)); 41050a96aa3bSJed Brown 41060a96aa3bSJed Brown points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 41070a96aa3bSJed Brown cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 41080a96aa3bSJed Brown cones = sc_array_new(sizeof(p4est_locidx_t)); 41090a96aa3bSJed Brown cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 41100a96aa3bSJed Brown coords = sc_array_new(3 * sizeof(double)); 41110a96aa3bSJed Brown children = sc_array_new(sizeof(p4est_locidx_t)); 41120a96aa3bSJed Brown parents = sc_array_new(sizeof(p4est_locidx_t)); 41130a96aa3bSJed Brown childids = sc_array_new(sizeof(p4est_locidx_t)); 41140a96aa3bSJed Brown leaves = sc_array_new(sizeof(p4est_locidx_t)); 41150a96aa3bSJed Brown remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 41160a96aa3bSJed Brown 4117792fecdfSBarry Smith PetscCallP4est(p4est_get_plex_data_ext, (pforest->forest, &pforest->ghost, &pforest->lnodes, ctype, (int)((size > 1) ? overlap : 0), &first_local_quad, points_per_dim, cone_sizes, cones, cone_orientations, coords, children, parents, childids, leaves, remotes, 1)); 41180a96aa3bSJed Brown 41190a96aa3bSJed Brown pforest->cLocalStart = (PetscInt)first_local_quad; 41200a96aa3bSJed Brown pforest->cLocalEnd = pforest->cLocalStart + (PetscInt)pforest->forest->local_num_quadrants; 41219566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 41229566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 41239566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 41249566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 41259566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, coordDim)); 41269566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(children)); 41279566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(parents)); 41289566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(childids)); 41299566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(leaves)); 41309566063dSJacob Faibussowitsch PetscCall(locidx_pair_to_PetscSFNode(remotes)); 41310a96aa3bSJed Brown 41329566063dSJacob Faibussowitsch PetscCall(DMSetDimension(newPlex, P4EST_DIM)); 41339566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(newPlex, coordDim)); 41349566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(newPlex, P4EST_DIM - 1)); 41359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(newPlex, P4EST_DIM, (PetscInt *)points_per_dim->array, (PetscInt *)cone_sizes->array, (PetscInt *)cones->array, (PetscInt *)cone_orientations->array, (PetscScalar *)coords->array)); 41369566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(newPlex)); 41379566063dSJacob Faibussowitsch PetscCall(DMCreateReferenceTree_pforest(comm, &refTree)); 41389566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlex, refTree)); 41399566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &parentSection)); 41409566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(newPlex, &pStart, &pEnd)); 41419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd)); 41420a96aa3bSJed Brown count = children->elem_count; 41430a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 41440a96aa3bSJed Brown PetscInt child = *((PetscInt *)sc_array_index(children, zz)); 41450a96aa3bSJed Brown 41469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(parentSection, child, 1)); 41470a96aa3bSJed Brown } 41489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 41499566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(newPlex, parentSection, (PetscInt *)parents->array, (PetscInt *)childids->array)); 41509566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 41519566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &pointSF)); 41520a96aa3bSJed Brown /* 41530a96aa3bSJed Brown These arrays defining the sf are from the p4est library, but the code there shows the leaves being populated in increasing order. 41540a96aa3bSJed Brown https://gitlab.com/petsc/petsc/merge_requests/2248#note_240186391 41550a96aa3bSJed Brown */ 41569566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(pointSF, pEnd - pStart, (PetscInt)leaves->elem_count, (PetscInt *)leaves->array, PETSC_COPY_VALUES, (PetscSFNode *)remotes->array, PETSC_COPY_VALUES)); 41579566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(newPlex, pointSF)); 41589566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 41590a96aa3bSJed Brown { 41600a96aa3bSJed Brown DM coordDM; 41610a96aa3bSJed Brown 41629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex, &coordDM)); 41639566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(coordDM, pointSF)); 41640a96aa3bSJed Brown } 41659566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointSF)); 41660a96aa3bSJed Brown sc_array_destroy(points_per_dim); 41670a96aa3bSJed Brown sc_array_destroy(cone_sizes); 41680a96aa3bSJed Brown sc_array_destroy(cones); 41690a96aa3bSJed Brown sc_array_destroy(cone_orientations); 41700a96aa3bSJed Brown sc_array_destroy(coords); 41710a96aa3bSJed Brown sc_array_destroy(children); 41720a96aa3bSJed Brown sc_array_destroy(parents); 41730a96aa3bSJed Brown sc_array_destroy(childids); 41740a96aa3bSJed Brown sc_array_destroy(leaves); 41750a96aa3bSJed Brown sc_array_destroy(remotes); 41760a96aa3bSJed Brown 41770a96aa3bSJed Brown { 41784fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 41790a96aa3bSJed Brown 41804fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 41814fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(newPlex, maxCell, Lstart, L)); 41829566063dSJacob Faibussowitsch PetscCall(DMPforestLocalizeCoordinates(dm, newPlex)); 41830a96aa3bSJed Brown } 41840a96aa3bSJed Brown 41850a96aa3bSJed Brown if (overlap > 0) { /* the p4est routine can't set all of the coordinates in its routine if there is overlap */ 41860a96aa3bSJed Brown Vec coordsGlobal, coordsLocal; 41870a96aa3bSJed Brown const PetscScalar *globalArray; 41880a96aa3bSJed Brown PetscScalar *localArray; 41890a96aa3bSJed Brown PetscSF coordSF; 41900a96aa3bSJed Brown DM coordDM; 41910a96aa3bSJed Brown 41929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex, &coordDM)); 41939566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(coordDM, &coordSF)); 41949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(newPlex, &coordsGlobal)); 41959566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coordsLocal)); 41969566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordsGlobal, &globalArray)); 41979566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordsLocal, &localArray)); 41989566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coordSF, MPIU_SCALAR, globalArray, localArray, MPI_REPLACE)); 41999566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coordSF, MPIU_SCALAR, globalArray, localArray, MPI_REPLACE)); 42009566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordsLocal, &localArray)); 42019566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordsGlobal, &globalArray)); 42029566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(newPlex, coordsLocal)); 42030a96aa3bSJed Brown } 42049566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates(dm, newPlex)); 42050a96aa3bSJed Brown 42060a96aa3bSJed Brown pforest->plex = newPlex; 42070a96aa3bSJed Brown 42080a96aa3bSJed Brown /* copy labels */ 42099566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsFinalize(dm, newPlex)); 42100a96aa3bSJed Brown 42110a96aa3bSJed Brown if (ghostLabelBase || pforest->ghostName) { /* we have to do this after copying labels because the labels drive the construction of ghost cells */ 42120a96aa3bSJed Brown PetscInt numAdded; 42130a96aa3bSJed Brown DM newPlexGhosted; 42140a96aa3bSJed Brown void *ctx; 42150a96aa3bSJed Brown 42169566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(newPlex, pforest->ghostName, &numAdded, &newPlexGhosted)); 42179566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(newPlex, &ctx)); 42189566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(newPlexGhosted, ctx)); 42190a96aa3bSJed Brown /* we want the sf for the ghost dm to be the one for the p4est dm as well */ 42209566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(newPlexGhosted, &pointSF)); 42219566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 42229566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newPlex)); 42239566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlexGhosted, refTree)); 42249566063dSJacob Faibussowitsch PetscCall(DMForestClearAdaptivityForest_pforest(dm)); 42250a96aa3bSJed Brown newPlex = newPlexGhosted; 42260a96aa3bSJed Brown 42270a96aa3bSJed Brown /* share the labels back */ 42289566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 42299566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(newPlex, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 42300a96aa3bSJed Brown pforest->plex = newPlex; 42310a96aa3bSJed Brown } 42329566063dSJacob Faibussowitsch PetscCall(DMDestroy(&refTree)); 42330a96aa3bSJed Brown if (dm->setfromoptionscalled) { 4234d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)newPlex); 4235dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(newPlex, PetscOptionsObject)); 4236dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)newPlex, PetscOptionsObject)); 4237d0609cedSBarry Smith PetscOptionsEnd(); 42380a96aa3bSJed Brown } 42399566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(newPlex, NULL, "-dm_p4est_plex_view")); 42400a96aa3bSJed Brown { 42416858538eSMatthew G. Knepley DM cdm; 42420a96aa3bSJed Brown PetscSection coordsSec; 42430a96aa3bSJed Brown Vec coords; 42440a96aa3bSJed Brown PetscInt cDim; 42450a96aa3bSJed Brown 42469566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(newPlex, &cDim)); 42479566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(newPlex, &coordsSec)); 42489566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dm, cDim, coordsSec)); 42499566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coords)); 42509566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 42516858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex, &cdm)); 42526858538eSMatthew G. Knepley if (cdm) PetscCall(DMSetCellCoordinateDM(dm, cdm)); 42536858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(newPlex, &coordsSec)); 42546858538eSMatthew G. Knepley if (coordsSec) PetscCall(DMSetCellCoordinateSection(dm, cDim, coordsSec)); 42556858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(newPlex, &coords)); 42566858538eSMatthew G. Knepley if (coords) PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 42570a96aa3bSJed Brown } 42580a96aa3bSJed Brown } 42590a96aa3bSJed Brown newPlex = pforest->plex; 42600a96aa3bSJed Brown if (plex) { 42619566063dSJacob Faibussowitsch PetscCall(DMClone(newPlex, plex)); 42626858538eSMatthew G. Knepley #if 0 42639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM)); 42649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(*plex,coordDM)); 42656858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex,&coordDM)); 42666858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*plex,coordDM)); 42676858538eSMatthew G. Knepley #endif 42689566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm, *plex)); 42690a96aa3bSJed Brown } 42700a96aa3bSJed Brown PetscFunctionReturn(0); 42710a96aa3bSJed Brown } 42720a96aa3bSJed Brown 42739371c9d4SSatish Balay static PetscErrorCode DMSetFromOptions_pforest(DM dm, PetscOptionItems *PetscOptionsObject) { 42740a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 42750a96aa3bSJed Brown char stringBuffer[256]; 42760a96aa3bSJed Brown PetscBool flg; 42770a96aa3bSJed Brown 42780a96aa3bSJed Brown PetscFunctionBegin; 4279dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Forest(dm, PetscOptionsObject)); 4280d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DM" P4EST_STRING " options"); 42819566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_p4est_partition_for_coarsening", "partition forest to allow for coarsening", "DMP4estSetPartitionForCoarsening", pforest->partition_for_coarsening, &(pforest->partition_for_coarsening), NULL)); 42829566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_p4est_ghost_label_name", "the name of the ghost label when converting from a DMPlex", NULL, NULL, stringBuffer, sizeof(stringBuffer), &flg)); 4283d0609cedSBarry Smith PetscOptionsHeadEnd(); 42840a96aa3bSJed Brown if (flg) { 42859566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName)); 42869566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(stringBuffer, &pforest->ghostName)); 42870a96aa3bSJed Brown } 42880a96aa3bSJed Brown PetscFunctionReturn(0); 42890a96aa3bSJed Brown } 42900a96aa3bSJed Brown 42910a96aa3bSJed Brown #if !defined(P4_TO_P8) 42920a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP4estGetPartitionForCoarsening 42930a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP4estSetPartitionForCoarsening 42940a96aa3bSJed Brown #else 42950a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP8estGetPartitionForCoarsening 42960a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP8estSetPartitionForCoarsening 42970a96aa3bSJed Brown #endif 42980a96aa3bSJed Brown 42999371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMPforestGetPartitionForCoarsening(DM dm, PetscBool *flg) { 43000a96aa3bSJed Brown DM_Forest_pforest *pforest; 43010a96aa3bSJed Brown 43020a96aa3bSJed Brown PetscFunctionBegin; 43030a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43040a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 43050a96aa3bSJed Brown *flg = pforest->partition_for_coarsening; 43060a96aa3bSJed Brown PetscFunctionReturn(0); 43070a96aa3bSJed Brown } 43080a96aa3bSJed Brown 43099371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMPforestSetPartitionForCoarsening(DM dm, PetscBool flg) { 43100a96aa3bSJed Brown DM_Forest_pforest *pforest; 43110a96aa3bSJed Brown 43120a96aa3bSJed Brown PetscFunctionBegin; 43130a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43140a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 43150a96aa3bSJed Brown pforest->partition_for_coarsening = flg; 43160a96aa3bSJed Brown PetscFunctionReturn(0); 43170a96aa3bSJed Brown } 43180a96aa3bSJed Brown 43199371c9d4SSatish Balay static PetscErrorCode DMPforestGetPlex(DM dm, DM *plex) { 43200a96aa3bSJed Brown DM_Forest_pforest *pforest; 43210a96aa3bSJed Brown 43220a96aa3bSJed Brown PetscFunctionBegin; 43230a96aa3bSJed Brown if (plex) *plex = NULL; 43249566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 43250a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 432648a46eb9SPierre Jolivet if (!pforest->plex) PetscCall(DMConvert_pforest_plex(dm, DMPLEX, NULL)); 43279566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm, pforest->plex)); 43280a96aa3bSJed Brown if (plex) *plex = pforest->plex; 43290a96aa3bSJed Brown PetscFunctionReturn(0); 43300a96aa3bSJed Brown } 43310a96aa3bSJed Brown 43320a96aa3bSJed Brown #define DMCreateInterpolation_pforest _append_pforest(DMCreateInterpolation) 43339371c9d4SSatish Balay static PetscErrorCode DMCreateInterpolation_pforest(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) { 43340a96aa3bSJed Brown PetscSection gsc, gsf; 43350a96aa3bSJed Brown PetscInt m, n; 43360a96aa3bSJed Brown DM cdm; 43370a96aa3bSJed Brown 43380a96aa3bSJed Brown PetscFunctionBegin; 43399566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 43409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 43419566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 43429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 43430a96aa3bSJed Brown 43449566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmFine), interpolation)); 43459566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 43469566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, MATAIJ)); 43470a96aa3bSJed Brown 43489566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 434908401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse, PetscObjectComm((PetscObject)dmFine), PETSC_ERR_SUP, "Only interpolation from coarse DM for now"); 43500a96aa3bSJed Brown 43510a96aa3bSJed Brown { 43520a96aa3bSJed Brown DM plexF, plexC; 43530a96aa3bSJed Brown PetscSF sf; 43540a96aa3bSJed Brown PetscInt *cids; 43550a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1}; 43560a96aa3bSJed Brown 43579566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse, &plexC)); 43589566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine, &plexF)); 43599566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 43609566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 43619566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInterpolatorTree(plexC, plexF, sf, cids, *interpolation)); 43629566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 43639566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 43640a96aa3bSJed Brown } 43659566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 43660a96aa3bSJed Brown /* Use naive scaling */ 43679566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 43680a96aa3bSJed Brown PetscFunctionReturn(0); 43690a96aa3bSJed Brown } 43700a96aa3bSJed Brown 43710a96aa3bSJed Brown #define DMCreateInjection_pforest _append_pforest(DMCreateInjection) 43729371c9d4SSatish Balay static PetscErrorCode DMCreateInjection_pforest(DM dmCoarse, DM dmFine, Mat *injection) { 43730a96aa3bSJed Brown PetscSection gsc, gsf; 43740a96aa3bSJed Brown PetscInt m, n; 43750a96aa3bSJed Brown DM cdm; 43760a96aa3bSJed Brown 43770a96aa3bSJed Brown PetscFunctionBegin; 43789566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 43799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &n)); 43809566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 43819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &m)); 43820a96aa3bSJed Brown 43839566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmFine), injection)); 43849566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*injection, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 43859566063dSJacob Faibussowitsch PetscCall(MatSetType(*injection, MATAIJ)); 43860a96aa3bSJed Brown 43879566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 438808401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse, PetscObjectComm((PetscObject)dmFine), PETSC_ERR_SUP, "Only injection to coarse DM for now"); 43890a96aa3bSJed Brown 43900a96aa3bSJed Brown { 43910a96aa3bSJed Brown DM plexF, plexC; 43920a96aa3bSJed Brown PetscSF sf; 43930a96aa3bSJed Brown PetscInt *cids; 43940a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1}; 43950a96aa3bSJed Brown 43969566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse, &plexC)); 43979566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine, &plexF)); 43989566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 43999566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 44009566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorTree(plexC, plexF, sf, cids, *injection)); 44019566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 44029566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 44030a96aa3bSJed Brown } 44049566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*injection, NULL, "-inject_mat_view")); 44050a96aa3bSJed Brown /* Use naive scaling */ 44060a96aa3bSJed Brown PetscFunctionReturn(0); 44070a96aa3bSJed Brown } 44080a96aa3bSJed Brown 44090a96aa3bSJed Brown #define DMForestTransferVecFromBase_pforest _append_pforest(DMForestTransferVecFromBase) 44109371c9d4SSatish Balay static PetscErrorCode DMForestTransferVecFromBase_pforest(DM dm, Vec vecIn, Vec vecOut) { 44110a96aa3bSJed Brown DM dmIn, dmVecIn, base, basec, plex, coarseDM; 44120a96aa3bSJed Brown DM *hierarchy; 44130a96aa3bSJed Brown PetscSF sfRed = NULL; 44140a96aa3bSJed Brown PetscDS ds; 44150a96aa3bSJed Brown Vec vecInLocal, vecOutLocal; 44160a96aa3bSJed Brown DMLabel subpointMap; 44170a96aa3bSJed Brown PetscInt minLevel, mh, n_hi, i; 44180a96aa3bSJed Brown PetscBool hiforest, *hierarchy_forest; 44190a96aa3bSJed Brown 44200a96aa3bSJed Brown PetscFunctionBegin; 44219566063dSJacob Faibussowitsch PetscCall(VecGetDM(vecIn, &dmVecIn)); 44229566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmVecIn, &ds)); 442328b400f6SJacob Faibussowitsch PetscCheck(ds, PetscObjectComm((PetscObject)dmVecIn), PETSC_ERR_SUP, "Cannot transfer without a PetscDS object"); 44240a96aa3bSJed Brown { /* we cannot stick user contexts into function callbacks for DMProjectFieldLocal! */ 44250a96aa3bSJed Brown PetscSection section; 44260a96aa3bSJed Brown PetscInt Nf; 44270a96aa3bSJed Brown 44289566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn, §ion)); 44299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 443063a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 3, PetscObjectComm((PetscObject)dmVecIn), PETSC_ERR_SUP, "Number of fields %" PetscInt_FMT " are currently not supported! Send an email at petsc-dev@mcs.anl.gov", Nf); 44310a96aa3bSJed Brown } 44329566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel)); 443363a3b9bcSJacob Faibussowitsch PetscCheck(!minLevel, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot transfer with minimum refinement set to %" PetscInt_FMT ". Rerun with DMForestSetMinimumRefinement(dm,0)", minLevel); 44349566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 443528b400f6SJacob Faibussowitsch PetscCheck(base, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing base DM"); 44360a96aa3bSJed Brown 44379566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0)); 44380a96aa3bSJed Brown if (dmVecIn == base) { /* sequential runs */ 44399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 44400a96aa3bSJed Brown } else { 44410a96aa3bSJed Brown PetscSection secIn, secInRed; 44420a96aa3bSJed Brown Vec vecInRed, vecInLocal; 44430a96aa3bSJed Brown 44449566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)base, "_base_migration_sf", (PetscObject *)&sfRed)); 444528b400f6SJacob Faibussowitsch PetscCheck(sfRed, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not the DM set with DMForestSetBaseDM()"); 44469566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmVecIn), &secInRed)); 44479566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &vecInRed)); 44489566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn, &secIn)); 44499566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmVecIn, &vecInLocal)); 44509566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmVecIn, vecIn, INSERT_VALUES, vecInLocal)); 44519566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmVecIn, vecIn, INSERT_VALUES, vecInLocal)); 44529566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dmVecIn, sfRed, secIn, vecInLocal, secInRed, vecInRed)); 44539566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmVecIn, &vecInLocal)); 44549566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secInRed)); 44550a96aa3bSJed Brown vecIn = vecInRed; 44560a96aa3bSJed Brown } 44570a96aa3bSJed Brown 44580a96aa3bSJed Brown /* we first search through the AdaptivityForest hierarchy 44590a96aa3bSJed Brown once we found the first disconnected forest, we upsweep the DM hierarchy */ 44600a96aa3bSJed Brown hiforest = PETSC_TRUE; 44610a96aa3bSJed Brown 44620a96aa3bSJed Brown /* upsweep to the coarsest DM */ 44630a96aa3bSJed Brown n_hi = 0; 44640a96aa3bSJed Brown coarseDM = dm; 44650a96aa3bSJed Brown do { 44660a96aa3bSJed Brown PetscBool isforest; 44670a96aa3bSJed Brown 44680a96aa3bSJed Brown dmIn = coarseDM; 44690a96aa3bSJed Brown /* need to call DMSetUp to have the hierarchy recursively setup */ 44709566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmIn)); 44719566063dSJacob Faibussowitsch PetscCall(DMIsForest(dmIn, &isforest)); 447228b400f6SJacob Faibussowitsch PetscCheck(isforest, PetscObjectComm((PetscObject)dmIn), PETSC_ERR_SUP, "Cannot currently transfer through a mixed hierarchy! Found DM type %s", ((PetscObject)dmIn)->type_name); 44730a96aa3bSJed Brown coarseDM = NULL; 447448a46eb9SPierre Jolivet if (hiforest) PetscCall(DMForestGetAdaptivityForest(dmIn, &coarseDM)); 44750a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 44760a96aa3bSJed Brown hiforest = PETSC_FALSE; 44779566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn, &coarseDM)); 44780a96aa3bSJed Brown } 44790a96aa3bSJed Brown n_hi++; 44800a96aa3bSJed Brown } while (coarseDM); 44810a96aa3bSJed Brown 44829566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n_hi, &hierarchy, n_hi, &hierarchy_forest)); 44830a96aa3bSJed Brown 44840a96aa3bSJed Brown i = 0; 44850a96aa3bSJed Brown hiforest = PETSC_TRUE; 44860a96aa3bSJed Brown coarseDM = dm; 44870a96aa3bSJed Brown do { 44880a96aa3bSJed Brown dmIn = coarseDM; 44890a96aa3bSJed Brown coarseDM = NULL; 449048a46eb9SPierre Jolivet if (hiforest) PetscCall(DMForestGetAdaptivityForest(dmIn, &coarseDM)); 44910a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 44920a96aa3bSJed Brown hiforest = PETSC_FALSE; 44939566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn, &coarseDM)); 44940a96aa3bSJed Brown } 44950a96aa3bSJed Brown i++; 44960a96aa3bSJed Brown hierarchy[n_hi - i] = dmIn; 44970a96aa3bSJed Brown } while (coarseDM); 44980a96aa3bSJed Brown 44990a96aa3bSJed Brown /* project base vector on the coarsest forest (minimum refinement = 0) */ 45009566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn, &plex)); 45010a96aa3bSJed Brown 45020a96aa3bSJed Brown /* Check this plex is compatible with the base */ 45030a96aa3bSJed Brown { 45040a96aa3bSJed Brown IS gnum[2]; 45050a96aa3bSJed Brown PetscInt ncells[2], gncells[2]; 45060a96aa3bSJed Brown 45079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(base, &gnum[0])); 45089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(plex, &gnum[1])); 45099566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[0], NULL, &ncells[0])); 45109566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[1], NULL, &ncells[1])); 45111c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(ncells, gncells, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 451263a3b9bcSJacob Faibussowitsch PetscCheck(gncells[0] == gncells[1], PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Invalid number of base cells! Expected %" PetscInt_FMT ", found %" PetscInt_FMT, gncells[0] + 1, gncells[1] + 1); 45130a96aa3bSJed Brown } 45140a96aa3bSJed Brown 45159566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmIn, "_forest_base_subpoint_map", &subpointMap)); 451628b400f6SJacob Faibussowitsch PetscCheck(subpointMap, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing _forest_base_subpoint_map label"); 45170a96aa3bSJed Brown 45189566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(base, &mh)); 45199566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(plex, mh)); 45200a96aa3bSJed Brown 45219566063dSJacob Faibussowitsch PetscCall(DMClone(base, &basec)); 45229566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmVecIn, basec)); 45230a96aa3bSJed Brown if (sfRed) { 45249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 45250a96aa3bSJed Brown vecInLocal = vecIn; 45260a96aa3bSJed Brown } else { 45279566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(basec, &vecInLocal)); 45289566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(basec, vecIn, INSERT_VALUES, vecInLocal)); 45299566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(basec, vecIn, INSERT_VALUES, vecInLocal)); 45300a96aa3bSJed Brown } 45310a96aa3bSJed Brown 45329566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecOutLocal)); 45330a96aa3bSJed Brown { /* get degrees of freedom ordered onto dmIn */ 45340a96aa3bSJed Brown PetscSF basetocoarse; 45350a96aa3bSJed Brown PetscInt bStart, bEnd, nroots; 45360a96aa3bSJed Brown PetscInt iStart, iEnd, nleaves, leaf; 45370a96aa3bSJed Brown PetscMPIInt rank; 45380a96aa3bSJed Brown PetscSFNode *remotes; 45390a96aa3bSJed Brown PetscSection secIn, secOut; 45400a96aa3bSJed Brown PetscInt *remoteOffsets; 45410a96aa3bSJed Brown PetscSF transferSF; 45420a96aa3bSJed Brown const PetscScalar *inArray; 45430a96aa3bSJed Brown PetscScalar *outArray; 45440a96aa3bSJed Brown 45459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)basec), &rank)); 45469566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(basec, &bStart, &bEnd)); 45470a96aa3bSJed Brown nroots = PetscMax(bEnd - bStart, 0); 45489566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &iStart, &iEnd)); 45490a96aa3bSJed Brown nleaves = PetscMax(iEnd - iStart, 0); 45500a96aa3bSJed Brown 45519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotes)); 45520a96aa3bSJed Brown for (leaf = iStart; leaf < iEnd; leaf++) { 45530a96aa3bSJed Brown PetscInt index; 45540a96aa3bSJed Brown 45550a96aa3bSJed Brown remotes[leaf - iStart].rank = rank; 45569566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, leaf, &index)); 45570a96aa3bSJed Brown remotes[leaf - iStart].index = index; 45580a96aa3bSJed Brown } 45590a96aa3bSJed Brown 45609566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)basec), &basetocoarse)); 45619566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(basetocoarse, nroots, nleaves, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 45629566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(basetocoarse)); 45639566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(basec, &secIn)); 45649566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmIn), &secOut)); 45659566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(basetocoarse, secIn, &remoteOffsets, secOut)); 45669566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(basetocoarse, secIn, remoteOffsets, secOut, &transferSF)); 45679566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 45689566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(vecOutLocal, &outArray)); 45699566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecInLocal, &inArray)); 45709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferSF, MPIU_SCALAR, inArray, outArray, MPI_REPLACE)); 45719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferSF, MPIU_SCALAR, inArray, outArray, MPI_REPLACE)); 45729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecInLocal, &inArray)); 45739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(vecOutLocal, &outArray)); 45749566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferSF)); 45759566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secOut)); 45769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&basetocoarse)); 45770a96aa3bSJed Brown } 45789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecInLocal)); 45799566063dSJacob Faibussowitsch PetscCall(DMDestroy(&basec)); 45809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecIn)); 45810a96aa3bSJed Brown 45820a96aa3bSJed Brown /* output */ 45830a96aa3bSJed Brown if (n_hi > 1) { /* downsweep the stored hierarchy */ 45840a96aa3bSJed Brown Vec vecOut1, vecOut2; 45850a96aa3bSJed Brown DM fineDM; 45860a96aa3bSJed Brown 45879566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmIn, &vecOut1)); 45889566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn, vecOutLocal, INSERT_VALUES, vecOut1)); 45899566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecOutLocal)); 45900a96aa3bSJed Brown for (i = 1; i < n_hi - 1; i++) { 45910a96aa3bSJed Brown fineDM = hierarchy[i]; 45929566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(fineDM, &vecOut2)); 45939566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn, vecOut1, fineDM, vecOut2, PETSC_TRUE, 0.0)); 45949566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn, &vecOut1)); 45950a96aa3bSJed Brown vecOut1 = vecOut2; 45960a96aa3bSJed Brown dmIn = fineDM; 45970a96aa3bSJed Brown } 45989566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn, vecOut1, dm, vecOut, PETSC_TRUE, 0.0)); 45999566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn, &vecOut1)); 46000a96aa3bSJed Brown } else { 46019566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn, vecOutLocal, INSERT_VALUES, vecOut)); 46029566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecOutLocal)); 46030a96aa3bSJed Brown } 46049566063dSJacob Faibussowitsch PetscCall(PetscFree2(hierarchy, hierarchy_forest)); 46050a96aa3bSJed Brown PetscFunctionReturn(0); 46060a96aa3bSJed Brown } 46070a96aa3bSJed Brown 46080a96aa3bSJed Brown #define DMForestTransferVec_pforest _append_pforest(DMForestTransferVec) 46099371c9d4SSatish Balay static PetscErrorCode DMForestTransferVec_pforest(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time) { 46100a96aa3bSJed Brown DM adaptIn, adaptOut, plexIn, plexOut; 46110a96aa3bSJed Brown DM_Forest *forestIn, *forestOut, *forestAdaptIn, *forestAdaptOut; 46120a96aa3bSJed Brown PetscInt dofPerDim[] = {1, 1, 1, 1}; 46130a96aa3bSJed Brown PetscSF inSF = NULL, outSF = NULL; 46140a96aa3bSJed Brown PetscInt *inCids = NULL, *outCids = NULL; 46150a96aa3bSJed Brown DMAdaptFlag purposeIn, purposeOut; 46160a96aa3bSJed Brown 46170a96aa3bSJed Brown PetscFunctionBegin; 46180a96aa3bSJed Brown forestOut = (DM_Forest *)dmOut->data; 46190a96aa3bSJed Brown forestIn = (DM_Forest *)dmIn->data; 46200a96aa3bSJed Brown 46219566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmOut, &adaptOut)); 46229566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmOut, &purposeOut)); 46230a96aa3bSJed Brown forestAdaptOut = adaptOut ? (DM_Forest *)adaptOut->data : NULL; 46240a96aa3bSJed Brown 46259566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn, &adaptIn)); 46269566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmIn, &purposeIn)); 46270a96aa3bSJed Brown forestAdaptIn = adaptIn ? (DM_Forest *)adaptIn->data : NULL; 46280a96aa3bSJed Brown 46290a96aa3bSJed Brown if (forestAdaptOut == forestIn) { 46300a96aa3bSJed Brown switch (purposeOut) { 46310a96aa3bSJed Brown case DM_ADAPT_REFINE: 46329566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 46339566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 46340a96aa3bSJed Brown break; 46350a96aa3bSJed Brown case DM_ADAPT_COARSEN: 46360a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 46379566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_TRUE, &outCids)); 46389566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 46390a96aa3bSJed Brown break; 46400a96aa3bSJed Brown default: 46419566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 46429566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_FALSE, &outCids)); 46439566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 46449566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 46450a96aa3bSJed Brown } 46460a96aa3bSJed Brown } else if (forestAdaptIn == forestOut) { 46470a96aa3bSJed Brown switch (purposeIn) { 46480a96aa3bSJed Brown case DM_ADAPT_REFINE: 46499566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_TRUE, &inCids)); 46509566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 46510a96aa3bSJed Brown break; 46520a96aa3bSJed Brown case DM_ADAPT_COARSEN: 46530a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 46549566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 46559566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 46560a96aa3bSJed Brown break; 46570a96aa3bSJed Brown default: 46589566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 46599566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_FALSE, &outCids)); 46609566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 46619566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 46620a96aa3bSJed Brown } 46630a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dmIn), PETSC_ERR_SUP, "Only support transfer from pre-adaptivity to post-adaptivity right now"); 46649566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn, &plexIn)); 46659566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmOut, &plexOut)); 46660a96aa3bSJed Brown 46679566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree(plexIn, vecIn, plexOut, vecOut, inSF, outSF, inCids, outCids, useBCs, time)); 46689566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 46699566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 46709566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&inSF)); 46719566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&outSF)); 46729566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 46739566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 46740a96aa3bSJed Brown PetscFunctionReturn(0); 46750a96aa3bSJed Brown } 46760a96aa3bSJed Brown 46770a96aa3bSJed Brown #define DMCreateCoordinateDM_pforest _append_pforest(DMCreateCoordinateDM) 46789371c9d4SSatish Balay static PetscErrorCode DMCreateCoordinateDM_pforest(DM dm, DM *cdm) { 46790a96aa3bSJed Brown DM plex; 46800a96aa3bSJed Brown 46810a96aa3bSJed Brown PetscFunctionBegin; 46820a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46839566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 46849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(plex, cdm)); 46859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*cdm)); 46860a96aa3bSJed Brown PetscFunctionReturn(0); 46870a96aa3bSJed Brown } 46880a96aa3bSJed Brown 46890a96aa3bSJed Brown #define VecViewLocal_pforest _append_pforest(VecViewLocal) 46909371c9d4SSatish Balay static PetscErrorCode VecViewLocal_pforest(Vec vec, PetscViewer viewer) { 46910a96aa3bSJed Brown DM dm, plex; 46920a96aa3bSJed Brown 46930a96aa3bSJed Brown PetscFunctionBegin; 46949566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 46959566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 46969566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 46979566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(vec, viewer)); 46989566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 46990a96aa3bSJed Brown PetscFunctionReturn(0); 47000a96aa3bSJed Brown } 47010a96aa3bSJed Brown 47020a96aa3bSJed Brown #define VecView_pforest _append_pforest(VecView) 47039371c9d4SSatish Balay static PetscErrorCode VecView_pforest(Vec vec, PetscViewer viewer) { 47040a96aa3bSJed Brown DM dm, plex; 47050a96aa3bSJed Brown 47060a96aa3bSJed Brown PetscFunctionBegin; 47079566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 47089566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47099566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 47109566063dSJacob Faibussowitsch PetscCall(VecView_Plex(vec, viewer)); 47119566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 47120a96aa3bSJed Brown PetscFunctionReturn(0); 47130a96aa3bSJed Brown } 47140a96aa3bSJed Brown 47150a96aa3bSJed Brown #define VecView_pforest_Native _infix_pforest(VecView, _Native) 47169371c9d4SSatish Balay static PetscErrorCode VecView_pforest_Native(Vec vec, PetscViewer viewer) { 47170a96aa3bSJed Brown DM dm, plex; 47180a96aa3bSJed Brown 47190a96aa3bSJed Brown PetscFunctionBegin; 47209566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 47219566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47229566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 47239566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Native(vec, viewer)); 47249566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 47250a96aa3bSJed Brown PetscFunctionReturn(0); 47260a96aa3bSJed Brown } 47270a96aa3bSJed Brown 47280a96aa3bSJed Brown #define VecLoad_pforest _append_pforest(VecLoad) 47299371c9d4SSatish Balay static PetscErrorCode VecLoad_pforest(Vec vec, PetscViewer viewer) { 47300a96aa3bSJed Brown DM dm, plex; 47310a96aa3bSJed Brown 47320a96aa3bSJed Brown PetscFunctionBegin; 47339566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 47349566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47359566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 47369566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex(vec, viewer)); 47379566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 47380a96aa3bSJed Brown PetscFunctionReturn(0); 47390a96aa3bSJed Brown } 47400a96aa3bSJed Brown 47410a96aa3bSJed Brown #define VecLoad_pforest_Native _infix_pforest(VecLoad, _Native) 47429371c9d4SSatish Balay static PetscErrorCode VecLoad_pforest_Native(Vec vec, PetscViewer viewer) { 47430a96aa3bSJed Brown DM dm, plex; 47440a96aa3bSJed Brown 47450a96aa3bSJed Brown PetscFunctionBegin; 47469566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 47479566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47489566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 47499566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_Native(vec, viewer)); 47509566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 47510a96aa3bSJed Brown PetscFunctionReturn(0); 47520a96aa3bSJed Brown } 47530a96aa3bSJed Brown 47540a96aa3bSJed Brown #define DMCreateGlobalVector_pforest _append_pforest(DMCreateGlobalVector) 47559371c9d4SSatish Balay static PetscErrorCode DMCreateGlobalVector_pforest(DM dm, Vec *vec) { 47560a96aa3bSJed Brown PetscFunctionBegin; 47579566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 47589566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 47599566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_pforest)); 47609566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_pforest_Native)); 47619566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_pforest)); 47629566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_pforest_Native)); 47630a96aa3bSJed Brown PetscFunctionReturn(0); 47640a96aa3bSJed Brown } 47650a96aa3bSJed Brown 47660a96aa3bSJed Brown #define DMCreateLocalVector_pforest _append_pforest(DMCreateLocalVector) 47679371c9d4SSatish Balay static PetscErrorCode DMCreateLocalVector_pforest(DM dm, Vec *vec) { 47680a96aa3bSJed Brown PetscFunctionBegin; 47699566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 47709566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecViewLocal_pforest)); 47710a96aa3bSJed Brown PetscFunctionReturn(0); 47720a96aa3bSJed Brown } 47730a96aa3bSJed Brown 47740a96aa3bSJed Brown #define DMCreateMatrix_pforest _append_pforest(DMCreateMatrix) 47759371c9d4SSatish Balay static PetscErrorCode DMCreateMatrix_pforest(DM dm, Mat *mat) { 47760a96aa3bSJed Brown DM plex; 47770a96aa3bSJed Brown 47780a96aa3bSJed Brown PetscFunctionBegin; 47790a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47809566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47810a96aa3bSJed Brown if (plex->prealloc_only != dm->prealloc_only) plex->prealloc_only = dm->prealloc_only; /* maybe this should go into forest->plex */ 47829566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(plex, mat)); 47839566063dSJacob Faibussowitsch PetscCall(MatSetDM(*mat, dm)); 47840a96aa3bSJed Brown PetscFunctionReturn(0); 47850a96aa3bSJed Brown } 47860a96aa3bSJed Brown 47870a96aa3bSJed Brown #define DMProjectFunctionLocal_pforest _append_pforest(DMProjectFunctionLocal) 47889371c9d4SSatish Balay static PetscErrorCode DMProjectFunctionLocal_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) { 47890a96aa3bSJed Brown DM plex; 47900a96aa3bSJed Brown 47910a96aa3bSJed Brown PetscFunctionBegin; 47920a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47939566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47949566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLocal(plex, time, funcs, ctxs, mode, localX)); 47950a96aa3bSJed Brown PetscFunctionReturn(0); 47960a96aa3bSJed Brown } 47970a96aa3bSJed Brown 47980a96aa3bSJed Brown #define DMProjectFunctionLabelLocal_pforest _append_pforest(DMProjectFunctionLabelLocal) 47999371c9d4SSatish Balay static PetscErrorCode DMProjectFunctionLabelLocal_pforest(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) { 48000a96aa3bSJed Brown DM plex; 48010a96aa3bSJed Brown 48020a96aa3bSJed Brown PetscFunctionBegin; 48030a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48049566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48059566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLabelLocal(plex, time, label, numIds, ids, Ncc, comps, funcs, ctxs, mode, localX)); 48060a96aa3bSJed Brown PetscFunctionReturn(0); 48070a96aa3bSJed Brown } 48080a96aa3bSJed Brown 48090a96aa3bSJed Brown #define DMProjectFieldLocal_pforest _append_pforest(DMProjectFieldLocal) 48109371c9d4SSatish Balay PetscErrorCode DMProjectFieldLocal_pforest(DM dm, PetscReal time, Vec localU, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), InsertMode mode, Vec localX) { 48110a96aa3bSJed Brown DM plex; 48120a96aa3bSJed Brown 48130a96aa3bSJed Brown PetscFunctionBegin; 48140a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48159566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48169566063dSJacob Faibussowitsch PetscCall(DMProjectFieldLocal(plex, time, localU, funcs, mode, localX)); 48170a96aa3bSJed Brown PetscFunctionReturn(0); 48180a96aa3bSJed Brown } 48190a96aa3bSJed Brown 48200a96aa3bSJed Brown #define DMComputeL2Diff_pforest _append_pforest(DMComputeL2Diff) 48219371c9d4SSatish Balay PetscErrorCode DMComputeL2Diff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) { 48220a96aa3bSJed Brown DM plex; 48230a96aa3bSJed Brown 48240a96aa3bSJed Brown PetscFunctionBegin; 48250a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48269566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48279566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(plex, time, funcs, ctxs, X, diff)); 48280a96aa3bSJed Brown PetscFunctionReturn(0); 48290a96aa3bSJed Brown } 48300a96aa3bSJed Brown 48310a96aa3bSJed Brown #define DMComputeL2FieldDiff_pforest _append_pforest(DMComputeL2FieldDiff) 48329371c9d4SSatish Balay PetscErrorCode DMComputeL2FieldDiff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) { 48330a96aa3bSJed Brown DM plex; 48340a96aa3bSJed Brown 48350a96aa3bSJed Brown PetscFunctionBegin; 48360a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48379566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48389566063dSJacob Faibussowitsch PetscCall(DMComputeL2FieldDiff(plex, time, funcs, ctxs, X, diff)); 48390a96aa3bSJed Brown PetscFunctionReturn(0); 48400a96aa3bSJed Brown } 48410a96aa3bSJed Brown 48420a96aa3bSJed Brown #define DMCreatelocalsection_pforest _append_pforest(DMCreatelocalsection) 48439371c9d4SSatish Balay static PetscErrorCode DMCreatelocalsection_pforest(DM dm) { 48440a96aa3bSJed Brown DM plex; 48450a96aa3bSJed Brown PetscSection section; 48460a96aa3bSJed Brown 48470a96aa3bSJed Brown PetscFunctionBegin; 48480a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48499566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48509566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(plex, §ion)); 48519566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(dm, section)); 48520a96aa3bSJed Brown PetscFunctionReturn(0); 48530a96aa3bSJed Brown } 48540a96aa3bSJed Brown 48550a96aa3bSJed Brown #define DMCreateDefaultConstraints_pforest _append_pforest(DMCreateDefaultConstraints) 48569371c9d4SSatish Balay static PetscErrorCode DMCreateDefaultConstraints_pforest(DM dm) { 48570a96aa3bSJed Brown DM plex; 48580a96aa3bSJed Brown Mat mat; 485979769bd5SJed Brown Vec bias; 48600a96aa3bSJed Brown PetscSection section; 48610a96aa3bSJed Brown 48620a96aa3bSJed Brown PetscFunctionBegin; 48630a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48649566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48659566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(plex, §ion, &mat, &bias)); 48669566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, section, mat, bias)); 48670a96aa3bSJed Brown PetscFunctionReturn(0); 48680a96aa3bSJed Brown } 48690a96aa3bSJed Brown 48700a96aa3bSJed Brown #define DMGetDimPoints_pforest _append_pforest(DMGetDimPoints) 48719371c9d4SSatish Balay static PetscErrorCode DMGetDimPoints_pforest(DM dm, PetscInt dim, PetscInt *cStart, PetscInt *cEnd) { 48720a96aa3bSJed Brown DM plex; 48730a96aa3bSJed Brown 48740a96aa3bSJed Brown PetscFunctionBegin; 48750a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48769566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48779566063dSJacob Faibussowitsch PetscCall(DMGetDimPoints(plex, dim, cStart, cEnd)); 48780a96aa3bSJed Brown PetscFunctionReturn(0); 48790a96aa3bSJed Brown } 48800a96aa3bSJed Brown 48810a96aa3bSJed Brown /* Need to forward declare */ 48820a96aa3bSJed Brown #define DMInitialize_pforest _append_pforest(DMInitialize) 48830a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm); 48840a96aa3bSJed Brown 48850a96aa3bSJed Brown #define DMClone_pforest _append_pforest(DMClone) 48869371c9d4SSatish Balay static PetscErrorCode DMClone_pforest(DM dm, DM *newdm) { 48870a96aa3bSJed Brown PetscFunctionBegin; 48889566063dSJacob Faibussowitsch PetscCall(DMClone_Forest(dm, newdm)); 48899566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(*newdm)); 48900a96aa3bSJed Brown PetscFunctionReturn(0); 48910a96aa3bSJed Brown } 48920a96aa3bSJed Brown 48930a96aa3bSJed Brown #define DMForestCreateCellChart_pforest _append_pforest(DMForestCreateCellChart) 48949371c9d4SSatish Balay static PetscErrorCode DMForestCreateCellChart_pforest(DM dm, PetscInt *cStart, PetscInt *cEnd) { 48950a96aa3bSJed Brown DM_Forest *forest; 48960a96aa3bSJed Brown DM_Forest_pforest *pforest; 48970a96aa3bSJed Brown PetscInt overlap; 48980a96aa3bSJed Brown 48990a96aa3bSJed Brown PetscFunctionBegin; 49009566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 49010a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 49020a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 49030a96aa3bSJed Brown *cStart = 0; 49049566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 49050a96aa3bSJed Brown if (overlap && pforest->ghost) { 49060a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[pforest->forest->mpisize]; 49070a96aa3bSJed Brown } else { 49080a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants; 49090a96aa3bSJed Brown } 49100a96aa3bSJed Brown PetscFunctionReturn(0); 49110a96aa3bSJed Brown } 49120a96aa3bSJed Brown 49130a96aa3bSJed Brown #define DMForestCreateCellSF_pforest _append_pforest(DMForestCreateCellSF) 49149371c9d4SSatish Balay static PetscErrorCode DMForestCreateCellSF_pforest(DM dm, PetscSF *cellSF) { 49150a96aa3bSJed Brown DM_Forest *forest; 49160a96aa3bSJed Brown DM_Forest_pforest *pforest; 49170a96aa3bSJed Brown PetscMPIInt rank; 49180a96aa3bSJed Brown PetscInt overlap; 49190a96aa3bSJed Brown PetscInt cStart, cEnd, cLocalStart, cLocalEnd; 49200a96aa3bSJed Brown PetscInt nRoots, nLeaves, *mine = NULL; 49210a96aa3bSJed Brown PetscSFNode *remote = NULL; 49220a96aa3bSJed Brown PetscSF sf; 49230a96aa3bSJed Brown 49240a96aa3bSJed Brown PetscFunctionBegin; 49259566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(dm, &cStart, &cEnd)); 49260a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 49270a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 49280a96aa3bSJed Brown nRoots = cEnd - cStart; 49290a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 49300a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 49310a96aa3bSJed Brown nLeaves = 0; 49329566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 49339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 49340a96aa3bSJed Brown if (overlap && pforest->ghost) { 49350a96aa3bSJed Brown PetscSFNode *mirror; 49360a96aa3bSJed Brown p4est_quadrant_t *mirror_array; 49370a96aa3bSJed Brown PetscInt nMirror, nGhostPre, nSelf, q; 49380a96aa3bSJed Brown void **mirrorPtrs; 49390a96aa3bSJed Brown 49400a96aa3bSJed Brown nMirror = (PetscInt)pforest->ghost->mirrors.elem_count; 49410a96aa3bSJed Brown nSelf = cLocalEnd - cLocalStart; 49420a96aa3bSJed Brown nLeaves = nRoots - nSelf; 49430a96aa3bSJed Brown nGhostPre = (PetscInt)pforest->ghost->proc_offsets[rank]; 49449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &mine)); 49459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &remote)); 49469566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nMirror, &mirror, nMirror, &mirrorPtrs)); 49470a96aa3bSJed Brown mirror_array = (p4est_quadrant_t *)pforest->ghost->mirrors.array; 49480a96aa3bSJed Brown for (q = 0; q < nMirror; q++) { 49490a96aa3bSJed Brown p4est_quadrant_t *mir = &(mirror_array[q]); 49500a96aa3bSJed Brown 49510a96aa3bSJed Brown mirror[q].rank = rank; 49520a96aa3bSJed Brown mirror[q].index = (PetscInt)mir->p.piggy3.local_num + cLocalStart; 49530a96aa3bSJed Brown mirrorPtrs[q] = (void *)&(mirror[q]); 49540a96aa3bSJed Brown } 4955792fecdfSBarry Smith PetscCallP4est(p4est_ghost_exchange_custom, (pforest->forest, pforest->ghost, sizeof(PetscSFNode), mirrorPtrs, remote)); 49569566063dSJacob Faibussowitsch PetscCall(PetscFree2(mirror, mirrorPtrs)); 49570a96aa3bSJed Brown for (q = 0; q < nGhostPre; q++) mine[q] = q; 49580a96aa3bSJed Brown for (; q < nLeaves; q++) mine[q] = (q - nGhostPre) + cLocalEnd; 49590a96aa3bSJed Brown } 49609566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &sf)); 49619566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nRoots, nLeaves, mine, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER)); 49620a96aa3bSJed Brown *cellSF = sf; 49630a96aa3bSJed Brown PetscFunctionReturn(0); 49640a96aa3bSJed Brown } 49650a96aa3bSJed Brown 49669371c9d4SSatish Balay static PetscErrorCode DMCreateNeumannOverlap_pforest(DM dm, IS *ovl, Mat *J, PetscErrorCode (**setup)(Mat, PetscReal, Vec, Vec, PetscReal, IS, void *), void **setup_ctx) { 49670a96aa3bSJed Brown DM plex; 49680a96aa3bSJed Brown 49690a96aa3bSJed Brown PetscFunctionBegin; 49709566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49719566063dSJacob Faibussowitsch PetscCall(DMCreateNeumannOverlap_Plex(plex, ovl, J, setup, setup_ctx)); 49720a96aa3bSJed Brown if (!*setup) { 49739566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", setup)); 497448a46eb9SPierre Jolivet if (*setup) PetscCall(PetscObjectCompose((PetscObject)*ovl, "_DM_Original_HPDDM", (PetscObject)dm)); 49750a96aa3bSJed Brown } 49760a96aa3bSJed Brown PetscFunctionReturn(0); 49770a96aa3bSJed Brown } 49780a96aa3bSJed Brown 49799371c9d4SSatish Balay static PetscErrorCode DMInitialize_pforest(DM dm) { 49800a96aa3bSJed Brown PetscFunctionBegin; 49810a96aa3bSJed Brown dm->ops->setup = DMSetUp_pforest; 49820a96aa3bSJed Brown dm->ops->view = DMView_pforest; 49830a96aa3bSJed Brown dm->ops->clone = DMClone_pforest; 49840a96aa3bSJed Brown dm->ops->createinterpolation = DMCreateInterpolation_pforest; 49850a96aa3bSJed Brown dm->ops->createinjection = DMCreateInjection_pforest; 49860a96aa3bSJed Brown dm->ops->setfromoptions = DMSetFromOptions_pforest; 49870a96aa3bSJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_pforest; 49880a96aa3bSJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_pforest; 49890a96aa3bSJed Brown dm->ops->createlocalvector = DMCreateLocalVector_pforest; 49900a96aa3bSJed Brown dm->ops->creatematrix = DMCreateMatrix_pforest; 49910a96aa3bSJed Brown dm->ops->projectfunctionlocal = DMProjectFunctionLocal_pforest; 49920a96aa3bSJed Brown dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_pforest; 49930a96aa3bSJed Brown dm->ops->projectfieldlocal = DMProjectFieldLocal_pforest; 49940a96aa3bSJed Brown dm->ops->createlocalsection = DMCreatelocalsection_pforest; 49950a96aa3bSJed Brown dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_pforest; 49960a96aa3bSJed Brown dm->ops->computel2diff = DMComputeL2Diff_pforest; 49970a96aa3bSJed Brown dm->ops->computel2fielddiff = DMComputeL2FieldDiff_pforest; 49980a96aa3bSJed Brown dm->ops->getdimpoints = DMGetDimPoints_pforest; 49990a96aa3bSJed Brown 50009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_plex_pforest) "_C", DMConvert_plex_pforest)); 50019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_pforest_plex) "_C", DMConvert_pforest_plex)); 50029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_pforest)); 50039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMForestGetPartitionOverlap)); 50040a96aa3bSJed Brown PetscFunctionReturn(0); 50050a96aa3bSJed Brown } 50060a96aa3bSJed Brown 50070a96aa3bSJed Brown #define DMCreate_pforest _append_pforest(DMCreate) 50089371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMCreate_pforest(DM dm) { 50090a96aa3bSJed Brown DM_Forest *forest; 50100a96aa3bSJed Brown DM_Forest_pforest *pforest; 50110a96aa3bSJed Brown 50120a96aa3bSJed Brown PetscFunctionBegin; 50139566063dSJacob Faibussowitsch PetscCall(PetscP4estInitialize()); 50149566063dSJacob Faibussowitsch PetscCall(DMCreate_Forest(dm)); 50159566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(dm)); 50169566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, P4EST_DIM)); 50170a96aa3bSJed Brown 50180a96aa3bSJed Brown /* set forest defaults */ 50199566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm, "unit")); 50209566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(dm, 0)); 50219566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(dm, 0)); 50229566063dSJacob Faibussowitsch PetscCall(DMForestSetMaximumRefinement(dm, P4EST_QMAXLEVEL)); 50239566063dSJacob Faibussowitsch PetscCall(DMForestSetGradeFactor(dm, 2)); 50249566063dSJacob Faibussowitsch PetscCall(DMForestSetAdjacencyDimension(dm, 0)); 50259566063dSJacob Faibussowitsch PetscCall(DMForestSetPartitionOverlap(dm, 0)); 50260a96aa3bSJed Brown 50270a96aa3bSJed Brown /* create p4est data */ 5028*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&pforest)); 50290a96aa3bSJed Brown 50300a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 50310a96aa3bSJed Brown forest->data = pforest; 50320a96aa3bSJed Brown forest->destroy = DMForestDestroy_pforest; 50330a96aa3bSJed Brown forest->ftemplate = DMForestTemplate_pforest; 50340a96aa3bSJed Brown forest->transfervec = DMForestTransferVec_pforest; 50350a96aa3bSJed Brown forest->transfervecfrombase = DMForestTransferVecFromBase_pforest; 50360a96aa3bSJed Brown forest->createcellchart = DMForestCreateCellChart_pforest; 50370a96aa3bSJed Brown forest->createcellsf = DMForestCreateCellSF_pforest; 50380a96aa3bSJed Brown forest->clearadaptivityforest = DMForestClearAdaptivityForest_pforest; 50390a96aa3bSJed Brown forest->getadaptivitysuccess = DMForestGetAdaptivitySuccess_pforest; 50400a96aa3bSJed Brown pforest->topo = NULL; 50410a96aa3bSJed Brown pforest->forest = NULL; 50420a96aa3bSJed Brown pforest->ghost = NULL; 50430a96aa3bSJed Brown pforest->lnodes = NULL; 50440a96aa3bSJed Brown pforest->partition_for_coarsening = PETSC_TRUE; 50450a96aa3bSJed Brown pforest->coarsen_hierarchy = PETSC_FALSE; 50460a96aa3bSJed Brown pforest->cLocalStart = -1; 50470a96aa3bSJed Brown pforest->cLocalEnd = -1; 50480a96aa3bSJed Brown pforest->labelsFinalized = PETSC_FALSE; 50490a96aa3bSJed Brown pforest->ghostName = NULL; 50500a96aa3bSJed Brown PetscFunctionReturn(0); 50510a96aa3bSJed Brown } 50520a96aa3bSJed Brown 50530a96aa3bSJed Brown #endif /* defined(PETSC_HAVE_P4EST) */ 5054