1a4963045SJacob Faibussowitsch #pragma once 23ea99036SJacob Faibussowitsch 30a96aa3bSJed Brown #include <petscds.h> 40a96aa3bSJed Brown #include <petsc/private/dmimpl.h> 50a96aa3bSJed Brown #include <petsc/private/dmforestimpl.h> 60a96aa3bSJed Brown #include <petsc/private/dmpleximpl.h> 70a96aa3bSJed Brown #include <petsc/private/dmlabelimpl.h> 80a96aa3bSJed Brown #include <petsc/private/viewerimpl.h> 90a96aa3bSJed Brown #include <../src/sys/classes/viewer/impls/vtk/vtkvimpl.h> 100a96aa3bSJed Brown #include "petsc_p4est_package.h" 110a96aa3bSJed Brown 120a96aa3bSJed Brown #if defined(PETSC_HAVE_P4EST) 130a96aa3bSJed Brown 140a96aa3bSJed Brown #if !defined(P4_TO_P8) 150a96aa3bSJed Brown #include <p4est.h> 160a96aa3bSJed Brown #include <p4est_extended.h> 170a96aa3bSJed Brown #include <p4est_geometry.h> 180a96aa3bSJed Brown #include <p4est_ghost.h> 190a96aa3bSJed Brown #include <p4est_lnodes.h> 200a96aa3bSJed Brown #include <p4est_vtk.h> 210a96aa3bSJed Brown #include <p4est_plex.h> 220a96aa3bSJed Brown #include <p4est_bits.h> 230a96aa3bSJed Brown #include <p4est_algorithms.h> 240a96aa3bSJed Brown #else 250a96aa3bSJed Brown #include <p8est.h> 260a96aa3bSJed Brown #include <p8est_extended.h> 270a96aa3bSJed Brown #include <p8est_geometry.h> 280a96aa3bSJed Brown #include <p8est_ghost.h> 290a96aa3bSJed Brown #include <p8est_lnodes.h> 300a96aa3bSJed Brown #include <p8est_vtk.h> 310a96aa3bSJed Brown #include <p8est_plex.h> 320a96aa3bSJed Brown #include <p8est_bits.h> 330a96aa3bSJed Brown #include <p8est_algorithms.h> 340a96aa3bSJed Brown #endif 350a96aa3bSJed Brown 369371c9d4SSatish Balay typedef enum { 379371c9d4SSatish Balay PATTERN_HASH, 389371c9d4SSatish Balay PATTERN_FRACTAL, 399371c9d4SSatish Balay PATTERN_CORNER, 409371c9d4SSatish Balay PATTERN_CENTER, 419371c9d4SSatish Balay PATTERN_COUNT 429371c9d4SSatish Balay } DMRefinePattern; 430a96aa3bSJed Brown static const char *DMRefinePatternName[PATTERN_COUNT] = {"hash", "fractal", "corner", "center"}; 440a96aa3bSJed Brown 459371c9d4SSatish Balay typedef struct _DMRefinePatternCtx { 460a96aa3bSJed Brown PetscInt corner; 470a96aa3bSJed Brown PetscBool fractal[P4EST_CHILDREN]; 480a96aa3bSJed Brown PetscReal hashLikelihood; 490a96aa3bSJed Brown PetscInt maxLevel; 500a96aa3bSJed Brown p4est_refine_t refine_fn; 519371c9d4SSatish Balay } DMRefinePatternCtx; 520a96aa3bSJed Brown 53d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Corner(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 54d71ae5a4SJacob Faibussowitsch { 550a96aa3bSJed Brown p4est_quadrant_t root, rootcorner; 560a96aa3bSJed Brown DMRefinePatternCtx *ctx; 570a96aa3bSJed Brown 580a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 590a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 600a96aa3bSJed Brown 610a96aa3bSJed Brown root.x = root.y = 0; 620a96aa3bSJed Brown #if defined(P4_TO_P8) 630a96aa3bSJed Brown root.z = 0; 640a96aa3bSJed Brown #endif 650a96aa3bSJed Brown root.level = 0; 660a96aa3bSJed Brown p4est_quadrant_corner_descendant(&root, &rootcorner, ctx->corner, quadrant->level); 670a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant, &rootcorner)) return 1; 680a96aa3bSJed Brown return 0; 690a96aa3bSJed Brown } 700a96aa3bSJed Brown 71d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Center(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 72d71ae5a4SJacob Faibussowitsch { 730a96aa3bSJed Brown int cid; 740a96aa3bSJed Brown p4est_quadrant_t ancestor, ancestorcorner; 750a96aa3bSJed Brown DMRefinePatternCtx *ctx; 760a96aa3bSJed Brown 770a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 780a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 790a96aa3bSJed Brown if (quadrant->level <= 1) return 1; 800a96aa3bSJed Brown 810a96aa3bSJed Brown p4est_quadrant_ancestor(quadrant, 1, &ancestor); 820a96aa3bSJed Brown cid = p4est_quadrant_child_id(&ancestor); 830a96aa3bSJed Brown p4est_quadrant_corner_descendant(&ancestor, &ancestorcorner, P4EST_CHILDREN - 1 - cid, quadrant->level); 840a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant, &ancestorcorner)) return 1; 850a96aa3bSJed Brown return 0; 860a96aa3bSJed Brown } 870a96aa3bSJed Brown 88d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Fractal(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 89d71ae5a4SJacob Faibussowitsch { 900a96aa3bSJed Brown int cid; 910a96aa3bSJed Brown DMRefinePatternCtx *ctx; 920a96aa3bSJed Brown 930a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 940a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 950a96aa3bSJed Brown if (!quadrant->level) return 1; 960a96aa3bSJed Brown cid = p4est_quadrant_child_id(quadrant); 970a96aa3bSJed Brown if (ctx->fractal[cid ^ ((int)(quadrant->level % P4EST_CHILDREN))]) return 1; 980a96aa3bSJed Brown return 0; 990a96aa3bSJed Brown } 1000a96aa3bSJed Brown 1010a96aa3bSJed Brown /* simplified from MurmurHash3 by Austin Appleby */ 1020a96aa3bSJed Brown #define DMPROT32(x, y) ((x << y) | (x >> (32 - y))) 103d71ae5a4SJacob Faibussowitsch static uint32_t DMPforestHash(const uint32_t *blocks, uint32_t nblocks) 104d71ae5a4SJacob Faibussowitsch { 1050a96aa3bSJed Brown uint32_t c1 = 0xcc9e2d51; 1060a96aa3bSJed Brown uint32_t c2 = 0x1b873593; 1070a96aa3bSJed Brown uint32_t r1 = 15; 1080a96aa3bSJed Brown uint32_t r2 = 13; 1090a96aa3bSJed Brown uint32_t m = 5; 1100a96aa3bSJed Brown uint32_t n = 0xe6546b64; 1110a96aa3bSJed Brown uint32_t hash = 0; 1120a96aa3bSJed Brown int len = nblocks * 4; 1130a96aa3bSJed Brown uint32_t i; 1140a96aa3bSJed Brown 1150a96aa3bSJed Brown for (i = 0; i < nblocks; i++) { 1160a96aa3bSJed Brown uint32_t k; 1170a96aa3bSJed Brown 1180a96aa3bSJed Brown k = blocks[i]; 1190a96aa3bSJed Brown k *= c1; 1200a96aa3bSJed Brown k = DMPROT32(k, r1); 1210a96aa3bSJed Brown k *= c2; 1220a96aa3bSJed Brown 1230a96aa3bSJed Brown hash ^= k; 1240a96aa3bSJed Brown hash = DMPROT32(hash, r2) * m + n; 1250a96aa3bSJed Brown } 1260a96aa3bSJed Brown 1270a96aa3bSJed Brown hash ^= len; 1280a96aa3bSJed Brown hash ^= (hash >> 16); 1290a96aa3bSJed Brown hash *= 0x85ebca6b; 1300a96aa3bSJed Brown hash ^= (hash >> 13); 1310a96aa3bSJed Brown hash *= 0xc2b2ae35; 1320a96aa3bSJed Brown hash ^= (hash >> 16); 1330a96aa3bSJed Brown 1340a96aa3bSJed Brown return hash; 1350a96aa3bSJed Brown } 1360a96aa3bSJed Brown 1370a96aa3bSJed Brown #if defined(UINT32_MAX) 1380a96aa3bSJed Brown #define DMP4EST_HASH_MAX UINT32_MAX 1390a96aa3bSJed Brown #else 1400a96aa3bSJed Brown #define DMP4EST_HASH_MAX ((uint32_t)0xffffffff) 1410a96aa3bSJed Brown #endif 1420a96aa3bSJed Brown 143d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Hash(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 144d71ae5a4SJacob Faibussowitsch { 1450a96aa3bSJed Brown uint32_t data[5]; 1460a96aa3bSJed Brown uint32_t result; 1470a96aa3bSJed Brown DMRefinePatternCtx *ctx; 1480a96aa3bSJed Brown 1490a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 1500a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 1510a96aa3bSJed Brown data[0] = ((uint32_t)quadrant->level) << 24; 1520a96aa3bSJed Brown data[1] = (uint32_t)which_tree; 1530a96aa3bSJed Brown data[2] = (uint32_t)quadrant->x; 1540a96aa3bSJed Brown data[3] = (uint32_t)quadrant->y; 1550a96aa3bSJed Brown #if defined(P4_TO_P8) 1560a96aa3bSJed Brown data[4] = (uint32_t)quadrant->z; 1570a96aa3bSJed Brown #endif 1580a96aa3bSJed Brown 1590a96aa3bSJed Brown result = DMPforestHash(data, 2 + P4EST_DIM); 1600a96aa3bSJed Brown if (((double)result / (double)DMP4EST_HASH_MAX) < ctx->hashLikelihood) return 1; 1610a96aa3bSJed Brown return 0; 1620a96aa3bSJed Brown } 1630a96aa3bSJed Brown 1640a96aa3bSJed Brown #define DMConvert_pforest_plex _infix_pforest(DMConvert, _plex) 1650a96aa3bSJed Brown static PetscErrorCode DMConvert_pforest_plex(DM, DMType, DM *); 1660a96aa3bSJed Brown 1670a96aa3bSJed Brown #define DMFTopology_pforest _append_pforest(DMFTopology) 1680a96aa3bSJed Brown typedef struct { 1690a96aa3bSJed Brown PetscInt refct; 1700a96aa3bSJed Brown p4est_connectivity_t *conn; 1710a96aa3bSJed Brown p4est_geometry_t *geom; 1720a96aa3bSJed Brown PetscInt *tree_face_to_uniq; /* p4est does not explicitly enumerate facets, but we must to keep track of labels */ 1730a96aa3bSJed Brown } DMFTopology_pforest; 1740a96aa3bSJed Brown 1750a96aa3bSJed Brown #define DM_Forest_pforest _append_pforest(DM_Forest) 1760a96aa3bSJed Brown typedef struct { 1770a96aa3bSJed Brown DMFTopology_pforest *topo; 1780a96aa3bSJed Brown p4est_t *forest; 1790a96aa3bSJed Brown p4est_ghost_t *ghost; 1800a96aa3bSJed Brown p4est_lnodes_t *lnodes; 1810a96aa3bSJed Brown PetscBool partition_for_coarsening; 1820a96aa3bSJed Brown PetscBool coarsen_hierarchy; 1830a96aa3bSJed Brown PetscBool labelsFinalized; 1840a96aa3bSJed Brown PetscBool adaptivitySuccess; 1850a96aa3bSJed Brown PetscInt cLocalStart; 1860a96aa3bSJed Brown PetscInt cLocalEnd; 1870a96aa3bSJed Brown DM plex; 1880a96aa3bSJed Brown char *ghostName; 1890a96aa3bSJed Brown PetscSF pointAdaptToSelfSF; 1900a96aa3bSJed Brown PetscSF pointSelfToAdaptSF; 1910a96aa3bSJed Brown PetscInt *pointAdaptToSelfCids; 1920a96aa3bSJed Brown PetscInt *pointSelfToAdaptCids; 1930a96aa3bSJed Brown } DM_Forest_pforest; 1940a96aa3bSJed Brown 1950a96aa3bSJed Brown #define DM_Forest_geometry_pforest _append_pforest(DM_Forest_geometry) 1960a96aa3bSJed Brown typedef struct { 1970a96aa3bSJed Brown DM base; 1980a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *); 1990a96aa3bSJed Brown void *mapCtx; 2000a96aa3bSJed Brown PetscInt coordDim; 2010a96aa3bSJed Brown p4est_geometry_t *inner; 2029371c9d4SSatish Balay } DM_Forest_geometry_pforest; 2030a96aa3bSJed Brown 2040a96aa3bSJed Brown #define GeometryMapping_pforest _append_pforest(GeometryMapping) 205d71ae5a4SJacob Faibussowitsch static void GeometryMapping_pforest(p4est_geometry_t *geom, p4est_topidx_t which_tree, const double abc[3], double xyz[3]) 206d71ae5a4SJacob Faibussowitsch { 2070a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest *)geom->user; 2080a96aa3bSJed Brown PetscReal PetscABC[3] = {0.}; 2090a96aa3bSJed Brown PetscReal PetscXYZ[3] = {0.}; 2100a96aa3bSJed Brown PetscInt i, d = PetscMin(3, geom_pforest->coordDim); 2110a96aa3bSJed Brown double ABC[3]; 2120a96aa3bSJed Brown PetscErrorCode ierr; 2130a96aa3bSJed Brown 2140a96aa3bSJed Brown (geom_pforest->inner->X)(geom_pforest->inner, which_tree, abc, ABC); 2150a96aa3bSJed Brown 2160a96aa3bSJed Brown for (i = 0; i < d; i++) PetscABC[i] = ABC[i]; 2179371c9d4SSatish Balay ierr = (geom_pforest->map)(geom_pforest->base, (PetscInt)which_tree, geom_pforest->coordDim, PetscABC, PetscXYZ, geom_pforest->mapCtx); 2189371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr); 2190a96aa3bSJed Brown for (i = 0; i < d; i++) xyz[i] = PetscXYZ[i]; 2200a96aa3bSJed Brown } 2210a96aa3bSJed Brown 2220a96aa3bSJed Brown #define GeometryDestroy_pforest _append_pforest(GeometryDestroy) 223d71ae5a4SJacob Faibussowitsch static void GeometryDestroy_pforest(p4est_geometry_t *geom) 224d71ae5a4SJacob Faibussowitsch { 2250a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest *)geom->user; 2260a96aa3bSJed Brown PetscErrorCode ierr; 2270a96aa3bSJed Brown 2280a96aa3bSJed Brown p4est_geometry_destroy(geom_pforest->inner); 2299371c9d4SSatish Balay ierr = PetscFree(geom->user); 2309371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr); 2319371c9d4SSatish Balay ierr = PetscFree(geom); 2329371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr); 2330a96aa3bSJed Brown } 2340a96aa3bSJed Brown 2350a96aa3bSJed Brown #define DMFTopologyDestroy_pforest _append_pforest(DMFTopologyDestroy) 236d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFTopologyDestroy_pforest(DMFTopology_pforest **topo) 237d71ae5a4SJacob Faibussowitsch { 2380a96aa3bSJed Brown PetscFunctionBegin; 2393ba16761SJacob Faibussowitsch if (!(*topo)) PetscFunctionReturn(PETSC_SUCCESS); 2400a96aa3bSJed Brown if (--((*topo)->refct) > 0) { 2410a96aa3bSJed Brown *topo = NULL; 2423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2430a96aa3bSJed Brown } 244792fecdfSBarry Smith if ((*topo)->geom) PetscCallP4est(p4est_geometry_destroy, ((*topo)->geom)); 245792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy, ((*topo)->conn)); 2469566063dSJacob Faibussowitsch PetscCall(PetscFree((*topo)->tree_face_to_uniq)); 2479566063dSJacob Faibussowitsch PetscCall(PetscFree(*topo)); 2480a96aa3bSJed Brown *topo = NULL; 2493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2500a96aa3bSJed Brown } 2510a96aa3bSJed Brown 2520a96aa3bSJed Brown static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *, PetscInt **); 2530a96aa3bSJed Brown 2540a96aa3bSJed Brown #define DMFTopologyCreateBrick_pforest _append_pforest(DMFTopologyCreateBrick) 255d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFTopologyCreateBrick_pforest(DM dm, PetscInt N[], PetscInt P[], PetscReal B[], DMFTopology_pforest **topo, PetscBool useMorton) 256d71ae5a4SJacob Faibussowitsch { 2570a96aa3bSJed Brown double *vertices; 2580a96aa3bSJed Brown PetscInt i, numVerts; 2590a96aa3bSJed Brown 2600a96aa3bSJed Brown PetscFunctionBegin; 26128b400f6SJacob Faibussowitsch PetscCheck(useMorton, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Lexicographic ordering not implemented yet"); 2624dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(topo)); 2630a96aa3bSJed Brown 2640a96aa3bSJed Brown (*topo)->refct = 1; 2650a96aa3bSJed Brown #if !defined(P4_TO_P8) 266792fecdfSBarry 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)); 2670a96aa3bSJed Brown #else 268792fecdfSBarry 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)); 2690a96aa3bSJed Brown #endif 2700a96aa3bSJed Brown numVerts = (*topo)->conn->num_vertices; 2710a96aa3bSJed Brown vertices = (*topo)->conn->vertices; 2720a96aa3bSJed Brown for (i = 0; i < 3 * numVerts; i++) { 2730a96aa3bSJed Brown PetscInt j = i % 3; 2740a96aa3bSJed Brown 2750a96aa3bSJed Brown vertices[i] = B[2 * j] + (vertices[i] / N[j]) * (B[2 * j + 1] - B[2 * j]); 2760a96aa3bSJed Brown } 2770a96aa3bSJed Brown (*topo)->geom = NULL; 2789566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn, &(*topo)->tree_face_to_uniq)); 2793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2800a96aa3bSJed Brown } 2810a96aa3bSJed Brown 2820a96aa3bSJed Brown #define DMFTopologyCreate_pforest _append_pforest(DMFTopologyCreate) 283d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFTopologyCreate_pforest(DM dm, DMForestTopology topologyName, DMFTopology_pforest **topo) 284d71ae5a4SJacob Faibussowitsch { 2850a96aa3bSJed Brown const char *name = (const char *)topologyName; 2860a96aa3bSJed Brown const char *prefix; 2870a96aa3bSJed Brown PetscBool isBrick, isShell, isSphere, isMoebius; 2880a96aa3bSJed Brown 2890a96aa3bSJed Brown PetscFunctionBegin; 2900a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2914f572ea9SToby Isaac PetscAssertPointer(name, 2); 2924f572ea9SToby Isaac PetscAssertPointer(topo, 3); 2939566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "brick", &isBrick)); 2949566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "shell", &isShell)); 2959566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "sphere", &isSphere)); 2969566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "moebius", &isMoebius)); 2979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 2980a96aa3bSJed Brown if (isBrick) { 2990a96aa3bSJed Brown PetscBool flgN, flgP, flgM, flgB, useMorton = PETSC_TRUE, periodic = PETSC_FALSE; 3000a96aa3bSJed Brown PetscInt N[3] = {2, 2, 2}, P[3] = {0, 0, 0}, nretN = P4EST_DIM, nretP = P4EST_DIM, nretB = 2 * P4EST_DIM, i; 3014fb89dddSMatthew 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}; 3020a96aa3bSJed Brown 3030a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_size", N, &nretN, &flgN)); 3059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_periodicity", P, &nretP, &flgP)); 3069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_bounds", B, &nretB, &flgB)); 3079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_use_morton_curve", &useMorton, &flgM)); 3081dca8a05SBarry 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); 3091dca8a05SBarry 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); 3101dca8a05SBarry 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); 3110a96aa3bSJed Brown } 3120a96aa3bSJed Brown for (i = 0; i < P4EST_DIM; i++) { 3130a96aa3bSJed Brown P[i] = (P[i] ? DM_BOUNDARY_PERIODIC : DM_BOUNDARY_NONE); 3140a96aa3bSJed Brown periodic = (PetscBool)(P[i] || periodic); 3150a96aa3bSJed Brown if (!flgB) B[2 * i + 1] = N[i]; 3166858538eSMatthew G. Knepley if (P[i]) { 3174fb89dddSMatthew G. Knepley Lstart[i] = B[2 * i + 0]; 3184fb89dddSMatthew G. Knepley L[i] = B[2 * i + 1] - B[2 * i + 0]; 3196858538eSMatthew G. Knepley maxCell[i] = 1.1 * (L[i] / N[i]); 3206858538eSMatthew G. Knepley } 3210a96aa3bSJed Brown } 3229566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm, N, P, B, topo, useMorton)); 3234fb89dddSMatthew G. Knepley if (periodic) PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 3240a96aa3bSJed Brown } else { 3254dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(topo)); 3260a96aa3bSJed Brown 3270a96aa3bSJed Brown (*topo)->refct = 1; 328792fecdfSBarry Smith PetscCallP4estReturn((*topo)->conn, p4est_connectivity_new_byname, (name)); 3290a96aa3bSJed Brown (*topo)->geom = NULL; 3301baa6e33SBarry Smith if (isMoebius) PetscCall(DMSetCoordinateDim(dm, 3)); 3310a96aa3bSJed Brown #if defined(P4_TO_P8) 3320a96aa3bSJed Brown if (isShell) { 3330a96aa3bSJed Brown PetscReal R2 = 1., R1 = .55; 3340a96aa3bSJed Brown 3350a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_shell_outer_radius", &R2, NULL)); 3379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_shell_inner_radius", &R1, NULL)); 3380a96aa3bSJed Brown } 339792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom, p8est_geometry_new_shell, ((*topo)->conn, R2, R1)); 3400a96aa3bSJed Brown } else if (isSphere) { 3410a96aa3bSJed Brown PetscReal R2 = 1., R1 = 0.191728, R0 = 0.039856; 3420a96aa3bSJed Brown 3430a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3449566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_outer_radius", &R2, NULL)); 3459566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_inner_radius", &R1, NULL)); 3469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_core_radius", &R0, NULL)); 3470a96aa3bSJed Brown } 348792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom, p8est_geometry_new_sphere, ((*topo)->conn, R2, R1, R0)); 3490a96aa3bSJed Brown } 3500a96aa3bSJed Brown #endif 3519566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn, &(*topo)->tree_face_to_uniq)); 3520a96aa3bSJed Brown } 3533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3540a96aa3bSJed Brown } 3550a96aa3bSJed Brown 3560a96aa3bSJed Brown #define DMConvert_plex_pforest _append_pforest(DMConvert_plex) 357d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMConvert_plex_pforest(DM dm, DMType newtype, DM *pforest) 358d71ae5a4SJacob Faibussowitsch { 3590a96aa3bSJed Brown MPI_Comm comm; 3600a96aa3bSJed Brown PetscBool isPlex; 3610a96aa3bSJed Brown PetscInt dim; 3620a96aa3bSJed Brown void *ctx; 3630a96aa3bSJed Brown 3640a96aa3bSJed Brown PetscFunctionBegin; 3650a96aa3bSJed Brown 3660a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3670a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 3689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isPlex)); 36928b400f6SJacob Faibussowitsch PetscCheck(isPlex, comm, PETSC_ERR_ARG_WRONG, "Expected DM type %s, got %s", DMPLEX, ((PetscObject)dm)->type_name); 3709566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 37163a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM, comm, PETSC_ERR_ARG_WRONG, "Expected DM dimension %d, got %" PetscInt_FMT, P4EST_DIM, dim); 3729566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, pforest)); 3739566063dSJacob Faibussowitsch PetscCall(DMSetType(*pforest, DMPFOREST)); 3749566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(*pforest, dm)); 3759566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dm, &ctx)); 3769566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(*pforest, ctx)); 3779566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *pforest)); 3783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3790a96aa3bSJed Brown } 3800a96aa3bSJed Brown 3810a96aa3bSJed Brown #define DMForestDestroy_pforest _append_pforest(DMForestDestroy) 382d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestDestroy_pforest(DM dm) 383d71ae5a4SJacob Faibussowitsch { 3840a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 3850a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 3860a96aa3bSJed Brown 3870a96aa3bSJed Brown PetscFunctionBegin; 3880a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 389792fecdfSBarry Smith if (pforest->lnodes) PetscCallP4est(p4est_lnodes_destroy, (pforest->lnodes)); 3900a96aa3bSJed Brown pforest->lnodes = NULL; 391792fecdfSBarry Smith if (pforest->ghost) PetscCallP4est(p4est_ghost_destroy, (pforest->ghost)); 3920a96aa3bSJed Brown pforest->ghost = NULL; 393792fecdfSBarry Smith if (pforest->forest) PetscCallP4est(p4est_destroy, (pforest->forest)); 3940a96aa3bSJed Brown pforest->forest = NULL; 3959566063dSJacob Faibussowitsch PetscCall(DMFTopologyDestroy_pforest(&pforest->topo)); 3969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_plex_pforest) "_C", NULL)); 3979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_pforest_plex) "_C", NULL)); 3982e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 3999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 4002e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 4012e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 4029566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName)); 4039566063dSJacob Faibussowitsch PetscCall(DMDestroy(&pforest->plex)); 4049566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointAdaptToSelfSF)); 4059566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointSelfToAdaptSF)); 4069566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 4079566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 4089566063dSJacob Faibussowitsch PetscCall(PetscFree(forest->data)); 4093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4100a96aa3bSJed Brown } 4110a96aa3bSJed Brown 4120a96aa3bSJed Brown #define DMForestTemplate_pforest _append_pforest(DMForestTemplate) 413d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestTemplate_pforest(DM dm, DM tdm) 414d71ae5a4SJacob Faibussowitsch { 4150a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 4160a96aa3bSJed Brown DM_Forest_pforest *tpforest = (DM_Forest_pforest *)((DM_Forest *)tdm->data)->data; 4170a96aa3bSJed Brown 4180a96aa3bSJed Brown PetscFunctionBegin; 4190a96aa3bSJed Brown if (pforest->topo) pforest->topo->refct++; 4209566063dSJacob Faibussowitsch PetscCall(DMFTopologyDestroy_pforest(&(tpforest->topo))); 4210a96aa3bSJed Brown tpforest->topo = pforest->topo; 4223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4230a96aa3bSJed Brown } 4240a96aa3bSJed Brown 4250a96aa3bSJed Brown #define DMPlexCreateConnectivity_pforest _append_pforest(DMPlexCreateConnectivity) 4260a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM, p4est_connectivity_t **, PetscInt **); 4270a96aa3bSJed Brown 4289371c9d4SSatish Balay typedef struct _PforestAdaptCtx { 4290a96aa3bSJed Brown PetscInt maxLevel; 4300a96aa3bSJed Brown PetscInt minLevel; 4310a96aa3bSJed Brown PetscInt currLevel; 4320a96aa3bSJed Brown PetscBool anyChange; 4339371c9d4SSatish Balay } PforestAdaptCtx; 4340a96aa3bSJed Brown 435d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_currlevel(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 436d71ae5a4SJacob Faibussowitsch { 4370a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4380a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4390a96aa3bSJed Brown PetscInt currLevel = ctx->currLevel; 4400a96aa3bSJed Brown 4410a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4420a96aa3bSJed Brown return (int)((PetscInt)quadrants[0]->level == currLevel); 4430a96aa3bSJed Brown } 4440a96aa3bSJed Brown 445d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_uniform(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 446d71ae5a4SJacob Faibussowitsch { 4470a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4480a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4490a96aa3bSJed Brown 4500a96aa3bSJed Brown return (int)((PetscInt)quadrants[0]->level > minLevel); 4510a96aa3bSJed Brown } 4520a96aa3bSJed Brown 453d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_flag_any(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 454d71ae5a4SJacob Faibussowitsch { 4550a96aa3bSJed Brown PetscInt i; 4560a96aa3bSJed Brown PetscBool any = PETSC_FALSE; 4570a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4580a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4590a96aa3bSJed Brown 4600a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4610a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 4620a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_KEEP) { 4630a96aa3bSJed Brown any = PETSC_FALSE; 4640a96aa3bSJed Brown break; 4650a96aa3bSJed Brown } 4660a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_COARSEN) { 4670a96aa3bSJed Brown any = PETSC_TRUE; 4680a96aa3bSJed Brown break; 4690a96aa3bSJed Brown } 4700a96aa3bSJed Brown } 4710a96aa3bSJed Brown return any ? 1 : 0; 4720a96aa3bSJed Brown } 4730a96aa3bSJed Brown 474d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_flag_all(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 475d71ae5a4SJacob Faibussowitsch { 4760a96aa3bSJed Brown PetscInt i; 4770a96aa3bSJed Brown PetscBool all = PETSC_TRUE; 4780a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4790a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4800a96aa3bSJed Brown 4810a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4820a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 4830a96aa3bSJed Brown if (quadrants[i]->p.user_int != DM_ADAPT_COARSEN) { 4840a96aa3bSJed Brown all = PETSC_FALSE; 4850a96aa3bSJed Brown break; 4860a96aa3bSJed Brown } 4870a96aa3bSJed Brown } 4880a96aa3bSJed Brown return all ? 1 : 0; 4890a96aa3bSJed Brown } 4900a96aa3bSJed Brown 491d71ae5a4SJacob Faibussowitsch static void pforest_init_determine(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 492d71ae5a4SJacob Faibussowitsch { 4930a96aa3bSJed Brown quadrant->p.user_int = DM_ADAPT_DETERMINE; 4940a96aa3bSJed Brown } 4950a96aa3bSJed Brown 496d71ae5a4SJacob Faibussowitsch static int pforest_refine_uniform(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 497d71ae5a4SJacob Faibussowitsch { 4980a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4990a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 5000a96aa3bSJed Brown 5010a96aa3bSJed Brown return ((PetscInt)quadrant->level < maxLevel); 5020a96aa3bSJed Brown } 5030a96aa3bSJed Brown 504d71ae5a4SJacob Faibussowitsch static int pforest_refine_flag(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 505d71ae5a4SJacob Faibussowitsch { 5060a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 5070a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 5080a96aa3bSJed Brown 5090a96aa3bSJed Brown if ((PetscInt)quadrant->level >= maxLevel) return 0; 5100a96aa3bSJed Brown 5110a96aa3bSJed Brown return (quadrant->p.user_int == DM_ADAPT_REFINE); 5120a96aa3bSJed Brown } 5130a96aa3bSJed Brown 514d71ae5a4SJacob Faibussowitsch 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) 515d71ae5a4SJacob Faibussowitsch { 5160a96aa3bSJed Brown PetscMPIInt rank = p4estFrom->mpirank; 5170a96aa3bSJed Brown p4est_topidx_t t; 5180a96aa3bSJed Brown PetscInt toFineLeaves = 0, fromFineLeaves = 0; 5190a96aa3bSJed Brown 5200a96aa3bSJed Brown PetscFunctionBegin; 5210a96aa3bSJed Brown for (t = flt; t <= llt; t++) { /* count roots and leaves */ 5220a96aa3bSJed Brown p4est_tree_t *treeFrom = &(((p4est_tree_t *)p4estFrom->trees->array)[t]); 5230a96aa3bSJed Brown p4est_tree_t *treeTo = &(((p4est_tree_t *)p4estTo->trees->array)[t]); 5240a96aa3bSJed Brown p4est_quadrant_t *firstFrom = &treeFrom->first_desc; 5250a96aa3bSJed Brown p4est_quadrant_t *firstTo = &treeTo->first_desc; 5260a96aa3bSJed Brown PetscInt numFrom = (PetscInt)treeFrom->quadrants.elem_count; 5270a96aa3bSJed Brown PetscInt numTo = (PetscInt)treeTo->quadrants.elem_count; 5280a96aa3bSJed Brown p4est_quadrant_t *quadsFrom = (p4est_quadrant_t *)treeFrom->quadrants.array; 5290a96aa3bSJed Brown p4est_quadrant_t *quadsTo = (p4est_quadrant_t *)treeTo->quadrants.array; 5300a96aa3bSJed Brown PetscInt currentFrom, currentTo; 5310a96aa3bSJed Brown PetscInt treeOffsetFrom = (PetscInt)treeFrom->quadrants_offset; 5320a96aa3bSJed Brown PetscInt treeOffsetTo = (PetscInt)treeTo->quadrants_offset; 5330a96aa3bSJed Brown int comp; 5340a96aa3bSJed Brown 535792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (firstFrom, firstTo)); 53628b400f6SJacob Faibussowitsch PetscCheck(comp, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "non-matching partitions"); 5370a96aa3bSJed Brown 5380a96aa3bSJed Brown for (currentFrom = 0, currentTo = 0; currentFrom < numFrom && currentTo < numTo;) { 5390a96aa3bSJed Brown p4est_quadrant_t *quadFrom = &quadsFrom[currentFrom]; 5400a96aa3bSJed Brown p4est_quadrant_t *quadTo = &quadsTo[currentTo]; 5410a96aa3bSJed Brown 5420a96aa3bSJed Brown if (quadFrom->level == quadTo->level) { 5430a96aa3bSJed Brown if (toLeaves) { 5440a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5450a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5460a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5470a96aa3bSJed Brown } 5480a96aa3bSJed Brown toFineLeaves++; 5490a96aa3bSJed Brown currentFrom++; 5500a96aa3bSJed Brown currentTo++; 5510a96aa3bSJed Brown } else { 5520a96aa3bSJed Brown int fromIsAncestor; 5530a96aa3bSJed Brown 554792fecdfSBarry Smith PetscCallP4estReturn(fromIsAncestor, p4est_quadrant_is_ancestor, (quadFrom, quadTo)); 5550a96aa3bSJed Brown if (fromIsAncestor) { 5560a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5570a96aa3bSJed Brown 5580a96aa3bSJed Brown if (toLeaves) { 5590a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5600a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5610a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5620a96aa3bSJed Brown } 5630a96aa3bSJed Brown toFineLeaves++; 5640a96aa3bSJed Brown currentTo++; 565792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant, (quadFrom, &lastDesc, quadTo->level)); 566792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (quadTo, &lastDesc)); 5670a96aa3bSJed Brown if (comp) currentFrom++; 5680a96aa3bSJed Brown } else { 5690a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5700a96aa3bSJed Brown 5710a96aa3bSJed Brown if (fromLeaves) { 5720a96aa3bSJed Brown fromLeaves[fromFineLeaves] = currentFrom + treeOffsetFrom + FromOffset; 5730a96aa3bSJed Brown toRoots[fromFineLeaves].rank = rank; 5740a96aa3bSJed Brown toRoots[fromFineLeaves].index = currentTo + treeOffsetTo + ToOffset; 5750a96aa3bSJed Brown } 5760a96aa3bSJed Brown fromFineLeaves++; 5770a96aa3bSJed Brown currentFrom++; 578792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant, (quadTo, &lastDesc, quadFrom->level)); 579792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (quadFrom, &lastDesc)); 5800a96aa3bSJed Brown if (comp) currentTo++; 5810a96aa3bSJed Brown } 5820a96aa3bSJed Brown } 5830a96aa3bSJed Brown } 5840a96aa3bSJed Brown } 5850a96aa3bSJed Brown *toFineLeavesCount = toFineLeaves; 5860a96aa3bSJed Brown *fromFineLeavesCount = fromFineLeaves; 5873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5880a96aa3bSJed Brown } 5890a96aa3bSJed Brown 5900a96aa3bSJed Brown /* Compute the maximum level across all the trees */ 591d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetRefinementLevel(DM dm, PetscInt *lev) 592d71ae5a4SJacob Faibussowitsch { 5930a96aa3bSJed Brown p4est_topidx_t t, flt, llt; 5940a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 5950a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 5960a96aa3bSJed Brown PetscInt maxlevelloc = 0; 5970a96aa3bSJed Brown p4est_t *p4est; 5980a96aa3bSJed Brown 5990a96aa3bSJed Brown PetscFunctionBegin; 60028b400f6SJacob Faibussowitsch PetscCheck(pforest, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing DM_Forest_pforest"); 60128b400f6SJacob Faibussowitsch PetscCheck(pforest->forest, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing p4est_t"); 6020a96aa3bSJed Brown p4est = pforest->forest; 6030a96aa3bSJed Brown flt = p4est->first_local_tree; 6040a96aa3bSJed Brown llt = p4est->last_local_tree; 6050a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 6060a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4est->trees->array)[t]); 6070a96aa3bSJed Brown maxlevelloc = PetscMax((PetscInt)tree->maxlevel, maxlevelloc); 6080a96aa3bSJed Brown } 6091c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&maxlevelloc, lev, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 6103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6110a96aa3bSJed Brown } 6120a96aa3bSJed Brown 6130a96aa3bSJed Brown /* Puts identity in coarseToFine */ 6140a96aa3bSJed Brown /* assumes a matching partition */ 615d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestComputeLocalCellTransferSF(MPI_Comm comm, p4est_t *p4estFrom, PetscInt FromOffset, p4est_t *p4estTo, PetscInt ToOffset, PetscSF *fromCoarseToFine, PetscSF *toCoarseFromFine) 616d71ae5a4SJacob Faibussowitsch { 6170a96aa3bSJed Brown p4est_topidx_t flt, llt; 6180a96aa3bSJed Brown PetscSF fromCoarse, toCoarse; 6190a96aa3bSJed Brown PetscInt numRootsFrom, numRootsTo, numLeavesFrom, numLeavesTo; 6200a96aa3bSJed Brown PetscInt *fromLeaves = NULL, *toLeaves = NULL; 6210a96aa3bSJed Brown PetscSFNode *fromRoots = NULL, *toRoots = NULL; 6220a96aa3bSJed Brown 6230a96aa3bSJed Brown PetscFunctionBegin; 6240a96aa3bSJed Brown flt = p4estFrom->first_local_tree; 6250a96aa3bSJed Brown llt = p4estFrom->last_local_tree; 6269566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &fromCoarse)); 62748a46eb9SPierre Jolivet if (toCoarseFromFine) PetscCall(PetscSFCreate(comm, &toCoarse)); 6280a96aa3bSJed Brown numRootsFrom = p4estFrom->local_num_quadrants + FromOffset; 6290a96aa3bSJed Brown numRootsTo = p4estTo->local_num_quadrants + ToOffset; 6309566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom, FromOffset, p4estTo, ToOffset, flt, llt, &numLeavesTo, NULL, NULL, &numLeavesFrom, NULL, NULL)); 6319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo, &toLeaves)); 6329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo, &fromRoots)); 6330a96aa3bSJed Brown if (toCoarseFromFine) { 6349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom, &fromLeaves)); 6359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom, &fromRoots)); 6360a96aa3bSJed Brown } 6379566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom, FromOffset, p4estTo, ToOffset, flt, llt, &numLeavesTo, toLeaves, fromRoots, &numLeavesFrom, fromLeaves, toRoots)); 6380a96aa3bSJed Brown if (!ToOffset && (numLeavesTo == numRootsTo)) { /* compress */ 6399566063dSJacob Faibussowitsch PetscCall(PetscFree(toLeaves)); 6409566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(fromCoarse, numRootsFrom, numLeavesTo, NULL, PETSC_OWN_POINTER, fromRoots, PETSC_OWN_POINTER)); 6411baa6e33SBarry Smith } else PetscCall(PetscSFSetGraph(fromCoarse, numRootsFrom, numLeavesTo, toLeaves, PETSC_OWN_POINTER, fromRoots, PETSC_OWN_POINTER)); 6420a96aa3bSJed Brown *fromCoarseToFine = fromCoarse; 6430a96aa3bSJed Brown if (toCoarseFromFine) { 6449566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(toCoarse, numRootsTo, numLeavesFrom, fromLeaves, PETSC_OWN_POINTER, toRoots, PETSC_OWN_POINTER)); 6450a96aa3bSJed Brown *toCoarseFromFine = toCoarse; 6460a96aa3bSJed Brown } 6473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6480a96aa3bSJed Brown } 6490a96aa3bSJed Brown 6500a96aa3bSJed Brown /* range of processes whose B sections overlap this ranks A section */ 651d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestComputeOverlappingRanks(PetscMPIInt size, PetscMPIInt rank, p4est_t *p4estA, p4est_t *p4estB, PetscInt *startB, PetscInt *endB) 652d71ae5a4SJacob Faibussowitsch { 6530a96aa3bSJed Brown p4est_quadrant_t *myCoarseStart = &(p4estA->global_first_position[rank]); 6540a96aa3bSJed Brown p4est_quadrant_t *myCoarseEnd = &(p4estA->global_first_position[rank + 1]); 6550a96aa3bSJed Brown p4est_quadrant_t *globalFirstB = p4estB->global_first_position; 6560a96aa3bSJed Brown 6570a96aa3bSJed Brown PetscFunctionBegin; 6580a96aa3bSJed Brown *startB = -1; 6590a96aa3bSJed Brown *endB = -1; 6600a96aa3bSJed Brown if (p4estA->local_num_quadrants) { 6610a96aa3bSJed Brown PetscInt lo, hi, guess; 6620a96aa3bSJed Brown /* binary search to find interval containing myCoarseStart */ 6630a96aa3bSJed Brown lo = 0; 6640a96aa3bSJed Brown hi = size; 6650a96aa3bSJed Brown guess = rank; 6660a96aa3bSJed Brown while (1) { 6670a96aa3bSJed Brown int startCompMy, myCompEnd; 6680a96aa3bSJed Brown 669792fecdfSBarry Smith PetscCallP4estReturn(startCompMy, p4est_quadrant_compare_piggy, (&globalFirstB[guess], myCoarseStart)); 670792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd, p4est_quadrant_compare_piggy, (myCoarseStart, &globalFirstB[guess + 1])); 6710a96aa3bSJed Brown if (startCompMy <= 0 && myCompEnd < 0) { 6720a96aa3bSJed Brown *startB = guess; 6730a96aa3bSJed Brown break; 6740a96aa3bSJed Brown } else if (startCompMy > 0) { /* guess is to high */ 6750a96aa3bSJed Brown hi = guess; 6760a96aa3bSJed Brown } else { /* guess is to low */ 6770a96aa3bSJed Brown lo = guess + 1; 6780a96aa3bSJed Brown } 6790a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6800a96aa3bSJed Brown } 6810a96aa3bSJed Brown /* reset bounds, but not guess */ 6820a96aa3bSJed Brown lo = 0; 6830a96aa3bSJed Brown hi = size; 6840a96aa3bSJed Brown while (1) { 6850a96aa3bSJed Brown int startCompMy, myCompEnd; 6860a96aa3bSJed Brown 687792fecdfSBarry Smith PetscCallP4estReturn(startCompMy, p4est_quadrant_compare_piggy, (&globalFirstB[guess], myCoarseEnd)); 688792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd, p4est_quadrant_compare_piggy, (myCoarseEnd, &globalFirstB[guess + 1])); 6890a96aa3bSJed Brown if (startCompMy < 0 && myCompEnd <= 0) { /* notice that the comparison operators are different from above */ 6900a96aa3bSJed Brown *endB = guess + 1; 6910a96aa3bSJed Brown break; 6920a96aa3bSJed Brown } else if (startCompMy >= 0) { /* guess is to high */ 6930a96aa3bSJed Brown hi = guess; 6940a96aa3bSJed Brown } else { /* guess is to low */ 6950a96aa3bSJed Brown lo = guess + 1; 6960a96aa3bSJed Brown } 6970a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6980a96aa3bSJed Brown } 6990a96aa3bSJed Brown } 7003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7010a96aa3bSJed Brown } 7020a96aa3bSJed Brown 7030a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM, DM *); 7040a96aa3bSJed Brown 7050a96aa3bSJed Brown #define DMSetUp_pforest _append_pforest(DMSetUp) 706d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetUp_pforest(DM dm) 707d71ae5a4SJacob Faibussowitsch { 7080a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 7090a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 7100a96aa3bSJed Brown DM base, adaptFrom; 7110a96aa3bSJed Brown DMForestTopology topoName; 7120a96aa3bSJed Brown PetscSF preCoarseToFine = NULL, coarseToPreFine = NULL; 7130a96aa3bSJed Brown PforestAdaptCtx ctx; 7140a96aa3bSJed Brown 7150a96aa3bSJed Brown PetscFunctionBegin; 7160a96aa3bSJed Brown ctx.minLevel = PETSC_MAX_INT; 7170a96aa3bSJed Brown ctx.maxLevel = 0; 7180a96aa3bSJed Brown ctx.currLevel = 0; 7190a96aa3bSJed Brown ctx.anyChange = PETSC_FALSE; 7200a96aa3bSJed Brown /* sanity check */ 7219566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm, &adaptFrom)); 7229566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 7239566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm, &topoName)); 7241dca8a05SBarry 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"); 7250a96aa3bSJed Brown 7260a96aa3bSJed Brown /* === Step 1: DMFTopology === */ 7270a96aa3bSJed Brown if (adaptFrom) { /* reference already created topology */ 7280a96aa3bSJed Brown PetscBool ispforest; 7290a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest *)adaptFrom->data; 7300a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest *)aforest->data; 7310a96aa3bSJed Brown 7329566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)adaptFrom, DMPFOREST, &ispforest)); 73328b400f6SJacob Faibussowitsch PetscCheck(ispforest, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NOTSAMETYPE, "Trying to adapt from %s, which is not %s", ((PetscObject)adaptFrom)->type_name, DMPFOREST); 73428b400f6SJacob Faibussowitsch PetscCheck(apforest->topo, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "The pre-adaptation forest must have a topology"); 7359566063dSJacob Faibussowitsch PetscCall(DMSetUp(adaptFrom)); 7369566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 7379566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm, &topoName)); 7380a96aa3bSJed Brown } else if (base) { /* construct a connectivity from base */ 7390a96aa3bSJed Brown PetscBool isPlex, isDA; 7400a96aa3bSJed Brown 7419566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)base, &topoName)); 7429566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm, topoName)); 7439566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base, DMPLEX, &isPlex)); 7449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base, DMDA, &isDA)); 7450a96aa3bSJed Brown if (isPlex) { 7460a96aa3bSJed Brown MPI_Comm comm = PetscObjectComm((PetscObject)dm); 7470a96aa3bSJed Brown PetscInt depth; 7480a96aa3bSJed Brown PetscMPIInt size; 7490a96aa3bSJed Brown p4est_connectivity_t *conn = NULL; 7500a96aa3bSJed Brown DMFTopology_pforest *topo; 7510a96aa3bSJed Brown PetscInt *tree_face_to_uniq = NULL; 7520a96aa3bSJed Brown 7539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(base, &depth)); 7540a96aa3bSJed Brown if (depth == 1) { 7550a96aa3bSJed Brown DM connDM; 7560a96aa3bSJed Brown 7579566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(base, &connDM)); 7580a96aa3bSJed Brown base = connDM; 7599566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm, base)); 7609566063dSJacob Faibussowitsch PetscCall(DMDestroy(&connDM)); 76163a3b9bcSJacob 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); 7629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 7630a96aa3bSJed Brown if (size > 1) { 7640a96aa3bSJed Brown DM dmRedundant; 7650a96aa3bSJed Brown PetscSF sf; 7660a96aa3bSJed Brown 7679566063dSJacob Faibussowitsch PetscCall(DMPlexGetRedundantDM(base, &sf, &dmRedundant)); 76828b400f6SJacob Faibussowitsch PetscCheck(dmRedundant, comm, PETSC_ERR_PLIB, "Could not create redundant DM"); 7699566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dmRedundant, "_base_migration_sf", (PetscObject)sf)); 7709566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 7710a96aa3bSJed Brown base = dmRedundant; 7729566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm, base)); 7739566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRedundant)); 7740a96aa3bSJed Brown } 7759566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(base, NULL, "-dm_p4est_base_view")); 7769566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConnectivity_pforest(base, &conn, &tree_face_to_uniq)); 7774dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&topo)); 7780a96aa3bSJed Brown topo->refct = 1; 7790a96aa3bSJed Brown topo->conn = conn; 7800a96aa3bSJed Brown topo->geom = NULL; 7810a96aa3bSJed Brown { 7820a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *); 7830a96aa3bSJed Brown void *mapCtx; 7840a96aa3bSJed Brown 7859566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx)); 7860a96aa3bSJed Brown if (map) { 7870a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest; 7880a96aa3bSJed Brown p4est_geometry_t *geom; 7890a96aa3bSJed Brown 7909566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom_pforest)); 7919566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &geom_pforest->coordDim)); 7920a96aa3bSJed Brown geom_pforest->map = map; 7930a96aa3bSJed Brown geom_pforest->mapCtx = mapCtx; 794792fecdfSBarry Smith PetscCallP4estReturn(geom_pforest->inner, p4est_geometry_new_connectivity, (conn)); 7959566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom)); 7960a96aa3bSJed Brown geom->name = topoName; 7970a96aa3bSJed Brown geom->user = geom_pforest; 7980a96aa3bSJed Brown geom->X = GeometryMapping_pforest; 7990a96aa3bSJed Brown geom->destroy = GeometryDestroy_pforest; 8000a96aa3bSJed Brown topo->geom = geom; 8010a96aa3bSJed Brown } 8020a96aa3bSJed Brown } 8030a96aa3bSJed Brown topo->tree_face_to_uniq = tree_face_to_uniq; 8040a96aa3bSJed Brown pforest->topo = topo; 80528b400f6SJacob Faibussowitsch } else PetscCheck(!isDA, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Not implemented yet"); 8060a96aa3bSJed Brown #if 0 8070a96aa3bSJed Brown PetscInt N[3], P[3]; 8080a96aa3bSJed Brown 8090a96aa3bSJed Brown /* get the sizes, periodicities */ 8100a96aa3bSJed Brown /* ... */ 8110a96aa3bSJed Brown /* don't use Morton order */ 8129566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm,N,P,&pforest->topo,PETSC_FALSE)); 8130a96aa3bSJed Brown #endif 8140a96aa3bSJed Brown { 8150a96aa3bSJed Brown PetscInt numLabels, l; 8160a96aa3bSJed Brown 8179566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(base, &numLabels)); 8180a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 8190a96aa3bSJed Brown PetscBool isDepth, isGhost, isVTK, isDim, isCellType; 8200a96aa3bSJed Brown DMLabel label, labelNew; 8210a96aa3bSJed Brown PetscInt defVal; 8220a96aa3bSJed Brown const char *name; 8230a96aa3bSJed Brown 8249566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(base, l, &name)); 8259566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(base, l, &label)); 8269566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 8270a96aa3bSJed Brown if (isDepth) continue; 8289566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "dim", &isDim)); 8290a96aa3bSJed Brown if (isDim) continue; 8309566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 8310a96aa3bSJed Brown if (isCellType) continue; 8329566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 8330a96aa3bSJed Brown if (isGhost) continue; 8349566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 8350a96aa3bSJed Brown if (isVTK) continue; 8369566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 8379566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &labelNew)); 8389566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defVal)); 8399566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew, defVal)); 8400a96aa3bSJed Brown } 8410a96aa3bSJed Brown /* map dm points (internal plex) to base 8420a96aa3bSJed Brown we currently create the subpoint_map for the entire hierarchy, starting from the finest forest 8430a96aa3bSJed Brown and propagating back to the coarsest 8440a96aa3bSJed Brown This is not an optimal approach, since we need the map only on the coarsest level 8450a96aa3bSJed Brown during DMForestTransferVecFromBase */ 8469566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &l)); 84748a46eb9SPierre Jolivet if (!l) PetscCall(DMCreateLabel(dm, "_forest_base_subpoint_map")); 8480a96aa3bSJed Brown } 8490a96aa3bSJed Brown } else { /* construct from topology name */ 8500a96aa3bSJed Brown DMFTopology_pforest *topo; 8510a96aa3bSJed Brown 8529566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreate_pforest(dm, topoName, &topo)); 8530a96aa3bSJed Brown pforest->topo = topo; 8540a96aa3bSJed Brown /* TODO: construct base? */ 8550a96aa3bSJed Brown } 8560a96aa3bSJed Brown 8570a96aa3bSJed Brown /* === Step 2: get the leaves of the forest === */ 8580a96aa3bSJed Brown if (adaptFrom) { /* start with the old forest */ 8590a96aa3bSJed Brown DMLabel adaptLabel; 8600a96aa3bSJed Brown PetscInt defaultValue; 8610a96aa3bSJed Brown PetscInt numValues, numValuesGlobal, cLocalStart, count; 8620a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest *)adaptFrom->data; 8630a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest *)aforest->data; 8640a96aa3bSJed Brown PetscBool computeAdaptSF; 8650a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 8660a96aa3bSJed Brown 8670a96aa3bSJed Brown flt = apforest->forest->first_local_tree; 8680a96aa3bSJed Brown llt = apforest->forest->last_local_tree; 8690a96aa3bSJed Brown cLocalStart = apforest->cLocalStart; 8709566063dSJacob Faibussowitsch PetscCall(DMForestGetComputeAdaptivitySF(dm, &computeAdaptSF)); 871792fecdfSBarry Smith PetscCallP4estReturn(pforest->forest, p4est_copy, (apforest->forest, 0)); /* 0 indicates no data copying */ 8729566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm, &adaptLabel)); 8730a96aa3bSJed Brown if (adaptLabel) { 8740a96aa3bSJed Brown /* apply the refinement/coarsening by flags, plus minimum/maximum refinement */ 8759566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(adaptLabel, &numValues)); 876712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &numValuesGlobal, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)adaptFrom))); 8779566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(adaptLabel, &defaultValue)); 8780a96aa3bSJed Brown if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN_LAST) { /* uniform coarsen of the last level only (equivalent to DM_ADAPT_COARSEN for conforming grids) */ 8799566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel)); 8809566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm, &ctx.currLevel)); 8810a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 882792fecdfSBarry Smith PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_currlevel, NULL)); 8830a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 884792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 8850a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 88648a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), pforest->forest, 0, apforest->forest, apforest->cLocalStart, &coarseToPreFine, NULL)); 8870a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN) { /* uniform coarsen */ 8889566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel)); 8890a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 890792fecdfSBarry Smith PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_uniform, NULL)); 8910a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 892792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 8930a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 89448a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), pforest->forest, 0, apforest->forest, apforest->cLocalStart, &coarseToPreFine, NULL)); 8950a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_REFINE) { /* uniform refine */ 8969566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &ctx.maxLevel)); 8970a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 898792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 0, pforest_refine_uniform, NULL)); 8990a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 900792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 9010a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 90248a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), apforest->forest, apforest->cLocalStart, pforest->forest, 0, &preCoarseToFine, NULL)); 9030a96aa3bSJed Brown } else if (numValuesGlobal) { 9040a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 9050a96aa3bSJed Brown PetscInt *cellFlags; 9060a96aa3bSJed Brown DMForestAdaptivityStrategy strategy; 9070a96aa3bSJed Brown PetscSF cellSF; 9080a96aa3bSJed Brown PetscInt c, cStart, cEnd; 9090a96aa3bSJed Brown PetscBool adaptAny; 9100a96aa3bSJed Brown 9119566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &ctx.maxLevel)); 9129566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel)); 9139566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityStrategy(dm, &strategy)); 9149566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(strategy, "any", 3, &adaptAny)); 9159566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(adaptFrom, &cStart, &cEnd)); 9169566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(adaptFrom, &cellSF)); 9179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cStart, &cellFlags)); 9189566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; c++) PetscCall(DMLabelGetValue(adaptLabel, c, &cellFlags[c - cStart])); 9190a96aa3bSJed Brown if (cellSF) { 9200a96aa3bSJed Brown if (adaptAny) { 9219566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MAX)); 9229566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MAX)); 9230a96aa3bSJed Brown } else { 9249566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MIN)); 9259566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MIN)); 9260a96aa3bSJed Brown } 9270a96aa3bSJed Brown } 9280a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9290a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4est->trees->array)[t]); 9300a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count, i; 9310a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 9320a96aa3bSJed Brown 9330a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9340a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9350a96aa3bSJed Brown q->p.user_int = cellFlags[count++]; 9360a96aa3bSJed Brown } 9370a96aa3bSJed Brown } 9389566063dSJacob Faibussowitsch PetscCall(PetscFree(cellFlags)); 9390a96aa3bSJed Brown 9400a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 941792fecdfSBarry Smith if (adaptAny) PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_flag_any, pforest_init_determine)); 942792fecdfSBarry Smith else PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_flag_all, pforest_init_determine)); 943792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 0, pforest_refine_flag, NULL)); 9440a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 945792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 94648a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), apforest->forest, apforest->cLocalStart, pforest->forest, 0, &preCoarseToFine, &coarseToPreFine)); 9470a96aa3bSJed Brown } 9480a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9490a96aa3bSJed Brown p4est_tree_t *atree = &(((p4est_tree_t *)apforest->forest->trees->array)[t]); 9500a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)pforest->forest->trees->array)[t]); 9510a96aa3bSJed Brown PetscInt anumQuads = (PetscInt)atree->quadrants.elem_count, i; 9520a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 9530a96aa3bSJed Brown p4est_quadrant_t *aquads = (p4est_quadrant_t *)atree->quadrants.array; 9540a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 9550a96aa3bSJed Brown 9560a96aa3bSJed Brown if (anumQuads != numQuads) { 9570a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9580a96aa3bSJed Brown } else { 9590a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9600a96aa3bSJed Brown p4est_quadrant_t *aq = &aquads[i]; 9610a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9620a96aa3bSJed Brown 9630a96aa3bSJed Brown if (aq->level != q->level) { 9640a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9650a96aa3bSJed Brown break; 9660a96aa3bSJed Brown } 9670a96aa3bSJed Brown } 9680a96aa3bSJed Brown } 969ad540459SPierre Jolivet if (ctx.anyChange) break; 9700a96aa3bSJed Brown } 9710a96aa3bSJed Brown } 9720a96aa3bSJed Brown { 9730a96aa3bSJed Brown PetscInt numLabels, l; 9740a96aa3bSJed Brown 9759566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(adaptFrom, &numLabels)); 9760a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 9770a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 9780a96aa3bSJed Brown DMLabel label, labelNew; 9790a96aa3bSJed Brown PetscInt defVal; 9800a96aa3bSJed Brown const char *name; 9810a96aa3bSJed Brown 9829566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(adaptFrom, l, &name)); 9839566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(adaptFrom, l, &label)); 9849566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 9850a96aa3bSJed Brown if (isDepth) continue; 9869566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 9870a96aa3bSJed Brown if (isCellType) continue; 9889566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 9890a96aa3bSJed Brown if (isGhost) continue; 9909566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 9910a96aa3bSJed Brown if (isVTK) continue; 9929566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 9939566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &labelNew)); 9949566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defVal)); 9959566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew, defVal)); 9960a96aa3bSJed Brown } 9970a96aa3bSJed Brown } 9980a96aa3bSJed Brown } else { /* initial */ 9990a96aa3bSJed Brown PetscInt initLevel, minLevel; 100066c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI) 100166c0a4b5SToby Isaac sc_MPI_Comm comm = sc_MPI_COMM_WORLD; 100266c0a4b5SToby Isaac #else 100366c0a4b5SToby Isaac MPI_Comm comm = PetscObjectComm((PetscObject)dm); 100466c0a4b5SToby Isaac #endif 10050a96aa3bSJed Brown 10069566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm, &initLevel)); 10079566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel)); 10089371c9d4SSatish Balay PetscCallP4estReturn(pforest->forest, p4est_new_ext, 10099371c9d4SSatish Balay (comm, pforest->topo->conn, 0, /* minimum number of quadrants per processor */ 10100a96aa3bSJed Brown initLevel, /* level of refinement */ 10110a96aa3bSJed Brown 1, /* uniform refinement */ 10120a96aa3bSJed Brown 0, /* we don't allocate any per quadrant data */ 10130a96aa3bSJed Brown NULL, /* there is no special quadrant initialization */ 10140a96aa3bSJed Brown (void *)dm)); /* this dm is the user context */ 10150a96aa3bSJed Brown 10160a96aa3bSJed Brown if (initLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 10170a96aa3bSJed Brown if (dm->setfromoptionscalled) { 10180a96aa3bSJed Brown PetscBool flgPattern, flgFractal; 10190a96aa3bSJed Brown PetscInt corner = 0; 10200a96aa3bSJed Brown PetscInt corners[P4EST_CHILDREN], ncorner = P4EST_CHILDREN; 10210a96aa3bSJed Brown PetscReal likelihood = 1. / P4EST_DIM; 10220a96aa3bSJed Brown PetscInt pattern; 10230a96aa3bSJed Brown const char *prefix; 10240a96aa3bSJed Brown 10259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 10269566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEList(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_pattern", DMRefinePatternName, PATTERN_COUNT, &pattern, &flgPattern)); 10279566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_corner", &corner, NULL)); 10289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_fractal_corners", corners, &ncorner, &flgFractal)); 10299566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_hash_likelihood", &likelihood, NULL)); 10300a96aa3bSJed Brown 10310a96aa3bSJed Brown if (flgPattern) { 10320a96aa3bSJed Brown DMRefinePatternCtx *ctx; 10330a96aa3bSJed Brown PetscInt maxLevel; 10340a96aa3bSJed Brown 10359566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &maxLevel)); 10364dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ctx)); 10370a96aa3bSJed Brown ctx->maxLevel = PetscMin(maxLevel, P4EST_QMAXLEVEL); 10380a96aa3bSJed Brown if (initLevel + ctx->maxLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 10390a96aa3bSJed Brown switch (pattern) { 10400a96aa3bSJed Brown case PATTERN_HASH: 10410a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Hash; 10420a96aa3bSJed Brown ctx->hashLikelihood = likelihood; 10430a96aa3bSJed Brown break; 10440a96aa3bSJed Brown case PATTERN_CORNER: 10450a96aa3bSJed Brown ctx->corner = corner; 10460a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Corner; 10470a96aa3bSJed Brown break; 1048d71ae5a4SJacob Faibussowitsch case PATTERN_CENTER: 1049d71ae5a4SJacob Faibussowitsch ctx->refine_fn = DMRefinePattern_Center; 1050d71ae5a4SJacob Faibussowitsch break; 10510a96aa3bSJed Brown case PATTERN_FRACTAL: 10520a96aa3bSJed Brown if (flgFractal) { 10530a96aa3bSJed Brown PetscInt i; 10540a96aa3bSJed Brown 10550a96aa3bSJed Brown for (i = 0; i < ncorner; i++) ctx->fractal[corners[i]] = PETSC_TRUE; 10560a96aa3bSJed Brown } else { 10570a96aa3bSJed Brown #if !defined(P4_TO_P8) 10580a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[1] = ctx->fractal[2] = PETSC_TRUE; 10590a96aa3bSJed Brown #else 10600a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[3] = ctx->fractal[5] = ctx->fractal[6] = PETSC_TRUE; 10610a96aa3bSJed Brown #endif 10620a96aa3bSJed Brown } 10630a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Fractal; 10640a96aa3bSJed Brown break; 1065d71ae5a4SJacob Faibussowitsch default: 1066d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Not a valid refinement pattern"); 10670a96aa3bSJed Brown } 10680a96aa3bSJed Brown 10690a96aa3bSJed Brown pforest->forest->user_pointer = (void *)ctx; 1070792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 1, ctx->refine_fn, NULL)); 1071792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 10729566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 10730a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 10740a96aa3bSJed Brown } 10750a96aa3bSJed Brown } 10760a96aa3bSJed Brown } 10770a96aa3bSJed Brown if (pforest->coarsen_hierarchy) { 10780a96aa3bSJed Brown PetscInt initLevel, currLevel, minLevel; 10790a96aa3bSJed Brown 10809566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm, &currLevel)); 10819566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm, &initLevel)); 10829566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel)); 10830a96aa3bSJed Brown if (currLevel > minLevel) { 10840a96aa3bSJed Brown DM_Forest_pforest *coarse_pforest; 10850a96aa3bSJed Brown DMLabel coarsen; 10860a96aa3bSJed Brown DM coarseDM; 10870a96aa3bSJed Brown 10889566063dSJacob Faibussowitsch PetscCall(DMForestTemplate(dm, MPI_COMM_NULL, &coarseDM)); 10899566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityPurpose(coarseDM, DM_ADAPT_COARSEN)); 10909566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "coarsen", &coarsen)); 10919566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(coarsen, DM_ADAPT_COARSEN)); 10929566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityLabel(coarseDM, coarsen)); 10939566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&coarsen)); 10949566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 10959566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 10960a96aa3bSJed Brown initLevel = currLevel == initLevel ? initLevel - 1 : initLevel; 10979566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(coarseDM, initLevel)); 10989566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(coarseDM, minLevel)); 10990a96aa3bSJed Brown coarse_pforest = (DM_Forest_pforest *)((DM_Forest *)coarseDM->data)->data; 11000a96aa3bSJed Brown coarse_pforest->coarsen_hierarchy = PETSC_TRUE; 11010a96aa3bSJed Brown } 11020a96aa3bSJed Brown } 11030a96aa3bSJed Brown 11040a96aa3bSJed Brown { /* repartitioning and overlap */ 11050a96aa3bSJed Brown PetscMPIInt size, rank; 11060a96aa3bSJed Brown 11079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 11089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 11090a96aa3bSJed Brown if ((size > 1) && (pforest->partition_for_coarsening || forest->cellWeights || forest->weightCapacity != 1. || forest->weightsFactor != 1.)) { 11100a96aa3bSJed Brown PetscBool copyForest = PETSC_FALSE; 11110a96aa3bSJed Brown p4est_t *forest_copy = NULL; 11120a96aa3bSJed Brown p4est_gloidx_t shipped = 0; 11130a96aa3bSJed Brown 11140a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) copyForest = PETSC_TRUE; 1115792fecdfSBarry Smith if (copyForest) PetscCallP4estReturn(forest_copy, p4est_copy, (pforest->forest, 0)); 11160a96aa3bSJed Brown 11170a96aa3bSJed Brown if (!forest->cellWeights && forest->weightCapacity == 1. && forest->weightsFactor == 1.) { 1118792fecdfSBarry Smith PetscCallP4estReturn(shipped, p4est_partition_ext, (pforest->forest, (int)pforest->partition_for_coarsening, NULL)); 11190a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Non-uniform partition cases not implemented yet"); 11200a96aa3bSJed Brown if (shipped) ctx.anyChange = PETSC_TRUE; 11210a96aa3bSJed Brown if (forest_copy) { 11220a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 11230a96aa3bSJed Brown PetscSF repartSF; /* repartSF has roots in the old partition */ 11240a96aa3bSJed Brown PetscInt pStart = -1, pEnd = -1, p; 11250a96aa3bSJed Brown PetscInt numRoots, numLeaves; 11260a96aa3bSJed Brown PetscSFNode *repartRoots; 11270a96aa3bSJed Brown p4est_gloidx_t postStart = pforest->forest->global_first_quadrant[rank]; 11280a96aa3bSJed Brown p4est_gloidx_t postEnd = pforest->forest->global_first_quadrant[rank + 1]; 11290a96aa3bSJed Brown p4est_gloidx_t partOffset = postStart; 11300a96aa3bSJed Brown 11310a96aa3bSJed Brown numRoots = (PetscInt)(forest_copy->global_first_quadrant[rank + 1] - forest_copy->global_first_quadrant[rank]); 11320a96aa3bSJed Brown numLeaves = (PetscInt)(postEnd - postStart); 11339566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(size, rank, pforest->forest, forest_copy, &pStart, &pEnd)); 11349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((PetscInt)pforest->forest->local_num_quadrants, &repartRoots)); 11350a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 11360a96aa3bSJed Brown p4est_gloidx_t preStart = forest_copy->global_first_quadrant[p]; 11370a96aa3bSJed Brown p4est_gloidx_t preEnd = forest_copy->global_first_quadrant[p + 1]; 11380a96aa3bSJed Brown PetscInt q; 11390a96aa3bSJed Brown 11400a96aa3bSJed Brown if (preEnd == preStart) continue; 114108401ef6SPierre Jolivet PetscCheck(preStart <= postStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad partition overlap computation"); 11420a96aa3bSJed Brown preEnd = preEnd > postEnd ? postEnd : preEnd; 11430a96aa3bSJed Brown for (q = partOffset; q < preEnd; q++) { 11440a96aa3bSJed Brown repartRoots[q - postStart].rank = p; 11450a96aa3bSJed Brown repartRoots[q - postStart].index = partOffset - preStart; 11460a96aa3bSJed Brown } 11470a96aa3bSJed Brown partOffset = preEnd; 11480a96aa3bSJed Brown } 11499566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &repartSF)); 11509566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(repartSF, numRoots, numLeaves, NULL, PETSC_OWN_POINTER, repartRoots, PETSC_OWN_POINTER)); 11519566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(repartSF)); 11520a96aa3bSJed Brown if (preCoarseToFine) { 11530a96aa3bSJed Brown PetscSF repartSFembed, preCoarseToFineNew; 11540a96aa3bSJed Brown PetscInt nleaves; 11550a96aa3bSJed Brown const PetscInt *leaves; 11560a96aa3bSJed Brown 11579566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 11589566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine, NULL, &nleaves, &leaves, NULL)); 11590a96aa3bSJed Brown if (leaves) { 11609566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(repartSF, nleaves, leaves, &repartSFembed)); 11610a96aa3bSJed Brown } else { 11620a96aa3bSJed Brown repartSFembed = repartSF; 11639566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)repartSFembed)); 11640a96aa3bSJed Brown } 11659566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(preCoarseToFine, repartSFembed, &preCoarseToFineNew)); 11669566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 11679566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFembed)); 11680a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 11690a96aa3bSJed Brown } 11700a96aa3bSJed Brown if (coarseToPreFine) { 11710a96aa3bSJed Brown PetscSF repartSFinv, coarseToPreFineNew; 11720a96aa3bSJed Brown 11739566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(repartSF, &repartSFinv)); 11749566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(repartSFinv, coarseToPreFine, &coarseToPreFineNew)); 11759566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 11769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFinv)); 11770a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 11780a96aa3bSJed Brown } 11799566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSF)); 11800a96aa3bSJed Brown } 1181792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (forest_copy)); 11820a96aa3bSJed Brown } 11830a96aa3bSJed Brown } 11840a96aa3bSJed Brown if (size > 1) { 11850a96aa3bSJed Brown PetscInt overlap; 11860a96aa3bSJed Brown 11879566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 11880a96aa3bSJed Brown 11890a96aa3bSJed Brown if (adaptFrom) { 11900a96aa3bSJed Brown PetscInt aoverlap; 11910a96aa3bSJed Brown 11929566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(adaptFrom, &aoverlap)); 1193ad540459SPierre Jolivet if (aoverlap != overlap) ctx.anyChange = PETSC_TRUE; 11940a96aa3bSJed Brown } 11950a96aa3bSJed Brown 11960a96aa3bSJed Brown if (overlap > 0) { 11970a96aa3bSJed Brown PetscInt i, cLocalStart; 11980a96aa3bSJed Brown PetscInt cEnd; 11990a96aa3bSJed Brown PetscSF preCellSF = NULL, cellSF = NULL; 12000a96aa3bSJed Brown 1201792fecdfSBarry Smith PetscCallP4estReturn(pforest->ghost, p4est_ghost_new, (pforest->forest, P4EST_CONNECT_FULL)); 1202792fecdfSBarry Smith PetscCallP4estReturn(pforest->lnodes, p4est_lnodes_new, (pforest->forest, pforest->ghost, -P4EST_DIM)); 1203792fecdfSBarry Smith PetscCallP4est(p4est_ghost_support_lnodes, (pforest->forest, pforest->lnodes, pforest->ghost)); 1204792fecdfSBarry Smith for (i = 1; i < overlap; i++) PetscCallP4est(p4est_ghost_expand_by_lnodes, (pforest->forest, pforest->lnodes, pforest->ghost)); 12050a96aa3bSJed Brown 12060a96aa3bSJed Brown cLocalStart = pforest->cLocalStart = pforest->ghost->proc_offsets[rank]; 12070a96aa3bSJed Brown cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[size]; 12080a96aa3bSJed Brown 12090a96aa3bSJed Brown /* shift sfs by cLocalStart, expand by cell SFs */ 12100a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 12119566063dSJacob Faibussowitsch if (adaptFrom) PetscCall(DMForestGetCellSF(adaptFrom, &preCellSF)); 12120a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 12139566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(dm, &cellSF)); 12140a96aa3bSJed Brown } 12150a96aa3bSJed Brown if (preCoarseToFine) { 12160a96aa3bSJed Brown PetscSF preCoarseToFineNew; 12170a96aa3bSJed Brown PetscInt nleaves, nroots, *leavesNew, i, nleavesNew; 12180a96aa3bSJed Brown const PetscInt *leaves; 12190a96aa3bSJed Brown const PetscSFNode *remotes; 12200a96aa3bSJed Brown PetscSFNode *remotesAll; 12210a96aa3bSJed Brown 12229566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 12239566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine, &nroots, &nleaves, &leaves, &remotes)); 12249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd, &remotesAll)); 12250a96aa3bSJed Brown for (i = 0; i < cEnd; i++) { 12260a96aa3bSJed Brown remotesAll[i].rank = -1; 12270a96aa3bSJed Brown remotesAll[i].index = -1; 12280a96aa3bSJed Brown } 12290a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesAll[(leaves ? leaves[i] : i) + cLocalStart] = remotes[i]; 12309566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(cellSF)); 12319566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(cellSF, MPIU_2INT, remotesAll, remotesAll, MPI_REPLACE)); 12329566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(cellSF, MPIU_2INT, remotesAll, remotesAll, MPI_REPLACE)); 12330a96aa3bSJed Brown nleavesNew = 0; 12340a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12350a96aa3bSJed Brown if (remotesAll[i].rank >= 0) nleavesNew++; 12360a96aa3bSJed Brown } 12379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesNew, &leavesNew)); 12380a96aa3bSJed Brown nleavesNew = 0; 12390a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12400a96aa3bSJed Brown if (remotesAll[i].rank >= 0) { 12410a96aa3bSJed Brown leavesNew[nleavesNew] = i; 12420a96aa3bSJed Brown if (i > nleavesNew) remotesAll[nleavesNew] = remotesAll[i]; 12430a96aa3bSJed Brown nleavesNew++; 12440a96aa3bSJed Brown } 12450a96aa3bSJed Brown } 12469566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &preCoarseToFineNew)); 12470a96aa3bSJed Brown if (nleavesNew < cEnd) { 12489566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew, nroots, nleavesNew, leavesNew, PETSC_OWN_POINTER, remotesAll, PETSC_COPY_VALUES)); 12490a96aa3bSJed Brown } else { /* all cells are leaves */ 12509566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 12519566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew, nroots, nleavesNew, NULL, PETSC_OWN_POINTER, remotesAll, PETSC_COPY_VALUES)); 12520a96aa3bSJed Brown } 12539566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesAll)); 12549566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 12550a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12560a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12570a96aa3bSJed Brown } 12580a96aa3bSJed Brown if (coarseToPreFine) { 12590a96aa3bSJed Brown PetscSF coarseToPreFineNew; 12600a96aa3bSJed Brown PetscInt nleaves, nroots, i, nleavesCellSF, nleavesExpanded, *leavesNew; 12610a96aa3bSJed Brown const PetscInt *leaves; 12620a96aa3bSJed Brown const PetscSFNode *remotes; 12630a96aa3bSJed Brown PetscSFNode *remotesNew, *remotesNewRoot, *remotesExpanded; 12640a96aa3bSJed Brown 12659566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(coarseToPreFine)); 12669566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToPreFine, &nroots, &nleaves, &leaves, &remotes)); 12679566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCellSF, NULL, &nleavesCellSF, NULL, NULL)); 12689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &remotesNewRoot)); 12699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotesNew)); 12700a96aa3bSJed Brown for (i = 0; i < nroots; i++) { 12710a96aa3bSJed Brown remotesNewRoot[i].rank = rank; 12720a96aa3bSJed Brown remotesNewRoot[i].index = i + cLocalStart; 12730a96aa3bSJed Brown } 12749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToPreFine, MPIU_2INT, remotesNewRoot, remotesNew, MPI_REPLACE)); 12759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToPreFine, MPIU_2INT, remotesNewRoot, remotesNew, MPI_REPLACE)); 12769566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNewRoot)); 12779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesCellSF, &remotesExpanded)); 12780a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12790a96aa3bSJed Brown remotesExpanded[i].rank = -1; 12800a96aa3bSJed Brown remotesExpanded[i].index = -1; 12810a96aa3bSJed Brown } 12820a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesExpanded[leaves ? leaves[i] : i] = remotesNew[i]; 12839566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNew)); 12849566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(preCellSF, MPIU_2INT, remotesExpanded, remotesExpanded, MPI_REPLACE)); 12859566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(preCellSF, MPIU_2INT, remotesExpanded, remotesExpanded, MPI_REPLACE)); 12860a96aa3bSJed Brown 12870a96aa3bSJed Brown nleavesExpanded = 0; 12880a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12890a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) nleavesExpanded++; 12900a96aa3bSJed Brown } 12919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesExpanded, &leavesNew)); 12920a96aa3bSJed Brown nleavesExpanded = 0; 12930a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12940a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) { 12950a96aa3bSJed Brown leavesNew[nleavesExpanded] = i; 12960a96aa3bSJed Brown if (i > nleavesExpanded) remotesExpanded[nleavesExpanded] = remotes[i]; 12970a96aa3bSJed Brown nleavesExpanded++; 12980a96aa3bSJed Brown } 12990a96aa3bSJed Brown } 13009566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &coarseToPreFineNew)); 13010a96aa3bSJed Brown if (nleavesExpanded < nleavesCellSF) { 13029566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew, cEnd, nleavesExpanded, leavesNew, PETSC_OWN_POINTER, remotesExpanded, PETSC_COPY_VALUES)); 13030a96aa3bSJed Brown } else { 13049566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 13059566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew, cEnd, nleavesExpanded, NULL, PETSC_OWN_POINTER, remotesExpanded, PETSC_COPY_VALUES)); 13060a96aa3bSJed Brown } 13079566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesExpanded)); 13089566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 13090a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 13100a96aa3bSJed Brown } 13110a96aa3bSJed Brown } 13120a96aa3bSJed Brown } 13130a96aa3bSJed Brown } 13140a96aa3bSJed Brown forest->preCoarseToFine = preCoarseToFine; 13150a96aa3bSJed Brown forest->coarseToPreFine = coarseToPreFine; 13160a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 1317*d72c4dc2SStefano Zampini PetscCall(MPIU_Allreduce(&ctx.anyChange, &pforest->adaptivitySuccess, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 13189566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, NULL)); 13193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13200a96aa3bSJed Brown } 13210a96aa3bSJed Brown 13220a96aa3bSJed Brown #define DMForestGetAdaptivitySuccess_pforest _append_pforest(DMForestGetAdaptivitySuccess) 1323d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestGetAdaptivitySuccess_pforest(DM dm, PetscBool *success) 1324d71ae5a4SJacob Faibussowitsch { 13250a96aa3bSJed Brown DM_Forest *forest; 13260a96aa3bSJed Brown DM_Forest_pforest *pforest; 13270a96aa3bSJed Brown 13280a96aa3bSJed Brown PetscFunctionBegin; 13290a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 13300a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 13310a96aa3bSJed Brown *success = pforest->adaptivitySuccess; 13323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13330a96aa3bSJed Brown } 13340a96aa3bSJed Brown 13350a96aa3bSJed Brown #define DMView_ASCII_pforest _append_pforest(DMView_ASCII) 1336d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_ASCII_pforest(PetscObject odm, PetscViewer viewer) 1337d71ae5a4SJacob Faibussowitsch { 13380a96aa3bSJed Brown DM dm = (DM)odm; 13390a96aa3bSJed Brown 13400a96aa3bSJed Brown PetscFunctionBegin; 13410a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13420a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13439566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13440a96aa3bSJed Brown switch (viewer->format) { 13450a96aa3bSJed Brown case PETSC_VIEWER_DEFAULT: 13469371c9d4SSatish Balay case PETSC_VIEWER_ASCII_INFO: { 13470a96aa3bSJed Brown PetscInt dim; 13480a96aa3bSJed Brown const char *name; 13490a96aa3bSJed Brown 13509566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 13519566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 135263a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "Forest %s in %" PetscInt_FMT " dimensions:\n", name, dim)); 135363a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Forest in %" PetscInt_FMT " dimensions:\n", dim)); 1354f4d061e9SPierre Jolivet } /* fall through */ 13550a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO_DETAIL: 13569371c9d4SSatish Balay case PETSC_VIEWER_LOAD_BALANCE: { 13570a96aa3bSJed Brown DM plex; 13580a96aa3bSJed Brown 13599566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 13609566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 13619371c9d4SSatish Balay } break; 1362d71ae5a4SJacob Faibussowitsch default: 1363d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 13640a96aa3bSJed Brown } 13653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13660a96aa3bSJed Brown } 13670a96aa3bSJed Brown 13680a96aa3bSJed Brown #define DMView_VTK_pforest _append_pforest(DMView_VTK) 1369d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_VTK_pforest(PetscObject odm, PetscViewer viewer) 1370d71ae5a4SJacob Faibussowitsch { 13710a96aa3bSJed Brown DM dm = (DM)odm; 13720a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 13730a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 13740a96aa3bSJed Brown PetscBool isvtk; 13750a96aa3bSJed Brown PetscReal vtkScale = 1. - PETSC_MACHINE_EPSILON; 13760a96aa3bSJed Brown PetscViewer_VTK *vtk = (PetscViewer_VTK *)viewer->data; 13770a96aa3bSJed Brown const char *name; 13780a96aa3bSJed Brown char *filenameStrip = NULL; 13790a96aa3bSJed Brown PetscBool hasExt; 13800a96aa3bSJed Brown size_t len; 13810a96aa3bSJed Brown p4est_geometry_t *geom; 13820a96aa3bSJed Brown 13830a96aa3bSJed Brown PetscFunctionBegin; 13840a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13850a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13869566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13870a96aa3bSJed Brown geom = pforest->topo->geom; 13889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 138928b400f6SJacob Faibussowitsch PetscCheck(isvtk, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name); 13900a96aa3bSJed Brown switch (viewer->format) { 13910a96aa3bSJed Brown case PETSC_VIEWER_VTK_VTU: 139228b400f6SJacob Faibussowitsch PetscCheck(pforest->forest, PetscObjectComm(odm), PETSC_ERR_ARG_WRONG, "DM has not been setup with a valid forest"); 13930a96aa3bSJed Brown name = vtk->filename; 13949566063dSJacob Faibussowitsch PetscCall(PetscStrlen(name, &len)); 13959566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(name + len - 4, ".vtu", &hasExt)); 13960a96aa3bSJed Brown if (hasExt) { 13979566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &filenameStrip)); 13980a96aa3bSJed Brown filenameStrip[len - 4] = '\0'; 13990a96aa3bSJed Brown name = filenameStrip; 14000a96aa3bSJed Brown } 1401792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4estReturn(geom, p4est_geometry_new_connectivity, (pforest->topo->conn)); 14020a96aa3bSJed Brown { 14030a96aa3bSJed Brown p4est_vtk_context_t *pvtk; 14040a96aa3bSJed Brown int footerr; 14050a96aa3bSJed Brown 1406792fecdfSBarry Smith PetscCallP4estReturn(pvtk, p4est_vtk_context_new, (pforest->forest, name)); 1407792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_geom, (pvtk, geom)); 1408792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_scale, (pvtk, (double)vtkScale)); 1409792fecdfSBarry Smith PetscCallP4estReturn(pvtk, p4est_vtk_write_header, (pvtk)); 141028b400f6SJacob Faibussowitsch PetscCheck(pvtk, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_header() failed"); 14119371c9d4SSatish Balay PetscCallP4estReturn(pvtk, p4est_vtk_write_cell_dataf, 14129371c9d4SSatish Balay (pvtk, 1, /* write tree */ 14130a96aa3bSJed Brown 1, /* write level */ 14140a96aa3bSJed Brown 1, /* write rank */ 14150a96aa3bSJed Brown 0, /* do not wrap rank */ 14160a96aa3bSJed Brown 0, /* no scalar fields */ 14170a96aa3bSJed Brown 0, /* no vector fields */ 14180a96aa3bSJed Brown pvtk)); 141928b400f6SJacob Faibussowitsch PetscCheck(pvtk, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_cell_dataf() failed"); 1420792fecdfSBarry Smith PetscCallP4estReturn(footerr, p4est_vtk_write_footer, (pvtk)); 142128b400f6SJacob Faibussowitsch PetscCheck(!footerr, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_footer() failed"); 14220a96aa3bSJed Brown } 1423792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4est(p4est_geometry_destroy, (geom)); 14249566063dSJacob Faibussowitsch PetscCall(PetscFree(filenameStrip)); 14250a96aa3bSJed Brown break; 1426d71ae5a4SJacob Faibussowitsch default: 1427d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 14280a96aa3bSJed Brown } 14293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14300a96aa3bSJed Brown } 14310a96aa3bSJed Brown 14320a96aa3bSJed Brown #define DMView_HDF5_pforest _append_pforest(DMView_HDF5) 1433d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_HDF5_pforest(DM dm, PetscViewer viewer) 1434d71ae5a4SJacob Faibussowitsch { 14350a96aa3bSJed Brown DM plex; 14360a96aa3bSJed Brown 14370a96aa3bSJed Brown PetscFunctionBegin; 14389566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 14399566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 14409566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 14413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14420a96aa3bSJed Brown } 14430a96aa3bSJed Brown 14440a96aa3bSJed Brown #define DMView_GLVis_pforest _append_pforest(DMView_GLVis) 1445d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_GLVis_pforest(DM dm, PetscViewer viewer) 1446d71ae5a4SJacob Faibussowitsch { 14470a96aa3bSJed Brown DM plex; 14480a96aa3bSJed Brown 14490a96aa3bSJed Brown PetscFunctionBegin; 14509566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 14519566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 14529566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 14533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14540a96aa3bSJed Brown } 14550a96aa3bSJed Brown 14560a96aa3bSJed Brown #define DMView_pforest _append_pforest(DMView) 1457d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_pforest(DM dm, PetscViewer viewer) 1458d71ae5a4SJacob Faibussowitsch { 14590a96aa3bSJed Brown PetscBool isascii, isvtk, ishdf5, isglvis; 14600a96aa3bSJed Brown 14610a96aa3bSJed Brown PetscFunctionBegin; 14620a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14630a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 14649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 14659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 14669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 14679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 14680a96aa3bSJed Brown if (isascii) { 14699566063dSJacob Faibussowitsch PetscCall(DMView_ASCII_pforest((PetscObject)dm, viewer)); 14700a96aa3bSJed Brown } else if (isvtk) { 14719566063dSJacob Faibussowitsch PetscCall(DMView_VTK_pforest((PetscObject)dm, viewer)); 14720a96aa3bSJed Brown } else if (ishdf5) { 14739566063dSJacob Faibussowitsch PetscCall(DMView_HDF5_pforest(dm, viewer)); 14740a96aa3bSJed Brown } else if (isglvis) { 14759566063dSJacob Faibussowitsch PetscCall(DMView_GLVis_pforest(dm, viewer)); 14760a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer not supported (not VTK, HDF5, or GLVis)"); 14773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14780a96aa3bSJed Brown } 14790a96aa3bSJed Brown 1480d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *conn, PetscInt **tree_face_to_uniq) 1481d71ae5a4SJacob Faibussowitsch { 14820a96aa3bSJed Brown PetscInt *ttf, f, t, g, count; 14830a96aa3bSJed Brown PetscInt numFacets; 14840a96aa3bSJed Brown 14850a96aa3bSJed Brown PetscFunctionBegin; 14860a96aa3bSJed Brown numFacets = conn->num_trees * P4EST_FACES; 14879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFacets, &ttf)); 14880a96aa3bSJed Brown for (f = 0; f < numFacets; f++) ttf[f] = -1; 14890a96aa3bSJed Brown for (g = 0, count = 0, t = 0; t < conn->num_trees; t++) { 14900a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++, g++) { 14910a96aa3bSJed Brown if (ttf[g] == -1) { 14920a96aa3bSJed Brown PetscInt ng; 14930a96aa3bSJed Brown 14940a96aa3bSJed Brown ttf[g] = count++; 14950a96aa3bSJed Brown ng = conn->tree_to_tree[g] * P4EST_FACES + (conn->tree_to_face[g] % P4EST_FACES); 14960a96aa3bSJed Brown ttf[ng] = ttf[g]; 14970a96aa3bSJed Brown } 14980a96aa3bSJed Brown } 14990a96aa3bSJed Brown } 15000a96aa3bSJed Brown *tree_face_to_uniq = ttf; 15013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15020a96aa3bSJed Brown } 15030a96aa3bSJed Brown 1504d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConnectivity_pforest(DM dm, p4est_connectivity_t **connOut, PetscInt **tree_face_to_uniq) 1505d71ae5a4SJacob Faibussowitsch { 15060a96aa3bSJed Brown p4est_topidx_t numTrees, numVerts, numCorns, numCtt; 15070a96aa3bSJed Brown PetscSection ctt; 15080a96aa3bSJed Brown #if defined(P4_TO_P8) 15090a96aa3bSJed Brown p4est_topidx_t numEdges, numEtt; 15100a96aa3bSJed Brown PetscSection ett; 15110a96aa3bSJed Brown PetscInt eStart, eEnd, e, ettSize; 15120a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES + P8EST_EDGES; 15130a96aa3bSJed Brown PetscInt edgeOff = 1 + P4EST_FACES; 15140a96aa3bSJed Brown #else 15150a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES; 15160a96aa3bSJed Brown #endif 15170a96aa3bSJed Brown p4est_connectivity_t *conn; 15180a96aa3bSJed Brown PetscInt cStart, cEnd, c, vStart, vEnd, v, fStart, fEnd, f; 15190a96aa3bSJed Brown PetscInt *star = NULL, *closure = NULL, closureSize, starSize, cttSize; 15200a96aa3bSJed Brown PetscInt *ttf; 15210a96aa3bSJed Brown 15220a96aa3bSJed Brown PetscFunctionBegin; 15230a96aa3bSJed Brown /* 1: count objects, allocate */ 15249566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 15259566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cEnd - cStart, &numTrees)); 15260a96aa3bSJed Brown numVerts = P4EST_CHILDREN * numTrees; 15279566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 15289566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(vEnd - vStart, &numCorns)); 15299566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &ctt)); 15309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ctt, vStart, vEnd)); 15310a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 15320a96aa3bSJed Brown PetscInt s; 15330a96aa3bSJed Brown 15349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 15350a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 15360a96aa3bSJed Brown PetscInt p = star[2 * s]; 15370a96aa3bSJed Brown 15380a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 15390a96aa3bSJed Brown /* we want to count every time cell p references v, so we see how many times it comes up in the closure. This 15400a96aa3bSJed Brown * only protects against periodicity problems */ 15419566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 154263a3b9bcSJacob 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); 15430a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 15440a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 15450a96aa3bSJed Brown 15461dca8a05SBarry Smith PetscCheck(cellVert >= vStart && cellVert < vEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure: vertices"); 154748a46eb9SPierre Jolivet if (cellVert == v) PetscCall(PetscSectionAddDof(ctt, v, 1)); 15480a96aa3bSJed Brown } 15499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 15500a96aa3bSJed Brown } 15510a96aa3bSJed Brown } 15529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 15530a96aa3bSJed Brown } 15549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ctt)); 15559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ctt, &cttSize)); 15569566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cttSize, &numCtt)); 15570a96aa3bSJed Brown #if defined(P4_TO_P8) 15589566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, P4EST_DIM - 1, &eStart, &eEnd)); 15599566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(eEnd - eStart, &numEdges)); 15609566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &ett)); 15619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ett, eStart, eEnd)); 15620a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 15630a96aa3bSJed Brown PetscInt s; 15640a96aa3bSJed Brown 15659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 15660a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 15670a96aa3bSJed Brown PetscInt p = star[2 * s]; 15680a96aa3bSJed Brown 15690a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 15700a96aa3bSJed Brown /* we want to count every time cell p references e, so we see how many times it comes up in the closure. This 15710a96aa3bSJed Brown * only protects against periodicity problems */ 15729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 157308401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell with wrong closure size"); 15740a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 15750a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 15760a96aa3bSJed Brown 15771dca8a05SBarry Smith PetscCheck(cellEdge >= eStart && cellEdge < eEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure: edges"); 157848a46eb9SPierre Jolivet if (cellEdge == e) PetscCall(PetscSectionAddDof(ett, e, 1)); 15790a96aa3bSJed Brown } 15809566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 15810a96aa3bSJed Brown } 15820a96aa3bSJed Brown } 15839566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 15840a96aa3bSJed Brown } 15859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ett)); 15869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ett, &ettSize)); 15879566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(ettSize, &numEtt)); 15880a96aa3bSJed Brown 15890a96aa3bSJed Brown /* This routine allocates space for the arrays, which we fill below */ 1590792fecdfSBarry Smith PetscCallP4estReturn(conn, p8est_connectivity_new, (numVerts, numTrees, numEdges, numEtt, numCorns, numCtt)); 15910a96aa3bSJed Brown #else 1592792fecdfSBarry Smith PetscCallP4estReturn(conn, p4est_connectivity_new, (numVerts, numTrees, numCorns, numCtt)); 15930a96aa3bSJed Brown #endif 15940a96aa3bSJed Brown 15950a96aa3bSJed Brown /* 2: visit every face, determine neighboring cells(trees) */ 15969566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 1, &fStart, &fEnd)); 15979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * P4EST_FACES, &ttf)); 15980a96aa3bSJed Brown for (f = fStart; f < fEnd; f++) { 15990a96aa3bSJed Brown PetscInt numSupp, s; 16000a96aa3bSJed Brown PetscInt myFace[2] = {-1, -1}; 16010a96aa3bSJed Brown PetscInt myOrnt[2] = {PETSC_MIN_INT, PETSC_MIN_INT}; 16020a96aa3bSJed Brown const PetscInt *supp; 16030a96aa3bSJed Brown 16049566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &numSupp)); 16051dca8a05SBarry 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); 16069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &supp)); 16070a96aa3bSJed Brown 16080a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16090a96aa3bSJed Brown PetscInt p = supp[s]; 16100a96aa3bSJed Brown 16110a96aa3bSJed Brown if (p >= cEnd) { 16120a96aa3bSJed Brown numSupp--; 16130a96aa3bSJed Brown if (s) supp = &supp[1 - s]; 16140a96aa3bSJed Brown break; 16150a96aa3bSJed Brown } 16160a96aa3bSJed Brown } 16170a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16180a96aa3bSJed Brown PetscInt p = supp[s], i; 16190a96aa3bSJed Brown PetscInt numCone; 16200a96aa3bSJed Brown DMPolytopeType ct; 16210a96aa3bSJed Brown const PetscInt *cone; 16220a96aa3bSJed Brown const PetscInt *ornt; 16230a96aa3bSJed Brown PetscInt orient = PETSC_MIN_INT; 16240a96aa3bSJed Brown 16259566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &numCone)); 162663a3b9bcSJacob 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); 16279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 16289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[0], &ct)); 16299566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 16300a96aa3bSJed Brown for (i = 0; i < P4EST_FACES; i++) { 16310a96aa3bSJed Brown if (cone[i] == f) { 16320a96aa3bSJed Brown orient = DMPolytopeConvertNewOrientation_Internal(ct, ornt[i]); 16330a96aa3bSJed Brown break; 16340a96aa3bSJed Brown } 16350a96aa3bSJed Brown } 163663a3b9bcSJacob Faibussowitsch PetscCheck(i < P4EST_FACES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "cell %" PetscInt_FMT " faced %" PetscInt_FMT " mismatch", p, f); 16370a96aa3bSJed Brown if (p < cStart || p >= cEnd) { 16380a96aa3bSJed Brown DMPolytopeType ct; 16399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 164063a3b9bcSJacob 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); 16410a96aa3bSJed Brown } 16420a96aa3bSJed Brown ttf[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = f - fStart; 16430a96aa3bSJed Brown if (numSupp == 1) { 16440a96aa3bSJed Brown /* boundary faces indicated by self reference */ 16450a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = p - cStart; 16460a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = (int8_t)PetscFaceToP4estFace[i]; 16470a96aa3bSJed Brown } else { 16480a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16490a96aa3bSJed Brown 16500a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = supp[1 - s] - cStart; 16510a96aa3bSJed Brown myFace[s] = PetscFaceToP4estFace[i]; 16520a96aa3bSJed Brown /* get the orientation of cell p in p4est-type closure to facet f, by composing the p4est-closure to 16530a96aa3bSJed Brown * petsc-closure permutation and the petsc-closure to facet orientation */ 16540a96aa3bSJed Brown myOrnt[s] = DihedralCompose(N, orient, DMPolytopeConvertNewOrientation_Internal(ct, P4estFaceToPetscOrnt[myFace[s]])); 16550a96aa3bSJed Brown } 16560a96aa3bSJed Brown } 16570a96aa3bSJed Brown if (numSupp == 2) { 16580a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16590a96aa3bSJed Brown PetscInt p = supp[s]; 16600a96aa3bSJed Brown PetscInt orntAtoB; 16610a96aa3bSJed Brown PetscInt p4estOrient; 16620a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16630a96aa3bSJed Brown 16640a96aa3bSJed Brown /* composing the forward permutation with the other cell's inverse permutation gives the self-to-neighbor 16650a96aa3bSJed Brown * permutation of this cell-facet's cone */ 16660a96aa3bSJed Brown orntAtoB = DihedralCompose(N, DihedralInvert(N, myOrnt[1 - s]), myOrnt[s]); 16670a96aa3bSJed Brown 16680a96aa3bSJed Brown /* convert cone-description permutation (i.e., edges around facet) to cap-description permutation (i.e., 16690a96aa3bSJed Brown * vertices around facet) */ 16700a96aa3bSJed Brown #if !defined(P4_TO_P8) 16710a96aa3bSJed Brown p4estOrient = orntAtoB < 0 ? -(orntAtoB + 1) : orntAtoB; 16720a96aa3bSJed Brown #else 16730a96aa3bSJed Brown { 16740a96aa3bSJed Brown PetscInt firstVert = orntAtoB < 0 ? ((-orntAtoB) % N) : orntAtoB; 16750a96aa3bSJed Brown PetscInt p4estFirstVert = firstVert < 2 ? firstVert : (firstVert ^ 1); 16760a96aa3bSJed Brown 16770a96aa3bSJed Brown /* swap bits */ 16780a96aa3bSJed Brown p4estOrient = ((myFace[s] <= myFace[1 - s]) || (orntAtoB < 0)) ? p4estFirstVert : ((p4estFirstVert >> 1) | ((p4estFirstVert & 1) << 1)); 16790a96aa3bSJed Brown } 16800a96aa3bSJed Brown #endif 16810a96aa3bSJed Brown /* encode neighbor face and orientation in tree_to_face per p4est_connectivity standard (see 16820a96aa3bSJed Brown * p4est_connectivity.h, p8est_connectivity.h) */ 16830a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + myFace[s]] = (int8_t)myFace[1 - s] + p4estOrient * P4EST_FACES; 16840a96aa3bSJed Brown } 16850a96aa3bSJed Brown } 16860a96aa3bSJed Brown } 16870a96aa3bSJed Brown 16880a96aa3bSJed Brown #if defined(P4_TO_P8) 16890a96aa3bSJed Brown /* 3: visit every edge */ 16900a96aa3bSJed Brown conn->ett_offset[0] = 0; 16910a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 16920a96aa3bSJed Brown PetscInt off, s; 16930a96aa3bSJed Brown 16949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ett, e, &off)); 16950a96aa3bSJed Brown conn->ett_offset[e - eStart] = (p4est_topidx_t)off; 16969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 16970a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 16980a96aa3bSJed Brown PetscInt p = star[2 * s]; 16990a96aa3bSJed Brown 17000a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 17019566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 170208401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure"); 17030a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 17040a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 17050a96aa3bSJed Brown PetscInt cellOrnt = closure[2 * (c + edgeOff) + 1]; 17060a96aa3bSJed Brown DMPolytopeType ct; 17070a96aa3bSJed Brown 17089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cellEdge, &ct)); 17090a96aa3bSJed Brown cellOrnt = DMPolytopeConvertNewOrientation_Internal(ct, cellOrnt); 17100a96aa3bSJed Brown if (cellEdge == e) { 17110a96aa3bSJed Brown PetscInt p4estEdge = PetscEdgeToP4estEdge[c]; 17120a96aa3bSJed Brown PetscInt totalOrient; 17130a96aa3bSJed Brown 17140a96aa3bSJed Brown /* compose p4est-closure to petsc-closure permutation and petsc-closure to edge orientation */ 17150a96aa3bSJed Brown totalOrient = DihedralCompose(2, cellOrnt, DMPolytopeConvertNewOrientation_Internal(DM_POLYTOPE_SEGMENT, P4estEdgeToPetscOrnt[p4estEdge])); 17160a96aa3bSJed Brown /* p4est orientations are positive: -2 => 1, -1 => 0 */ 17170a96aa3bSJed Brown totalOrient = (totalOrient < 0) ? -(totalOrient + 1) : totalOrient; 17180a96aa3bSJed Brown conn->edge_to_tree[off] = (p4est_locidx_t)(p - cStart); 1719d5b43468SJose E. Roman /* encode cell-edge and orientation in edge_to_edge per p8est_connectivity standard (see 17200a96aa3bSJed Brown * p8est_connectivity.h) */ 17210a96aa3bSJed Brown conn->edge_to_edge[off++] = (int8_t)p4estEdge + P8EST_EDGES * totalOrient; 17220a96aa3bSJed Brown conn->tree_to_edge[P8EST_EDGES * (p - cStart) + p4estEdge] = e - eStart; 17230a96aa3bSJed Brown } 17240a96aa3bSJed Brown } 17259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 17260a96aa3bSJed Brown } 17270a96aa3bSJed Brown } 17289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 17290a96aa3bSJed Brown } 17309566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ett)); 17310a96aa3bSJed Brown #endif 17320a96aa3bSJed Brown 17330a96aa3bSJed Brown /* 4: visit every vertex */ 17340a96aa3bSJed Brown conn->ctt_offset[0] = 0; 17350a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 17360a96aa3bSJed Brown PetscInt off, s; 17370a96aa3bSJed Brown 17389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ctt, v, &off)); 17390a96aa3bSJed Brown conn->ctt_offset[v - vStart] = (p4est_topidx_t)off; 17409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 17410a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 17420a96aa3bSJed Brown PetscInt p = star[2 * s]; 17430a96aa3bSJed Brown 17440a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 17459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 174608401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure"); 17470a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 17480a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 17490a96aa3bSJed Brown 17500a96aa3bSJed Brown if (cellVert == v) { 17510a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[c]; 17520a96aa3bSJed Brown 17530a96aa3bSJed Brown conn->corner_to_tree[off] = (p4est_locidx_t)(p - cStart); 17540a96aa3bSJed Brown conn->corner_to_corner[off++] = (int8_t)p4estVert; 17550a96aa3bSJed Brown conn->tree_to_corner[P4EST_CHILDREN * (p - cStart) + p4estVert] = v - vStart; 17560a96aa3bSJed Brown } 17570a96aa3bSJed Brown } 17589566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 17590a96aa3bSJed Brown } 17600a96aa3bSJed Brown } 17619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 17620a96aa3bSJed Brown } 17639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ctt)); 17640a96aa3bSJed Brown 17650a96aa3bSJed Brown /* 5: Compute the coordinates */ 17660a96aa3bSJed Brown { 17670a96aa3bSJed Brown PetscInt coordDim; 17680a96aa3bSJed Brown 17699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim)); 17706858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 17710a96aa3bSJed Brown for (c = cStart; c < cEnd; c++) { 17720a96aa3bSJed Brown PetscInt dof; 17736858538eSMatthew G. Knepley PetscBool isDG; 17740a96aa3bSJed Brown PetscScalar *cellCoords = NULL; 17756858538eSMatthew G. Knepley const PetscScalar *array; 17760a96aa3bSJed Brown 17776858538eSMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 17786858538eSMatthew 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); 17790a96aa3bSJed Brown for (v = 0; v < P4EST_CHILDREN; v++) { 17800a96aa3bSJed Brown PetscInt i, lim = PetscMin(3, coordDim); 17810a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[v]; 17820a96aa3bSJed Brown 17830a96aa3bSJed Brown conn->tree_to_vertex[P4EST_CHILDREN * (c - cStart) + v] = P4EST_CHILDREN * (c - cStart) + v; 17840a96aa3bSJed Brown /* p4est vertices are always embedded in R^3 */ 17850a96aa3bSJed Brown for (i = 0; i < 3; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = 0.; 17860a96aa3bSJed Brown for (i = 0; i < lim; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = PetscRealPart(cellCoords[v * coordDim + i]); 17870a96aa3bSJed Brown } 17886858538eSMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 17890a96aa3bSJed Brown } 17900a96aa3bSJed Brown } 17910a96aa3bSJed Brown 17920a96aa3bSJed Brown #if defined(P4EST_ENABLE_DEBUG) 179308401ef6SPierre Jolivet PetscCheck(p4est_connectivity_is_valid(conn), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Plex to p4est conversion failed"); 17940a96aa3bSJed Brown #endif 17950a96aa3bSJed Brown 17960a96aa3bSJed Brown *connOut = conn; 17970a96aa3bSJed Brown 17980a96aa3bSJed Brown *tree_face_to_uniq = ttf; 17990a96aa3bSJed Brown 18003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18010a96aa3bSJed Brown } 18020a96aa3bSJed Brown 1803d71ae5a4SJacob Faibussowitsch static PetscErrorCode locidx_to_PetscInt(sc_array_t *array) 1804d71ae5a4SJacob Faibussowitsch { 18050a96aa3bSJed Brown sc_array_t *newarray; 18060a96aa3bSJed Brown size_t zz, count = array->elem_count; 18070a96aa3bSJed Brown 18080a96aa3bSJed Brown PetscFunctionBegin; 180908401ef6SPierre Jolivet PetscCheck(array->elem_size == sizeof(p4est_locidx_t), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong locidx size"); 18100a96aa3bSJed Brown 18113ba16761SJacob Faibussowitsch if (sizeof(p4est_locidx_t) == sizeof(PetscInt)) PetscFunctionReturn(PETSC_SUCCESS); 18120a96aa3bSJed Brown 18130a96aa3bSJed Brown newarray = sc_array_new_size(sizeof(PetscInt), array->elem_count); 18140a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18150a96aa3bSJed Brown p4est_locidx_t il = *((p4est_locidx_t *)sc_array_index(array, zz)); 18160a96aa3bSJed Brown PetscInt *ip = (PetscInt *)sc_array_index(newarray, zz); 18170a96aa3bSJed Brown 18180a96aa3bSJed Brown *ip = (PetscInt)il; 18190a96aa3bSJed Brown } 18200a96aa3bSJed Brown 18210a96aa3bSJed Brown sc_array_reset(array); 18220a96aa3bSJed Brown sc_array_init_size(array, sizeof(PetscInt), count); 18230a96aa3bSJed Brown sc_array_copy(array, newarray); 18240a96aa3bSJed Brown sc_array_destroy(newarray); 18253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18260a96aa3bSJed Brown } 18270a96aa3bSJed Brown 1828d71ae5a4SJacob Faibussowitsch static PetscErrorCode coords_double_to_PetscScalar(sc_array_t *array, PetscInt dim) 1829d71ae5a4SJacob Faibussowitsch { 18300a96aa3bSJed Brown sc_array_t *newarray; 18310a96aa3bSJed Brown size_t zz, count = array->elem_count; 18320a96aa3bSJed Brown 18330a96aa3bSJed Brown PetscFunctionBegin; 18341dca8a05SBarry Smith PetscCheck(array->elem_size == 3 * sizeof(double), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong coordinate size"); 18350a96aa3bSJed Brown #if !defined(PETSC_USE_COMPLEX) 18363ba16761SJacob Faibussowitsch if (sizeof(double) == sizeof(PetscScalar) && dim == 3) PetscFunctionReturn(PETSC_SUCCESS); 18370a96aa3bSJed Brown #endif 18380a96aa3bSJed Brown 18390a96aa3bSJed Brown newarray = sc_array_new_size(dim * sizeof(PetscScalar), array->elem_count); 18400a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18410a96aa3bSJed Brown int i; 18420a96aa3bSJed Brown double *id = (double *)sc_array_index(array, zz); 18430a96aa3bSJed Brown PetscScalar *ip = (PetscScalar *)sc_array_index(newarray, zz); 18440a96aa3bSJed Brown 18450a96aa3bSJed Brown for (i = 0; i < dim; i++) ip[i] = 0.; 18460a96aa3bSJed Brown for (i = 0; i < PetscMin(dim, 3); i++) ip[i] = (PetscScalar)id[i]; 18470a96aa3bSJed Brown } 18480a96aa3bSJed Brown 18490a96aa3bSJed Brown sc_array_reset(array); 18500a96aa3bSJed Brown sc_array_init_size(array, dim * sizeof(PetscScalar), count); 18510a96aa3bSJed Brown sc_array_copy(array, newarray); 18520a96aa3bSJed Brown sc_array_destroy(newarray); 18533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18540a96aa3bSJed Brown } 18550a96aa3bSJed Brown 1856d71ae5a4SJacob Faibussowitsch static PetscErrorCode locidx_pair_to_PetscSFNode(sc_array_t *array) 1857d71ae5a4SJacob Faibussowitsch { 18580a96aa3bSJed Brown sc_array_t *newarray; 18590a96aa3bSJed Brown size_t zz, count = array->elem_count; 18600a96aa3bSJed Brown 18610a96aa3bSJed Brown PetscFunctionBegin; 18621dca8a05SBarry Smith PetscCheck(array->elem_size == 2 * sizeof(p4est_locidx_t), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong locidx size"); 18630a96aa3bSJed Brown 18640a96aa3bSJed Brown newarray = sc_array_new_size(sizeof(PetscSFNode), array->elem_count); 18650a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18660a96aa3bSJed Brown p4est_locidx_t *il = (p4est_locidx_t *)sc_array_index(array, zz); 18670a96aa3bSJed Brown PetscSFNode *ip = (PetscSFNode *)sc_array_index(newarray, zz); 18680a96aa3bSJed Brown 18690a96aa3bSJed Brown ip->rank = (PetscInt)il[0]; 18700a96aa3bSJed Brown ip->index = (PetscInt)il[1]; 18710a96aa3bSJed Brown } 18720a96aa3bSJed Brown 18730a96aa3bSJed Brown sc_array_reset(array); 18740a96aa3bSJed Brown sc_array_init_size(array, sizeof(PetscSFNode), count); 18750a96aa3bSJed Brown sc_array_copy(array, newarray); 18760a96aa3bSJed Brown sc_array_destroy(newarray); 18773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18780a96aa3bSJed Brown } 18790a96aa3bSJed Brown 1880d71ae5a4SJacob Faibussowitsch static PetscErrorCode P4estToPlex_Local(p4est_t *p4est, DM *plex) 1881d71ae5a4SJacob Faibussowitsch { 18820a96aa3bSJed Brown PetscFunctionBegin; 18830a96aa3bSJed Brown { 18840a96aa3bSJed Brown sc_array_t *points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 18850a96aa3bSJed Brown sc_array_t *cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 18860a96aa3bSJed Brown sc_array_t *cones = sc_array_new(sizeof(p4est_locidx_t)); 18870a96aa3bSJed Brown sc_array_t *cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 18880a96aa3bSJed Brown sc_array_t *coords = sc_array_new(3 * sizeof(double)); 18890a96aa3bSJed Brown sc_array_t *children = sc_array_new(sizeof(p4est_locidx_t)); 18900a96aa3bSJed Brown sc_array_t *parents = sc_array_new(sizeof(p4est_locidx_t)); 18910a96aa3bSJed Brown sc_array_t *childids = sc_array_new(sizeof(p4est_locidx_t)); 18920a96aa3bSJed Brown sc_array_t *leaves = sc_array_new(sizeof(p4est_locidx_t)); 18930a96aa3bSJed Brown sc_array_t *remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 18940a96aa3bSJed Brown p4est_locidx_t first_local_quad; 18950a96aa3bSJed Brown 1896792fecdfSBarry 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)); 18970a96aa3bSJed Brown 18989566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 18999566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 19009566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 19019566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 19029566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, P4EST_DIM)); 19030a96aa3bSJed Brown 19049566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PETSC_COMM_SELF, plex)); 19059566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*plex, P4EST_DIM)); 19069566063dSJacob 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)); 19079566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(*plex)); 19080a96aa3bSJed Brown sc_array_destroy(points_per_dim); 19090a96aa3bSJed Brown sc_array_destroy(cone_sizes); 19100a96aa3bSJed Brown sc_array_destroy(cones); 19110a96aa3bSJed Brown sc_array_destroy(cone_orientations); 19120a96aa3bSJed Brown sc_array_destroy(coords); 19130a96aa3bSJed Brown sc_array_destroy(children); 19140a96aa3bSJed Brown sc_array_destroy(parents); 19150a96aa3bSJed Brown sc_array_destroy(childids); 19160a96aa3bSJed Brown sc_array_destroy(leaves); 19170a96aa3bSJed Brown sc_array_destroy(remotes); 19180a96aa3bSJed Brown } 19193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19200a96aa3bSJed Brown } 19210a96aa3bSJed Brown 19220a96aa3bSJed Brown #define DMReferenceTreeGetChildSymmetry_pforest _append_pforest(DMReferenceTreeGetChildSymmetry) 1923d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMReferenceTreeGetChildSymmetry_pforest(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 1924d71ae5a4SJacob Faibussowitsch { 19250a96aa3bSJed Brown PetscInt coneSize, dStart, dEnd, vStart, vEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 19260a96aa3bSJed Brown 19270a96aa3bSJed Brown PetscFunctionBegin; 19280a96aa3bSJed Brown if (parentOrientA == parentOrientB) { 19290a96aa3bSJed Brown if (childOrientB) *childOrientB = childOrientA; 19300a96aa3bSJed Brown if (childB) *childB = childA; 19313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19320a96aa3bSJed Brown } 19339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 19346aad120cSJose E. Roman if (childA >= vStart && childA < vEnd) { /* vertices (always in the middle) are invariant under rotation */ 19350a96aa3bSJed Brown if (childOrientB) *childOrientB = 0; 19360a96aa3bSJed Brown if (childB) *childB = childA; 19373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19380a96aa3bSJed Brown } 19390a96aa3bSJed Brown for (dim = 0; dim < 3; dim++) { 19409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, &dStart, &dEnd)); 19410a96aa3bSJed Brown if (parent >= dStart && parent <= dEnd) break; 19420a96aa3bSJed Brown } 194363a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot perform child symmetry for %" PetscInt_FMT "-cells", dim); 194428b400f6SJacob Faibussowitsch PetscCheck(dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "A vertex has no children"); 19450a96aa3bSJed Brown if (childA < dStart || childA >= dEnd) { /* a 1-cell in a 2-cell */ 19460a96aa3bSJed Brown /* this is a lower-dimensional child: bootstrap */ 19470a96aa3bSJed Brown PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 19480a96aa3bSJed Brown const PetscInt *supp, *coneA, *coneB, *oA, *oB; 19490a96aa3bSJed Brown 19509566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, childA, &size)); 19519566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, childA, &supp)); 19520a96aa3bSJed Brown 19530a96aa3bSJed Brown /* find a point sA in supp(childA) that has the same parent */ 19540a96aa3bSJed Brown for (i = 0; i < size; i++) { 19550a96aa3bSJed Brown PetscInt sParent; 19560a96aa3bSJed Brown 19570a96aa3bSJed Brown sA = supp[i]; 19580a96aa3bSJed Brown if (sA == parent) continue; 19599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, sA, &sParent, NULL)); 19600a96aa3bSJed Brown if (sParent == parent) break; 19610a96aa3bSJed Brown } 196208401ef6SPierre Jolivet PetscCheck(i != size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "could not find support in children"); 19630a96aa3bSJed Brown /* find out which point sB is in an equivalent position to sA under 19640a96aa3bSJed Brown * parentOrientB */ 19659566063dSJacob Faibussowitsch PetscCall(DMReferenceTreeGetChildSymmetry_pforest(dm, parent, parentOrientA, 0, sA, parentOrientB, &sOrientB, &sB)); 19669566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, sA, &sConeSize)); 19679566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sA, &coneA)); 19689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sB, &coneB)); 19699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sA, &oA)); 19709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sB, &oB)); 19710a96aa3bSJed Brown /* step through the cone of sA in natural order */ 19720a96aa3bSJed Brown for (i = 0; i < sConeSize; i++) { 19730a96aa3bSJed Brown if (coneA[i] == childA) { 19740a96aa3bSJed Brown /* if childA is at position i in coneA, 19750a96aa3bSJed Brown * then we want the point that is at sOrientB*i in coneB */ 19760a96aa3bSJed Brown PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize - (sOrientB + 1) - i) % sConeSize); 19770a96aa3bSJed Brown if (childB) *childB = coneB[j]; 19780a96aa3bSJed Brown if (childOrientB) { 19790a96aa3bSJed Brown DMPolytopeType ct; 19800a96aa3bSJed Brown PetscInt oBtrue; 19810a96aa3bSJed Brown 19829566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, childA, &coneSize)); 19830a96aa3bSJed Brown /* compose sOrientB and oB[j] */ 19841dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected a vertex or an edge"); 19850a96aa3bSJed Brown ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 19860a96aa3bSJed Brown /* we may have to flip an edge */ 19870a96aa3bSJed Brown oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientationInv(ct, -1, oB[j]); 19880a96aa3bSJed Brown oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 19890a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, DMPolytopeConvertNewOrientation_Internal(ct, oA[i]), oBtrue); 19900a96aa3bSJed Brown *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 19910a96aa3bSJed Brown } 19920a96aa3bSJed Brown break; 19930a96aa3bSJed Brown } 19940a96aa3bSJed Brown } 199508401ef6SPierre Jolivet PetscCheck(i != sConeSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "support cone mismatch"); 19963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19970a96aa3bSJed Brown } 19980a96aa3bSJed Brown /* get the cone size and symmetry swap */ 19999566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 20000a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 20010a96aa3bSJed Brown if (dim == 2) { 20020a96aa3bSJed Brown /* orientations refer to cones: we want them to refer to vertices: 20030a96aa3bSJed Brown * if it's a rotation, they are the same, but if the order is reversed, a 20040a96aa3bSJed Brown * permutation that puts side i first does *not* put vertex i first */ 20050a96aa3bSJed Brown oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 20060a96aa3bSJed Brown oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 20070a96aa3bSJed Brown ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 20080a96aa3bSJed Brown } else { 20090a96aa3bSJed Brown oAvert = parentOrientA; 20100a96aa3bSJed Brown oBvert = parentOrientB; 20110a96aa3bSJed Brown ABswapVert = ABswap; 20120a96aa3bSJed Brown } 20130a96aa3bSJed Brown if (childB) { 20140a96aa3bSJed Brown /* assume that each child corresponds to a vertex, in the same order */ 20150a96aa3bSJed Brown PetscInt p, posA = -1, numChildren, i; 20160a96aa3bSJed Brown const PetscInt *children; 20170a96aa3bSJed Brown 20180a96aa3bSJed Brown /* count which position the child is in */ 20199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, parent, &numChildren, &children)); 20200a96aa3bSJed Brown for (i = 0; i < numChildren; i++) { 20210a96aa3bSJed Brown p = children[i]; 20220a96aa3bSJed Brown if (p == childA) { 20230a96aa3bSJed Brown if (dim == 1) { 20240a96aa3bSJed Brown posA = i; 20250a96aa3bSJed Brown } else { /* 2D Morton to rotation */ 20260a96aa3bSJed Brown posA = (i & 2) ? (i ^ 1) : i; 20270a96aa3bSJed Brown } 20280a96aa3bSJed Brown break; 20290a96aa3bSJed Brown } 20300a96aa3bSJed Brown } 20310a96aa3bSJed Brown if (posA >= coneSize) { 20320a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find childA in children of parent"); 20330a96aa3bSJed Brown } else { 20340a96aa3bSJed Brown /* figure out position B by applying ABswapVert */ 20350a96aa3bSJed Brown PetscInt posB, childIdB; 20360a96aa3bSJed Brown 20370a96aa3bSJed Brown posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize - (ABswapVert + 1) - posA) % coneSize); 20380a96aa3bSJed Brown if (dim == 1) { 20390a96aa3bSJed Brown childIdB = posB; 20400a96aa3bSJed Brown } else { /* 2D rotation to Morton */ 20410a96aa3bSJed Brown childIdB = (posB & 2) ? (posB ^ 1) : posB; 20420a96aa3bSJed Brown } 20430a96aa3bSJed Brown if (childB) *childB = children[childIdB]; 20440a96aa3bSJed Brown } 20450a96aa3bSJed Brown } 20460a96aa3bSJed Brown if (childOrientB) *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 20473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20480a96aa3bSJed Brown } 20490a96aa3bSJed Brown 20500a96aa3bSJed Brown #define DMCreateReferenceTree_pforest _append_pforest(DMCreateReferenceTree) 2051d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateReferenceTree_pforest(MPI_Comm comm, DM *dm) 2052d71ae5a4SJacob Faibussowitsch { 20530a96aa3bSJed Brown p4est_connectivity_t *refcube; 20540a96aa3bSJed Brown p4est_t *root, *refined; 20550a96aa3bSJed Brown DM dmRoot, dmRefined; 20560a96aa3bSJed Brown DM_Plex *mesh; 20570a96aa3bSJed Brown PetscMPIInt rank; 205866c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI) 205966c0a4b5SToby Isaac sc_MPI_Comm comm_self = sc_MPI_COMM_SELF; 206066c0a4b5SToby Isaac #else 206166c0a4b5SToby Isaac MPI_Comm comm_self = PETSC_COMM_SELF; 206266c0a4b5SToby Isaac #endif 20630a96aa3bSJed Brown 20640a96aa3bSJed Brown PetscFunctionBegin; 2065792fecdfSBarry Smith PetscCallP4estReturn(refcube, p4est_connectivity_new_byname, ("unit")); 20660a96aa3bSJed Brown { /* [-1,1]^d geometry */ 20670a96aa3bSJed Brown PetscInt i, j; 20680a96aa3bSJed Brown 20690a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 20700a96aa3bSJed Brown for (j = 0; j < 3; j++) { 20710a96aa3bSJed Brown refcube->vertices[3 * i + j] *= 2.; 20720a96aa3bSJed Brown refcube->vertices[3 * i + j] -= 1.; 20730a96aa3bSJed Brown } 20740a96aa3bSJed Brown } 20750a96aa3bSJed Brown } 2076792fecdfSBarry Smith PetscCallP4estReturn(root, p4est_new, (comm_self, refcube, 0, NULL, NULL)); 2077792fecdfSBarry Smith PetscCallP4estReturn(refined, p4est_new_ext, (comm_self, refcube, 0, 1, 1, 0, NULL, NULL)); 20789566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(root, &dmRoot)); 20799566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(refined, &dmRefined)); 20800a96aa3bSJed Brown { 20810a96aa3bSJed Brown #if !defined(P4_TO_P8) 20820a96aa3bSJed Brown PetscInt nPoints = 25; 20839371c9d4SSatish 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}; 20849371c9d4SSatish 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}; 20850a96aa3bSJed Brown #else 20860a96aa3bSJed Brown PetscInt nPoints = 125; 20879371c9d4SSatish 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, 20889371c9d4SSatish 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, 20899371c9d4SSatish 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}; 20909371c9d4SSatish 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, 20919371c9d4SSatish 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}; 20920a96aa3bSJed Brown 20930a96aa3bSJed Brown #endif 20940a96aa3bSJed Brown IS permIS; 20950a96aa3bSJed Brown DM dmPerm; 20960a96aa3bSJed Brown 20979566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nPoints, perm, PETSC_USE_POINTER, &permIS)); 20989566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dmRefined, permIS, &dmPerm)); 20990a96aa3bSJed Brown if (dmPerm) { 21009566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 21010a96aa3bSJed Brown dmRefined = dmPerm; 21020a96aa3bSJed Brown } 21039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 21040a96aa3bSJed Brown { 21050a96aa3bSJed Brown PetscInt p; 21069566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRoot, "identity")); 21079566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRefined, "identity")); 210848a46eb9SPierre Jolivet for (p = 0; p < P4EST_INSUL; p++) PetscCall(DMSetLabelValue(dmRoot, "identity", p, p)); 210948a46eb9SPierre Jolivet for (p = 0; p < nPoints; p++) PetscCall(DMSetLabelValue(dmRefined, "identity", p, ident[p])); 21100a96aa3bSJed Brown } 21110a96aa3bSJed Brown } 21129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(dmRoot, dmRefined, "identity", dm)); 21130a96aa3bSJed Brown mesh = (DM_Plex *)(*dm)->data; 21140a96aa3bSJed Brown mesh->getchildsymmetry = DMReferenceTreeGetChildSymmetry_pforest; 21159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 21160a96aa3bSJed Brown if (rank == 0) { 21179566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRoot, NULL, "-dm_p4est_ref_root_view")); 21189566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined, NULL, "-dm_p4est_ref_refined_view")); 21199566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined, NULL, "-dm_p4est_ref_tree_view")); 21200a96aa3bSJed Brown } 21219566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 21229566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRoot)); 2123792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (refined)); 2124792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (root)); 2125792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy, (refcube)); 21263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21270a96aa3bSJed Brown } 21280a96aa3bSJed Brown 2129d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMShareDiscretization(DM dmA, DM dmB) 2130d71ae5a4SJacob Faibussowitsch { 21310a96aa3bSJed Brown void *ctx; 21320a96aa3bSJed Brown PetscInt num; 21330a96aa3bSJed Brown PetscReal val; 21340a96aa3bSJed Brown 21350a96aa3bSJed Brown PetscFunctionBegin; 21369566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmA, &ctx)); 21379566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(dmB, ctx)); 21389566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmA, dmB)); 21399566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dmA, &num, &val)); 21409566063dSJacob Faibussowitsch PetscCall(DMSetOutputSequenceNumber(dmB, num, val)); 21410a96aa3bSJed Brown if (dmB->localSection != dmA->localSection || dmB->globalSection != dmA->globalSection) { 21429566063dSJacob Faibussowitsch PetscCall(DMClearLocalVectors(dmB)); 21439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->localSection)); 21449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->localSection))); 21450a96aa3bSJed Brown dmB->localSection = dmA->localSection; 21469566063dSJacob Faibussowitsch PetscCall(DMClearGlobalVectors(dmB)); 21479566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->globalSection)); 21489566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->globalSection))); 21490a96aa3bSJed Brown dmB->globalSection = dmA->globalSection; 21509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.section)); 21519566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->defaultConstraint.section))); 21523b8ba7d1SJed Brown dmB->defaultConstraint.section = dmA->defaultConstraint.section; 21539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.mat)); 21549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(dmB->defaultConstraint.mat))); 21553b8ba7d1SJed Brown dmB->defaultConstraint.mat = dmA->defaultConstraint.mat; 21569566063dSJacob Faibussowitsch if (dmA->map) PetscCall(PetscLayoutReference(dmA->map, &dmB->map)); 21570a96aa3bSJed Brown } 21580a96aa3bSJed Brown if (dmB->sectionSF != dmA->sectionSF) { 21599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->sectionSF)); 21609566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&dmB->sectionSF)); 21610a96aa3bSJed Brown dmB->sectionSF = dmA->sectionSF; 21620a96aa3bSJed Brown } 21633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21640a96aa3bSJed Brown } 21650a96aa3bSJed Brown 21660a96aa3bSJed Brown /* Get an SF that broadcasts a coarse-cell covering of the local fine cells */ 2167d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetCellCoveringSF(MPI_Comm comm, p4est_t *p4estC, p4est_t *p4estF, PetscInt cStart, PetscInt cEnd, PetscSF *coveringSF) 2168d71ae5a4SJacob Faibussowitsch { 21690a96aa3bSJed Brown PetscInt startF, endF, startC, endC, p, nLeaves; 21700a96aa3bSJed Brown PetscSFNode *leaves; 21710a96aa3bSJed Brown PetscSF sf; 21720a96aa3bSJed Brown PetscInt *recv, *send; 21730a96aa3bSJed Brown PetscMPIInt tag; 21740a96aa3bSJed Brown MPI_Request *recvReqs, *sendReqs; 21750a96aa3bSJed Brown PetscSection section; 21760a96aa3bSJed Brown 21770a96aa3bSJed Brown PetscFunctionBegin; 21789566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize, p4estC->mpirank, p4estF, p4estC, &startC, &endC)); 21799566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2 * (endC - startC), &recv, endC - startC, &recvReqs)); 21809566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(comm, &tag)); 21810a96aa3bSJed Brown for (p = startC; p < endC; p++) { 21820a96aa3bSJed Brown recvReqs[p - startC] = MPI_REQUEST_NULL; /* just in case we don't initiate a receive */ 21830a96aa3bSJed Brown if (p4estC->global_first_quadrant[p] == p4estC->global_first_quadrant[p + 1]) { /* empty coarse partition */ 21840a96aa3bSJed Brown recv[2 * (p - startC)] = 0; 21850a96aa3bSJed Brown recv[2 * (p - startC) + 1] = 0; 21860a96aa3bSJed Brown continue; 21870a96aa3bSJed Brown } 21880a96aa3bSJed Brown 21899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(&recv[2 * (p - startC)], 2, MPIU_INT, p, tag, comm, &recvReqs[p - startC])); 21900a96aa3bSJed Brown } 21919566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize, p4estC->mpirank, p4estC, p4estF, &startF, &endF)); 21929566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2 * (endF - startF), &send, endF - startF, &sendReqs)); 21930a96aa3bSJed Brown /* count the quadrants rank will send to each of [startF,endF) */ 21940a96aa3bSJed Brown for (p = startF; p < endF; p++) { 21950a96aa3bSJed Brown p4est_quadrant_t *myFineStart = &p4estF->global_first_position[p]; 21960a96aa3bSJed Brown p4est_quadrant_t *myFineEnd = &p4estF->global_first_position[p + 1]; 21970a96aa3bSJed Brown PetscInt tStart = (PetscInt)myFineStart->p.which_tree; 21980a96aa3bSJed Brown PetscInt tEnd = (PetscInt)myFineEnd->p.which_tree; 21990a96aa3bSJed Brown PetscInt firstCell = -1, lastCell = -1; 22000a96aa3bSJed Brown p4est_tree_t *treeStart = &(((p4est_tree_t *)p4estC->trees->array)[tStart]); 22010a96aa3bSJed Brown p4est_tree_t *treeEnd = (size_t)tEnd < p4estC->trees->elem_count ? &(((p4est_tree_t *)p4estC->trees->array)[tEnd]) : NULL; 22020a96aa3bSJed Brown ssize_t overlapIndex; 22030a96aa3bSJed Brown 22040a96aa3bSJed Brown sendReqs[p - startF] = MPI_REQUEST_NULL; /* just in case we don't initiate a send */ 22050a96aa3bSJed Brown if (p4estF->global_first_quadrant[p] == p4estF->global_first_quadrant[p + 1]) continue; 22060a96aa3bSJed Brown 22070a96aa3bSJed Brown /* locate myFineStart in (or before) a cell */ 22080a96aa3bSJed Brown if (treeStart->quadrants.elem_count) { 2209792fecdfSBarry Smith PetscCallP4estReturn(overlapIndex, sc_array_bsearch, (&(treeStart->quadrants), myFineStart, p4est_quadrant_disjoint)); 22100a96aa3bSJed Brown if (overlapIndex < 0) { 22110a96aa3bSJed Brown firstCell = 0; 22120a96aa3bSJed Brown } else { 22130a96aa3bSJed Brown firstCell = treeStart->quadrants_offset + overlapIndex; 22140a96aa3bSJed Brown } 22150a96aa3bSJed Brown } else { 22160a96aa3bSJed Brown firstCell = 0; 22170a96aa3bSJed Brown } 22180a96aa3bSJed Brown if (treeEnd && treeEnd->quadrants.elem_count) { 2219792fecdfSBarry Smith PetscCallP4estReturn(overlapIndex, sc_array_bsearch, (&(treeEnd->quadrants), myFineEnd, p4est_quadrant_disjoint)); 22200a96aa3bSJed Brown if (overlapIndex < 0) { /* all of this local section is overlapped */ 22210a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 22220a96aa3bSJed Brown } else { 22230a96aa3bSJed Brown p4est_quadrant_t *container = &(((p4est_quadrant_t *)treeEnd->quadrants.array)[overlapIndex]); 22240a96aa3bSJed Brown p4est_quadrant_t first_desc; 22250a96aa3bSJed Brown int equal; 22260a96aa3bSJed Brown 2227792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_first_descendant, (container, &first_desc, P4EST_QMAXLEVEL)); 2228792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal, (myFineEnd, &first_desc)); 22290a96aa3bSJed Brown if (equal) { 22300a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex; 22310a96aa3bSJed Brown } else { 22320a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex + 1; 22330a96aa3bSJed Brown } 22340a96aa3bSJed Brown } 22350a96aa3bSJed Brown } else { 22360a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 22370a96aa3bSJed Brown } 22380a96aa3bSJed Brown send[2 * (p - startF)] = firstCell; 22390a96aa3bSJed Brown send[2 * (p - startF) + 1] = lastCell - firstCell; 22409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(&send[2 * (p - startF)], 2, MPIU_INT, p, tag, comm, &sendReqs[p - startF])); 22410a96aa3bSJed Brown } 22429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endC - startC), recvReqs, MPI_STATUSES_IGNORE)); 22439566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 22449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, startC, endC)); 22450a96aa3bSJed Brown for (p = startC; p < endC; p++) { 22460a96aa3bSJed Brown PetscInt numCells = recv[2 * (p - startC) + 1]; 22479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, numCells)); 22480a96aa3bSJed Brown } 22499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 22509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &nLeaves)); 22519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &leaves)); 22520a96aa3bSJed Brown for (p = startC; p < endC; p++) { 22530a96aa3bSJed Brown PetscInt firstCell = recv[2 * (p - startC)]; 22540a96aa3bSJed Brown PetscInt numCells = recv[2 * (p - startC) + 1]; 22550a96aa3bSJed Brown PetscInt off, i; 22560a96aa3bSJed Brown 22579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 22580a96aa3bSJed Brown for (i = 0; i < numCells; i++) { 22590a96aa3bSJed Brown leaves[off + i].rank = p; 22600a96aa3bSJed Brown leaves[off + i].index = firstCell + i; 22610a96aa3bSJed Brown } 22620a96aa3bSJed Brown } 22639566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sf)); 22649566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, cEnd - cStart, nLeaves, NULL, PETSC_OWN_POINTER, leaves, PETSC_OWN_POINTER)); 22659566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 22669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endF - startF), sendReqs, MPI_STATUSES_IGNORE)); 22679566063dSJacob Faibussowitsch PetscCall(PetscFree2(send, sendReqs)); 22689566063dSJacob Faibussowitsch PetscCall(PetscFree2(recv, recvReqs)); 22690a96aa3bSJed Brown *coveringSF = sf; 22703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22710a96aa3bSJed Brown } 22720a96aa3bSJed Brown 22730a96aa3bSJed Brown /* closure points for locally-owned cells */ 2274d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetCellSFNodes(DM dm, PetscInt numClosureIndices, PetscInt *numClosurePoints, PetscSFNode **closurePoints, PetscBool redirect) 2275d71ae5a4SJacob Faibussowitsch { 22760a96aa3bSJed Brown PetscInt cStart, cEnd; 22770a96aa3bSJed Brown PetscInt count, c; 22780a96aa3bSJed Brown PetscMPIInt rank; 22790a96aa3bSJed Brown PetscInt closureSize = -1; 22800a96aa3bSJed Brown PetscInt *closure = NULL; 22810a96aa3bSJed Brown PetscSF pointSF; 22820a96aa3bSJed Brown PetscInt nleaves, nroots; 22830a96aa3bSJed Brown const PetscInt *ilocal; 22840a96aa3bSJed Brown const PetscSFNode *iremote; 22850a96aa3bSJed Brown DM plex; 22860a96aa3bSJed Brown DM_Forest *forest; 22870a96aa3bSJed Brown DM_Forest_pforest *pforest; 22880a96aa3bSJed Brown 22890a96aa3bSJed Brown PetscFunctionBegin; 22900a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 22910a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 22920a96aa3bSJed Brown cStart = pforest->cLocalStart; 22930a96aa3bSJed Brown cEnd = pforest->cLocalEnd; 22949566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 22959566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &pointSF)); 22969566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &ilocal, &iremote)); 22970a96aa3bSJed Brown nleaves = PetscMax(0, nleaves); 22980a96aa3bSJed Brown nroots = PetscMax(0, nroots); 22990a96aa3bSJed Brown *numClosurePoints = numClosureIndices * (cEnd - cStart); 23009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numClosurePoints, closurePoints)); 23019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 23020a96aa3bSJed Brown for (c = cStart, count = 0; c < cEnd; c++) { 23030a96aa3bSJed Brown PetscInt i; 23049566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, c, PETSC_TRUE, &closureSize, &closure)); 23050a96aa3bSJed Brown 23060a96aa3bSJed Brown for (i = 0; i < numClosureIndices; i++, count++) { 23070a96aa3bSJed Brown PetscInt p = closure[2 * i]; 23080a96aa3bSJed Brown PetscInt loc = -1; 23090a96aa3bSJed Brown 23109566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p, nleaves, ilocal, &loc)); 23110a96aa3bSJed Brown if (redirect && loc >= 0) { 23120a96aa3bSJed Brown (*closurePoints)[count].rank = iremote[loc].rank; 23130a96aa3bSJed Brown (*closurePoints)[count].index = iremote[loc].index; 23140a96aa3bSJed Brown } else { 23150a96aa3bSJed Brown (*closurePoints)[count].rank = rank; 23160a96aa3bSJed Brown (*closurePoints)[count].index = p; 23170a96aa3bSJed Brown } 23180a96aa3bSJed Brown } 23199566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, c, PETSC_TRUE, &closureSize, &closure)); 23200a96aa3bSJed Brown } 23213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23220a96aa3bSJed Brown } 23230a96aa3bSJed Brown 2324d71ae5a4SJacob Faibussowitsch static void MPIAPI DMPforestMaxSFNode(void *a, void *b, PetscMPIInt *len, MPI_Datatype *type) 2325d71ae5a4SJacob Faibussowitsch { 23260a96aa3bSJed Brown PetscMPIInt i; 23270a96aa3bSJed Brown 23280a96aa3bSJed Brown for (i = 0; i < *len; i++) { 23290a96aa3bSJed Brown PetscSFNode *A = (PetscSFNode *)a; 23300a96aa3bSJed Brown PetscSFNode *B = (PetscSFNode *)b; 23310a96aa3bSJed Brown 23320a96aa3bSJed Brown if (B->rank < 0) *B = *A; 23330a96aa3bSJed Brown } 23340a96aa3bSJed Brown } 23350a96aa3bSJed Brown 2336d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetTransferSF_Point(DM coarse, DM fine, PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 2337d71ae5a4SJacob Faibussowitsch { 23380a96aa3bSJed Brown MPI_Comm comm; 23390a96aa3bSJed Brown PetscMPIInt rank, size; 23400a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 23410a96aa3bSJed Brown p4est_t *p4estC, *p4estF; 23420a96aa3bSJed Brown PetscInt numClosureIndices; 23430a96aa3bSJed Brown PetscInt numClosurePointsC, numClosurePointsF; 23440a96aa3bSJed Brown PetscSFNode *closurePointsC, *closurePointsF; 23450a96aa3bSJed Brown p4est_quadrant_t *coverQuads = NULL; 23460a96aa3bSJed Brown p4est_quadrant_t **treeQuads; 23470a96aa3bSJed Brown PetscInt *treeQuadCounts; 23480a96aa3bSJed Brown MPI_Datatype nodeType; 23490a96aa3bSJed Brown MPI_Datatype nodeClosureType; 23500a96aa3bSJed Brown MPI_Op sfNodeReduce; 23510a96aa3bSJed Brown p4est_topidx_t fltF, lltF, t; 23520a96aa3bSJed Brown DM plexC, plexF; 23530a96aa3bSJed Brown PetscInt pStartF, pEndF, pStartC, pEndC; 23540a96aa3bSJed Brown PetscBool saveInCoarse = PETSC_FALSE; 23550a96aa3bSJed Brown PetscBool saveInFine = PETSC_FALSE; 23560a96aa3bSJed Brown PetscBool formCids = (childIds != NULL) ? PETSC_TRUE : PETSC_FALSE; 23570a96aa3bSJed Brown PetscInt *cids = NULL; 23580a96aa3bSJed Brown 23590a96aa3bSJed Brown PetscFunctionBegin; 23600a96aa3bSJed Brown pforestC = (DM_Forest_pforest *)((DM_Forest *)coarse->data)->data; 23610a96aa3bSJed Brown pforestF = (DM_Forest_pforest *)((DM_Forest *)fine->data)->data; 23620a96aa3bSJed Brown p4estC = pforestC->forest; 23630a96aa3bSJed Brown p4estF = pforestF->forest; 236408401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo, PetscObjectComm((PetscObject)coarse), PETSC_ERR_ARG_INCOMP, "DM's must have the same base DM"); 23650a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 23669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 23679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 23689566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine, &plexF)); 23699566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF, &pStartF, &pEndF)); 23709566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse, &plexC)); 23719566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC, &pStartC, &pEndC)); 23720a96aa3bSJed Brown { /* check if the results have been cached */ 23730a96aa3bSJed Brown DM adaptCoarse, adaptFine; 23740a96aa3bSJed Brown 23759566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(coarse, &adaptCoarse)); 23769566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(fine, &adaptFine)); 23770a96aa3bSJed Brown if (adaptCoarse && adaptCoarse->data == fine->data) { /* coarse is adapted from fine */ 23780a96aa3bSJed Brown if (pforestC->pointSelfToAdaptSF) { 23799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(pforestC->pointSelfToAdaptSF))); 23800a96aa3bSJed Brown *sf = pforestC->pointSelfToAdaptSF; 23810a96aa3bSJed Brown if (childIds) { 23829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids)); 23839566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids, pforestC->pointSelfToAdaptCids, pEndF - pStartF)); 23840a96aa3bSJed Brown *childIds = cids; 23850a96aa3bSJed Brown } 23863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23870a96aa3bSJed Brown } else { 23880a96aa3bSJed Brown saveInCoarse = PETSC_TRUE; 23890a96aa3bSJed Brown formCids = PETSC_TRUE; 23900a96aa3bSJed Brown } 23910a96aa3bSJed Brown } else if (adaptFine && adaptFine->data == coarse->data) { /* fine is adapted from coarse */ 23920a96aa3bSJed Brown if (pforestF->pointAdaptToSelfSF) { 23939566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(pforestF->pointAdaptToSelfSF))); 23940a96aa3bSJed Brown *sf = pforestF->pointAdaptToSelfSF; 23950a96aa3bSJed Brown if (childIds) { 23969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids)); 23979566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids, pforestF->pointAdaptToSelfCids, pEndF - pStartF)); 23980a96aa3bSJed Brown *childIds = cids; 23990a96aa3bSJed Brown } 24003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24010a96aa3bSJed Brown } else { 24020a96aa3bSJed Brown saveInFine = PETSC_TRUE; 24030a96aa3bSJed Brown formCids = PETSC_TRUE; 24040a96aa3bSJed Brown } 24050a96aa3bSJed Brown } 24060a96aa3bSJed Brown } 24070a96aa3bSJed Brown 24080a96aa3bSJed Brown /* count the number of closure points that have dofs and create a list */ 24090a96aa3bSJed Brown numClosureIndices = P4EST_INSUL; 24100a96aa3bSJed Brown /* create the datatype */ 24119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(2, MPIU_INT, &nodeType)); 24129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 24139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(DMPforestMaxSFNode, PETSC_FALSE, &sfNodeReduce)); 24149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(numClosureIndices * 2, MPIU_INT, &nodeClosureType)); 24159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeClosureType)); 24160a96aa3bSJed Brown /* everything has to go through cells: for each cell, create a list of the sfnodes in its closure */ 24170a96aa3bSJed Brown /* get lists of closure point SF nodes for every cell */ 24189566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(coarse, numClosureIndices, &numClosurePointsC, &closurePointsC, PETSC_TRUE)); 24199566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(fine, numClosureIndices, &numClosurePointsF, &closurePointsF, PETSC_FALSE)); 24200a96aa3bSJed Brown /* create pointers for tree lists */ 24210a96aa3bSJed Brown fltF = p4estF->first_local_tree; 24220a96aa3bSJed Brown lltF = p4estF->last_local_tree; 24239566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(lltF + 1 - fltF, &treeQuads, lltF + 1 - fltF, &treeQuadCounts)); 24240a96aa3bSJed Brown /* if the partitions don't match, ship the coarse to cover the fine */ 24250a96aa3bSJed Brown if (size > 1) { 24260a96aa3bSJed Brown PetscInt p; 24270a96aa3bSJed Brown 24280a96aa3bSJed Brown for (p = 0; p < size; p++) { 24290a96aa3bSJed Brown int equal; 24300a96aa3bSJed Brown 2431792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal_piggy, (&p4estC->global_first_position[p], &p4estF->global_first_position[p])); 24320a96aa3bSJed Brown if (!equal) break; 24330a96aa3bSJed Brown } 24340a96aa3bSJed Brown if (p < size) { /* non-matching distribution: send the coarse to cover the fine */ 24350a96aa3bSJed Brown PetscInt cStartC, cEndC; 24360a96aa3bSJed Brown PetscSF coveringSF; 24370a96aa3bSJed Brown PetscInt nleaves; 24380a96aa3bSJed Brown PetscInt count; 24390a96aa3bSJed Brown PetscSFNode *newClosurePointsC; 24400a96aa3bSJed Brown p4est_quadrant_t *coverQuadsSend; 24410a96aa3bSJed Brown p4est_topidx_t fltC = p4estC->first_local_tree; 24420a96aa3bSJed Brown p4est_topidx_t lltC = p4estC->last_local_tree; 24430a96aa3bSJed Brown p4est_topidx_t t; 24440a96aa3bSJed Brown PetscMPIInt blockSizes[4] = {P4EST_DIM, 2, 1, 1}; 24459371c9d4SSatish 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)}; 24460a96aa3bSJed Brown MPI_Datatype blockTypes[4] = {MPI_INT32_T, MPI_INT8_T, MPI_INT16_T, MPI_INT32_T /* p.which_tree */}; 24470a96aa3bSJed Brown MPI_Datatype quadStruct, quadType; 24480a96aa3bSJed Brown 24499566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC, 0, &cStartC, &cEndC)); 24509566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellCoveringSF(comm, p4estC, p4estF, pforestC->cLocalStart, pforestC->cLocalEnd, &coveringSF)); 24519566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coveringSF, NULL, &nleaves, NULL, NULL)); 24529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numClosureIndices * nleaves, &newClosurePointsC)); 24539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &coverQuads)); 24549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEndC - cStartC, &coverQuadsSend)); 24550a96aa3bSJed Brown count = 0; 24560a96aa3bSJed Brown for (t = fltC; t <= lltC; t++) { /* unfortunately, we need to pack a send array, since quads are not stored packed in p4est */ 24570a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estC->trees->array)[t]); 24580a96aa3bSJed Brown PetscInt q; 24590a96aa3bSJed Brown 24609566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&coverQuadsSend[count], tree->quadrants.array, tree->quadrants.elem_count * sizeof(p4est_quadrant_t))); 24610a96aa3bSJed Brown for (q = 0; (size_t)q < tree->quadrants.elem_count; q++) coverQuadsSend[count + q].p.which_tree = t; 24620a96aa3bSJed Brown count += tree->quadrants.elem_count; 24630a96aa3bSJed Brown } 24640a96aa3bSJed Brown /* p is of a union type p4est_quadrant_data, but only the p.which_tree field is active at this time. So, we 24650a96aa3bSJed Brown have a simple blockTypes[] to use. Note that quadStruct does not count potential padding in array of 24660a96aa3bSJed Brown p4est_quadrant_t. We have to call MPI_Type_create_resized() to change upper-bound of quadStruct. 24670a96aa3bSJed Brown */ 24689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(4, blockSizes, blockOffsets, blockTypes, &quadStruct)); 24699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_resized(quadStruct, 0, sizeof(p4est_quadrant_t), &quadType)); 24709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&quadType)); 24719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF, nodeClosureType, closurePointsC, newClosurePointsC, MPI_REPLACE)); 24729566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF, quadType, coverQuadsSend, coverQuads, MPI_REPLACE)); 24739566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF, nodeClosureType, closurePointsC, newClosurePointsC, MPI_REPLACE)); 24749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF, quadType, coverQuadsSend, coverQuads, MPI_REPLACE)); 24759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadStruct)); 24769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadType)); 24779566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuadsSend)); 24789566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 24799566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coveringSF)); 24800a96aa3bSJed Brown closurePointsC = newClosurePointsC; 24810a96aa3bSJed Brown 24820a96aa3bSJed Brown /* assign tree quads based on locations in coverQuads */ 24830a96aa3bSJed Brown { 24840a96aa3bSJed Brown PetscInt q; 24850a96aa3bSJed Brown for (q = 0; q < nleaves; q++) { 24860a96aa3bSJed Brown p4est_locidx_t t = coverQuads[q].p.which_tree; 24870a96aa3bSJed Brown if (!treeQuadCounts[t - fltF]++) treeQuads[t - fltF] = &coverQuads[q]; 24880a96aa3bSJed Brown } 24890a96aa3bSJed Brown } 24900a96aa3bSJed Brown } 24910a96aa3bSJed Brown } 24920a96aa3bSJed Brown if (!coverQuads) { /* matching partitions: assign tree quads based on locations in p4est native arrays */ 24930a96aa3bSJed Brown for (t = fltF; t <= lltF; t++) { 24940a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estC->trees->array)[t]); 24950a96aa3bSJed Brown 24960a96aa3bSJed Brown treeQuadCounts[t - fltF] = tree->quadrants.elem_count; 24970a96aa3bSJed Brown treeQuads[t - fltF] = (p4est_quadrant_t *)tree->quadrants.array; 24980a96aa3bSJed Brown } 24990a96aa3bSJed Brown } 25000a96aa3bSJed Brown 25010a96aa3bSJed Brown { 25020a96aa3bSJed Brown PetscInt p; 25030a96aa3bSJed Brown PetscInt cLocalStartF; 25040a96aa3bSJed Brown PetscSF pointSF; 25050a96aa3bSJed Brown PetscSFNode *roots; 25060a96aa3bSJed Brown PetscInt *rootType; 25070a96aa3bSJed Brown DM refTree = NULL; 25080a96aa3bSJed Brown DMLabel canonical; 25090a96aa3bSJed Brown PetscInt *childClosures[P4EST_CHILDREN] = {NULL}; 25100a96aa3bSJed Brown PetscInt *rootClosure = NULL; 25110a96aa3bSJed Brown PetscInt coarseOffset; 25120a96aa3bSJed Brown PetscInt numCoarseQuads; 25130a96aa3bSJed Brown 25149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &roots)); 25159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &rootType)); 25169566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(fine, &pointSF)); 25170a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 25180a96aa3bSJed Brown roots[p - pStartF].rank = -1; 25190a96aa3bSJed Brown roots[p - pStartF].index = -1; 25200a96aa3bSJed Brown rootType[p - pStartF] = -1; 25210a96aa3bSJed Brown } 25220a96aa3bSJed Brown if (formCids) { 25230a96aa3bSJed Brown PetscInt child; 25240a96aa3bSJed Brown 25259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids)); 25260a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) cids[p - pStartF] = -2; 25279566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF, &refTree)); 25289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, 0, PETSC_TRUE, NULL, &rootClosure)); 25290a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { /* get the closures of the child cells in the reference tree */ 25309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child + 1, PETSC_TRUE, NULL, &childClosures[child])); 25310a96aa3bSJed Brown } 25329566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical)); 25330a96aa3bSJed Brown } 25340a96aa3bSJed Brown cLocalStartF = pforestF->cLocalStart; 25350a96aa3bSJed Brown for (t = fltF, coarseOffset = 0, numCoarseQuads = 0; t <= lltF; t++, coarseOffset += numCoarseQuads) { 25360a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estF->trees->array)[t]); 25370a96aa3bSJed Brown PetscInt numFineQuads = tree->quadrants.elem_count; 25380a96aa3bSJed Brown p4est_quadrant_t *coarseQuads = treeQuads[t - fltF]; 25390a96aa3bSJed Brown p4est_quadrant_t *fineQuads = (p4est_quadrant_t *)tree->quadrants.array; 25400a96aa3bSJed Brown PetscInt i, coarseCount = 0; 25410a96aa3bSJed Brown PetscInt offset = tree->quadrants_offset; 25420a96aa3bSJed Brown sc_array_t coarseQuadsArray; 25430a96aa3bSJed Brown 25440a96aa3bSJed Brown numCoarseQuads = treeQuadCounts[t - fltF]; 2545792fecdfSBarry Smith PetscCallP4est(sc_array_init_data, (&coarseQuadsArray, coarseQuads, sizeof(p4est_quadrant_t), (size_t)numCoarseQuads)); 25460a96aa3bSJed Brown for (i = 0; i < numFineQuads; i++) { 25470a96aa3bSJed Brown PetscInt c = i + offset; 25480a96aa3bSJed Brown p4est_quadrant_t *quad = &fineQuads[i]; 25490a96aa3bSJed Brown p4est_quadrant_t *quadCoarse = NULL; 25500a96aa3bSJed Brown ssize_t disjoint = -1; 25510a96aa3bSJed Brown 25520a96aa3bSJed Brown while (disjoint < 0 && coarseCount < numCoarseQuads) { 25530a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2554792fecdfSBarry Smith PetscCallP4estReturn(disjoint, p4est_quadrant_disjoint, (quadCoarse, quad)); 25550a96aa3bSJed Brown if (disjoint < 0) coarseCount++; 25560a96aa3bSJed Brown } 255708401ef6SPierre Jolivet PetscCheck(disjoint == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "did not find overlapping coarse quad"); 25580a96aa3bSJed Brown if (quadCoarse->level > quad->level || (quadCoarse->level == quad->level && !transferIdent)) { /* the "coarse" mesh is finer than the fine mesh at the point: continue */ 25590a96aa3bSJed Brown if (transferIdent) { /* find corners */ 25600a96aa3bSJed Brown PetscInt j = 0; 25610a96aa3bSJed Brown 25620a96aa3bSJed Brown do { 25630a96aa3bSJed Brown if (j < P4EST_CHILDREN) { 25640a96aa3bSJed Brown p4est_quadrant_t cornerQuad; 25650a96aa3bSJed Brown int equal; 25660a96aa3bSJed Brown 2567792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_descendant, (quad, &cornerQuad, j, quadCoarse->level)); 2568792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal, (&cornerQuad, quadCoarse)); 25690a96aa3bSJed Brown if (equal) { 25700a96aa3bSJed Brown PetscInt petscJ = P4estVertToPetscVert[j]; 25710a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + (P4EST_INSUL - P4EST_CHILDREN) + petscJ].index; 25720a96aa3bSJed Brown PetscSFNode q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + (P4EST_INSUL - P4EST_CHILDREN) + petscJ]; 25730a96aa3bSJed Brown 25740a96aa3bSJed Brown roots[p - pStartF] = q; 25750a96aa3bSJed Brown rootType[p - pStartF] = PETSC_MAX_INT; 25760a96aa3bSJed Brown cids[p - pStartF] = -1; 25770a96aa3bSJed Brown j++; 25780a96aa3bSJed Brown } 25790a96aa3bSJed Brown } 25800a96aa3bSJed Brown coarseCount++; 25810a96aa3bSJed Brown disjoint = 1; 25820a96aa3bSJed Brown if (coarseCount < numCoarseQuads) { 25830a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2584792fecdfSBarry Smith PetscCallP4estReturn(disjoint, p4est_quadrant_disjoint, (quadCoarse, quad)); 25850a96aa3bSJed Brown } 25860a96aa3bSJed Brown } while (!disjoint); 25870a96aa3bSJed Brown } 25880a96aa3bSJed Brown continue; 25890a96aa3bSJed Brown } 25900a96aa3bSJed Brown if (quadCoarse->level == quad->level) { /* same quad present in coarse and fine mesh */ 25910a96aa3bSJed Brown PetscInt j; 25920a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 25930a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + j].index; 25940a96aa3bSJed Brown 25950a96aa3bSJed Brown roots[p - pStartF] = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + j]; 25960a96aa3bSJed Brown rootType[p - pStartF] = PETSC_MAX_INT; /* unconditionally accept */ 25970a96aa3bSJed Brown cids[p - pStartF] = -1; 25980a96aa3bSJed Brown } 25990a96aa3bSJed Brown } else { 26000a96aa3bSJed Brown PetscInt levelDiff = quad->level - quadCoarse->level; 26010a96aa3bSJed Brown PetscInt proposedCids[P4EST_INSUL] = {0}; 26020a96aa3bSJed Brown 26030a96aa3bSJed Brown if (formCids) { 26040a96aa3bSJed Brown PetscInt cl; 26050a96aa3bSJed Brown PetscInt *pointClosure = NULL; 26060a96aa3bSJed Brown int cid; 26070a96aa3bSJed Brown 260808401ef6SPierre Jolivet PetscCheck(levelDiff <= 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Recursive child ids not implemented"); 2609792fecdfSBarry Smith PetscCallP4estReturn(cid, p4est_quadrant_child_id, (quad)); 26109566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plexF, c + cLocalStartF, PETSC_TRUE, NULL, &pointClosure)); 26110a96aa3bSJed Brown for (cl = 0; cl < P4EST_INSUL; cl++) { 26120a96aa3bSJed Brown PetscInt p = pointClosure[2 * cl]; 26130a96aa3bSJed Brown PetscInt point = childClosures[cid][2 * cl]; 26140a96aa3bSJed Brown PetscInt ornt = childClosures[cid][2 * cl + 1]; 26150a96aa3bSJed Brown PetscInt newcid = -1; 26160a96aa3bSJed Brown DMPolytopeType ct; 26170a96aa3bSJed Brown 26180a96aa3bSJed Brown if (rootType[p - pStartF] == PETSC_MAX_INT) continue; 26199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, point, &ct)); 26200a96aa3bSJed Brown ornt = DMPolytopeConvertNewOrientation_Internal(ct, ornt); 26210a96aa3bSJed Brown if (!cl) { 26220a96aa3bSJed Brown newcid = cid + 1; 26230a96aa3bSJed Brown } else { 26240a96aa3bSJed Brown PetscInt rcl, parent, parentOrnt = 0; 26250a96aa3bSJed Brown 26269566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, point, &parent, NULL)); 26270a96aa3bSJed Brown if (parent == point) { 26280a96aa3bSJed Brown newcid = -1; 26290a96aa3bSJed Brown } else if (!parent) { /* in the root */ 26300a96aa3bSJed Brown newcid = point; 26310a96aa3bSJed Brown } else { 26320a96aa3bSJed Brown DMPolytopeType rct = DM_POLYTOPE_UNKNOWN; 26330a96aa3bSJed Brown 26340a96aa3bSJed Brown for (rcl = 1; rcl < P4EST_INSUL; rcl++) { 26350a96aa3bSJed Brown if (rootClosure[2 * rcl] == parent) { 26369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, parent, &rct)); 26370a96aa3bSJed Brown parentOrnt = DMPolytopeConvertNewOrientation_Internal(rct, rootClosure[2 * rcl + 1]); 26380a96aa3bSJed Brown break; 26390a96aa3bSJed Brown } 26400a96aa3bSJed Brown } 264108401ef6SPierre Jolivet PetscCheck(rcl < P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Couldn't find parent in root closure"); 26429566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(refTree, parent, parentOrnt, ornt, point, DMPolytopeConvertNewOrientation_Internal(rct, pointClosure[2 * rcl + 1]), NULL, &newcid)); 26430a96aa3bSJed Brown } 26440a96aa3bSJed Brown } 26450a96aa3bSJed Brown if (newcid >= 0) { 264648a46eb9SPierre Jolivet if (canonical) PetscCall(DMLabelGetValue(canonical, newcid, &newcid)); 26470a96aa3bSJed Brown proposedCids[cl] = newcid; 26480a96aa3bSJed Brown } 26490a96aa3bSJed Brown } 26509566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plexF, c + cLocalStartF, PETSC_TRUE, NULL, &pointClosure)); 26510a96aa3bSJed Brown } 26529371c9d4SSatish Balay p4est_qcoord_t coarseBound[2][P4EST_DIM] = { 26539371c9d4SSatish Balay {quadCoarse->x, quadCoarse->y, 26540a96aa3bSJed Brown #if defined(P4_TO_P8) 26550a96aa3bSJed Brown quadCoarse->z 26560a96aa3bSJed Brown #endif 26579371c9d4SSatish Balay }, 26589371c9d4SSatish Balay {0} 26599371c9d4SSatish Balay }; 26609371c9d4SSatish Balay p4est_qcoord_t fineBound[2][P4EST_DIM] = { 26619371c9d4SSatish Balay {quad->x, quad->y, 26620a96aa3bSJed Brown #if defined(P4_TO_P8) 26630a96aa3bSJed Brown quad->z 26640a96aa3bSJed Brown #endif 26659371c9d4SSatish Balay }, 26669371c9d4SSatish Balay {0} 26679371c9d4SSatish Balay }; 26680a96aa3bSJed Brown PetscInt j; 26690a96aa3bSJed Brown for (j = 0; j < P4EST_DIM; j++) { /* get the coordinates of cell boundaries in each direction */ 26700a96aa3bSJed Brown coarseBound[1][j] = coarseBound[0][j] + P4EST_QUADRANT_LEN(quadCoarse->level); 26710a96aa3bSJed Brown fineBound[1][j] = fineBound[0][j] + P4EST_QUADRANT_LEN(quad->level); 26720a96aa3bSJed Brown } 26730a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 26740a96aa3bSJed Brown PetscInt l, p; 26750a96aa3bSJed Brown PetscSFNode q; 26760a96aa3bSJed Brown 26770a96aa3bSJed Brown p = closurePointsF[numClosureIndices * c + j].index; 26780a96aa3bSJed Brown if (rootType[p - pStartF] == PETSC_MAX_INT) continue; 26790a96aa3bSJed Brown if (j == 0) { /* volume: ancestor is volume */ 26800a96aa3bSJed Brown l = 0; 26810a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES) { /* facet */ 26820a96aa3bSJed Brown PetscInt face = PetscFaceToP4estFace[j - 1]; 26830a96aa3bSJed Brown PetscInt direction = face / 2; 26840a96aa3bSJed Brown PetscInt coarseFace = -1; 26850a96aa3bSJed Brown 26860a96aa3bSJed Brown if (coarseBound[face % 2][direction] == fineBound[face % 2][direction]) { 26870a96aa3bSJed Brown coarseFace = face; 26880a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 26890a96aa3bSJed Brown } else { 26900a96aa3bSJed Brown l = 0; 26910a96aa3bSJed Brown } 26920a96aa3bSJed Brown #if defined(P4_TO_P8) 26930a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES + P8EST_EDGES) { 26940a96aa3bSJed Brown PetscInt edge = PetscEdgeToP4estEdge[j - (1 + P4EST_FACES)]; 26950a96aa3bSJed Brown PetscInt direction = edge / 4; 26960a96aa3bSJed Brown PetscInt mod = edge % 4; 26970a96aa3bSJed Brown PetscInt coarseEdge = -1, coarseFace = -1; 26980a96aa3bSJed Brown PetscInt minDir = PetscMin((direction + 1) % 3, (direction + 2) % 3); 26990a96aa3bSJed Brown PetscInt maxDir = PetscMax((direction + 1) % 3, (direction + 2) % 3); 27000a96aa3bSJed Brown PetscBool dirTest[2]; 27010a96aa3bSJed Brown 27020a96aa3bSJed Brown dirTest[0] = (PetscBool)(coarseBound[mod % 2][minDir] == fineBound[mod % 2][minDir]); 27030a96aa3bSJed Brown dirTest[1] = (PetscBool)(coarseBound[mod / 2][maxDir] == fineBound[mod / 2][maxDir]); 27040a96aa3bSJed Brown 27050a96aa3bSJed Brown if (dirTest[0] && dirTest[1]) { /* fine edge falls on coarse edge */ 27060a96aa3bSJed Brown coarseEdge = edge; 27070a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 27080a96aa3bSJed Brown } else if (dirTest[0]) { /* fine edge falls on a coarse face in the minDir direction */ 27090a96aa3bSJed Brown coarseFace = 2 * minDir + (mod % 2); 27100a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27110a96aa3bSJed Brown } else if (dirTest[1]) { /* fine edge falls on a coarse face in the maxDir direction */ 27120a96aa3bSJed Brown coarseFace = 2 * maxDir + (mod / 2); 27130a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27140a96aa3bSJed Brown } else { 27150a96aa3bSJed Brown l = 0; 27160a96aa3bSJed Brown } 27170a96aa3bSJed Brown #endif 27180a96aa3bSJed Brown } else { 27190a96aa3bSJed Brown PetscInt vertex = PetscVertToP4estVert[P4EST_CHILDREN - (P4EST_INSUL - j)]; 27200a96aa3bSJed Brown PetscBool dirTest[P4EST_DIM]; 27210a96aa3bSJed Brown PetscInt m; 27220a96aa3bSJed Brown PetscInt numMatch = 0; 27230a96aa3bSJed Brown PetscInt coarseVertex = -1, coarseFace = -1; 27240a96aa3bSJed Brown #if defined(P4_TO_P8) 27250a96aa3bSJed Brown PetscInt coarseEdge = -1; 27260a96aa3bSJed Brown #endif 27270a96aa3bSJed Brown 27280a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27290a96aa3bSJed Brown dirTest[m] = (PetscBool)(coarseBound[(vertex >> m) & 1][m] == fineBound[(vertex >> m) & 1][m]); 27300a96aa3bSJed Brown if (dirTest[m]) numMatch++; 27310a96aa3bSJed Brown } 27320a96aa3bSJed Brown if (numMatch == P4EST_DIM) { /* vertex on vertex */ 27330a96aa3bSJed Brown coarseVertex = vertex; 27340a96aa3bSJed Brown l = P4EST_INSUL - (P4EST_CHILDREN - P4estVertToPetscVert[coarseVertex]); 27350a96aa3bSJed Brown } else if (numMatch == 1) { /* vertex on face */ 27360a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27370a96aa3bSJed Brown if (dirTest[m]) { 27380a96aa3bSJed Brown coarseFace = 2 * m + ((vertex >> m) & 1); 27390a96aa3bSJed Brown break; 27400a96aa3bSJed Brown } 27410a96aa3bSJed Brown } 27420a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27430a96aa3bSJed Brown #if defined(P4_TO_P8) 27440a96aa3bSJed Brown } else if (numMatch == 2) { /* vertex on edge */ 27450a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27460a96aa3bSJed Brown if (!dirTest[m]) { 27470a96aa3bSJed Brown PetscInt otherDir1 = (m + 1) % 3; 27480a96aa3bSJed Brown PetscInt otherDir2 = (m + 2) % 3; 27490a96aa3bSJed Brown PetscInt minDir = PetscMin(otherDir1, otherDir2); 27500a96aa3bSJed Brown PetscInt maxDir = PetscMax(otherDir1, otherDir2); 27510a96aa3bSJed Brown 27520a96aa3bSJed Brown coarseEdge = m * 4 + 2 * ((vertex >> maxDir) & 1) + ((vertex >> minDir) & 1); 27530a96aa3bSJed Brown break; 27540a96aa3bSJed Brown } 27550a96aa3bSJed Brown } 27560a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 27570a96aa3bSJed Brown #endif 27580a96aa3bSJed Brown } else { /* volume */ 27590a96aa3bSJed Brown l = 0; 27600a96aa3bSJed Brown } 27610a96aa3bSJed Brown } 27620a96aa3bSJed Brown q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + l]; 27630a96aa3bSJed Brown if (l > rootType[p - pStartF]) { 27640a96aa3bSJed Brown if (l >= P4EST_INSUL - P4EST_CHILDREN) { /* vertex on vertex: unconditional acceptance */ 27650a96aa3bSJed Brown if (transferIdent) { 27660a96aa3bSJed Brown roots[p - pStartF] = q; 27670a96aa3bSJed Brown rootType[p - pStartF] = PETSC_MAX_INT; 27680a96aa3bSJed Brown if (formCids) cids[p - pStartF] = -1; 27690a96aa3bSJed Brown } 27700a96aa3bSJed Brown } else { 27710a96aa3bSJed Brown PetscInt k, thisp = p, limit; 27720a96aa3bSJed Brown 27730a96aa3bSJed Brown roots[p - pStartF] = q; 27740a96aa3bSJed Brown rootType[p - pStartF] = l; 27750a96aa3bSJed Brown if (formCids) cids[p - pStartF] = proposedCids[j]; 27760a96aa3bSJed Brown limit = transferIdent ? levelDiff : (levelDiff - 1); 27770a96aa3bSJed Brown for (k = 0; k < limit; k++) { 27780a96aa3bSJed Brown PetscInt parent; 27790a96aa3bSJed Brown 27809566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plexF, thisp, &parent, NULL)); 27810a96aa3bSJed Brown if (parent == thisp) break; 27820a96aa3bSJed Brown 27830a96aa3bSJed Brown roots[parent - pStartF] = q; 27840a96aa3bSJed Brown rootType[parent - pStartF] = PETSC_MAX_INT; 27850a96aa3bSJed Brown if (formCids) cids[parent - pStartF] = -1; 27860a96aa3bSJed Brown thisp = parent; 27870a96aa3bSJed Brown } 27880a96aa3bSJed Brown } 27890a96aa3bSJed Brown } 27900a96aa3bSJed Brown } 27910a96aa3bSJed Brown } 27920a96aa3bSJed Brown } 27930a96aa3bSJed Brown } 27940a96aa3bSJed Brown 27950a96aa3bSJed 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 */ 27960a96aa3bSJed Brown if (size > 1) { 27970a96aa3bSJed Brown PetscInt *rootTypeCopy, p; 27980a96aa3bSJed Brown 27999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &rootTypeCopy)); 28009566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(rootTypeCopy, rootType, pEndF - pStartF)); 280157168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_MAX)); 280257168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_MAX)); 28039566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_REPLACE)); 28049566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_REPLACE)); 28050a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28060a96aa3bSJed 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 */ 28070a96aa3bSJed Brown roots[p - pStartF].rank = -1; 28080a96aa3bSJed Brown roots[p - pStartF].index = -1; 28090a96aa3bSJed Brown } 28109371c9d4SSatish 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 */ } 28110a96aa3bSJed Brown } 28129566063dSJacob Faibussowitsch PetscCall(PetscFree(rootTypeCopy)); 28139566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF, nodeType, roots, roots, sfNodeReduce)); 28149566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF, nodeType, roots, roots, sfNodeReduce)); 28159566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, nodeType, roots, roots, MPI_REPLACE)); 28169566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, nodeType, roots, roots, MPI_REPLACE)); 28170a96aa3bSJed Brown } 28189566063dSJacob Faibussowitsch PetscCall(PetscFree(rootType)); 28190a96aa3bSJed Brown 28200a96aa3bSJed Brown { 28210a96aa3bSJed Brown PetscInt numRoots; 28220a96aa3bSJed Brown PetscInt numLeaves; 28230a96aa3bSJed Brown PetscInt *leaves; 28240a96aa3bSJed Brown PetscSFNode *iremote; 28250a96aa3bSJed Brown /* count leaves */ 28260a96aa3bSJed Brown 28270a96aa3bSJed Brown numRoots = pEndC - pStartC; 28280a96aa3bSJed Brown 28290a96aa3bSJed Brown numLeaves = 0; 28300a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28310a96aa3bSJed Brown if (roots[p - pStartF].index >= 0) numLeaves++; 28320a96aa3bSJed Brown } 28339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &leaves)); 28349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &iremote)); 28350a96aa3bSJed Brown numLeaves = 0; 28360a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28370a96aa3bSJed Brown if (roots[p - pStartF].index >= 0) { 28380a96aa3bSJed Brown leaves[numLeaves] = p - pStartF; 28390a96aa3bSJed Brown iremote[numLeaves] = roots[p - pStartF]; 28400a96aa3bSJed Brown numLeaves++; 28410a96aa3bSJed Brown } 28420a96aa3bSJed Brown } 28439566063dSJacob Faibussowitsch PetscCall(PetscFree(roots)); 28449566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sf)); 28450a96aa3bSJed Brown if (numLeaves == (pEndF - pStartF)) { 28469566063dSJacob Faibussowitsch PetscCall(PetscFree(leaves)); 28479566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, numRoots, numLeaves, NULL, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 28480a96aa3bSJed Brown } else { 28499566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, numRoots, numLeaves, leaves, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 28500a96aa3bSJed Brown } 28510a96aa3bSJed Brown } 28520a96aa3bSJed Brown if (formCids) { 28530a96aa3bSJed Brown PetscSF pointSF; 28540a96aa3bSJed Brown PetscInt child; 28550a96aa3bSJed Brown 28569566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF, &refTree)); 28579566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plexF, &pointSF)); 285857168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, cids, cids, MPI_MAX)); 285957168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, cids, cids, MPI_MAX)); 28600a96aa3bSJed Brown if (childIds) *childIds = cids; 286148a46eb9SPierre Jolivet for (child = 0; child < P4EST_CHILDREN; child++) PetscCall(DMPlexRestoreTransitiveClosure(refTree, child + 1, PETSC_TRUE, NULL, &childClosures[child])); 28629566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, 0, PETSC_TRUE, NULL, &rootClosure)); 28630a96aa3bSJed Brown } 28640a96aa3bSJed Brown } 28650a96aa3bSJed Brown if (saveInCoarse) { /* cache results */ 28669566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 28670a96aa3bSJed Brown pforestC->pointSelfToAdaptSF = *sf; 28680a96aa3bSJed Brown if (!childIds) { 28690a96aa3bSJed Brown pforestC->pointSelfToAdaptCids = cids; 28700a96aa3bSJed Brown } else { 28719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &pforestC->pointSelfToAdaptCids)); 28729566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestC->pointSelfToAdaptCids, cids, pEndF - pStartF)); 28730a96aa3bSJed Brown } 28740a96aa3bSJed Brown } else if (saveInFine) { 28759566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 28760a96aa3bSJed Brown pforestF->pointAdaptToSelfSF = *sf; 28770a96aa3bSJed Brown if (!childIds) { 28780a96aa3bSJed Brown pforestF->pointAdaptToSelfCids = cids; 28790a96aa3bSJed Brown } else { 28809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &pforestF->pointAdaptToSelfCids)); 28819566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestF->pointAdaptToSelfCids, cids, pEndF - pStartF)); 28820a96aa3bSJed Brown } 28830a96aa3bSJed Brown } 28849566063dSJacob Faibussowitsch PetscCall(PetscFree2(treeQuads, treeQuadCounts)); 28859566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuads)); 28869566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 28879566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsF)); 28889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeClosureType)); 28899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&sfNodeReduce)); 28909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 28913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28920a96aa3bSJed Brown } 28930a96aa3bSJed Brown 28940a96aa3bSJed Brown /* children are sf leaves of parents */ 2895d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetTransferSF_Internal(DM coarse, DM fine, const PetscInt dofPerDim[], PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 2896d71ae5a4SJacob Faibussowitsch { 28970a96aa3bSJed Brown MPI_Comm comm; 2898d70f29a3SPierre Jolivet PetscMPIInt rank; 28990a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 29000a96aa3bSJed Brown DM plexC, plexF; 29010a96aa3bSJed Brown PetscInt pStartC, pEndC, pStartF, pEndF; 29020a96aa3bSJed Brown PetscSF pointTransferSF; 29030a96aa3bSJed Brown PetscBool allOnes = PETSC_TRUE; 29040a96aa3bSJed Brown 29050a96aa3bSJed Brown PetscFunctionBegin; 29060a96aa3bSJed Brown pforestC = (DM_Forest_pforest *)((DM_Forest *)coarse->data)->data; 29070a96aa3bSJed Brown pforestF = (DM_Forest_pforest *)((DM_Forest *)fine->data)->data; 290808401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo, PetscObjectComm((PetscObject)coarse), PETSC_ERR_ARG_INCOMP, "DM's must have the same base DM"); 29090a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 29109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 29110a96aa3bSJed Brown 29120a96aa3bSJed Brown { 29130a96aa3bSJed Brown PetscInt i; 29140a96aa3bSJed Brown for (i = 0; i <= P4EST_DIM; i++) { 29150a96aa3bSJed Brown if (dofPerDim[i] != 1) { 29160a96aa3bSJed Brown allOnes = PETSC_FALSE; 29170a96aa3bSJed Brown break; 29180a96aa3bSJed Brown } 29190a96aa3bSJed Brown } 29200a96aa3bSJed Brown } 29219566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Point(coarse, fine, &pointTransferSF, transferIdent, childIds)); 29220a96aa3bSJed Brown if (allOnes) { 29230a96aa3bSJed Brown *sf = pointTransferSF; 29243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29250a96aa3bSJed Brown } 29260a96aa3bSJed Brown 29279566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine, &plexF)); 29289566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF, &pStartF, &pEndF)); 29299566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse, &plexC)); 29309566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC, &pStartC, &pEndC)); 29310a96aa3bSJed Brown { 29320a96aa3bSJed Brown PetscInt numRoots; 29330a96aa3bSJed Brown PetscInt numLeaves; 29340a96aa3bSJed Brown const PetscInt *leaves; 29350a96aa3bSJed Brown const PetscSFNode *iremote; 29360a96aa3bSJed Brown PetscInt d; 29370a96aa3bSJed Brown PetscSection leafSection, rootSection; 29380a96aa3bSJed Brown /* count leaves */ 29390a96aa3bSJed Brown 29409566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointTransferSF, &numRoots, &numLeaves, &leaves, &iremote)); 29419566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &rootSection)); 29429566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &leafSection)); 29439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, pStartC, pEndC)); 29449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafSection, pStartF, pEndF)); 29450a96aa3bSJed Brown 29460a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 29470a96aa3bSJed Brown PetscInt startC, endC, e; 29480a96aa3bSJed Brown 29499566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC, P4EST_DIM - d, &startC, &endC)); 295048a46eb9SPierre Jolivet for (e = startC; e < endC; e++) PetscCall(PetscSectionSetDof(rootSection, e, dofPerDim[d])); 29510a96aa3bSJed Brown } 29520a96aa3bSJed Brown 29530a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 29540a96aa3bSJed Brown PetscInt startF, endF, e; 29550a96aa3bSJed Brown 29569566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexF, P4EST_DIM - d, &startF, &endF)); 295748a46eb9SPierre Jolivet for (e = startF; e < endF; e++) PetscCall(PetscSectionSetDof(leafSection, e, dofPerDim[d])); 29580a96aa3bSJed Brown } 29590a96aa3bSJed Brown 29609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 29619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSection)); 29620a96aa3bSJed Brown { 29630a96aa3bSJed Brown PetscInt nroots, nleaves; 29640a96aa3bSJed Brown PetscInt *mine, i, p; 29650a96aa3bSJed Brown PetscInt *offsets, *offsetsRoot; 29660a96aa3bSJed Brown PetscSFNode *remote; 29670a96aa3bSJed Brown 29689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &offsets)); 29699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &offsetsRoot)); 297048a46eb9SPierre Jolivet for (p = pStartC; p < pEndC; p++) PetscCall(PetscSectionGetOffset(rootSection, p, &offsetsRoot[p - pStartC])); 29719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointTransferSF, MPIU_INT, offsetsRoot, offsets, MPI_REPLACE)); 29729566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointTransferSF, MPIU_INT, offsetsRoot, offsets, MPI_REPLACE)); 29739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &nroots)); 29740a96aa3bSJed Brown nleaves = 0; 29750a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 29760a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 29770a96aa3bSJed Brown PetscInt dof; 29780a96aa3bSJed Brown 29799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, leaf, &dof)); 29800a96aa3bSJed Brown nleaves += dof; 29810a96aa3bSJed Brown } 29829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &mine)); 29839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remote)); 29840a96aa3bSJed Brown nleaves = 0; 29850a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 29860a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 29870a96aa3bSJed Brown PetscInt dof; 29880a96aa3bSJed Brown PetscInt off, j; 29890a96aa3bSJed Brown 29909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, leaf, &dof)); 29919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection, leaf, &off)); 29920a96aa3bSJed Brown for (j = 0; j < dof; j++) { 29930a96aa3bSJed Brown remote[nleaves].rank = iremote[i].rank; 29940a96aa3bSJed Brown remote[nleaves].index = offsets[leaf] + j; 29950a96aa3bSJed Brown mine[nleaves++] = off + j; 29960a96aa3bSJed Brown } 29970a96aa3bSJed Brown } 29989566063dSJacob Faibussowitsch PetscCall(PetscFree(offsetsRoot)); 29999566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 30009566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sf)); 30019566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, nroots, nleaves, mine, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER)); 30020a96aa3bSJed Brown } 30039566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 30049566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 30059566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointTransferSF)); 30060a96aa3bSJed Brown } 30073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30080a96aa3bSJed Brown } 30090a96aa3bSJed Brown 3010d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetTransferSF(DM dmA, DM dmB, const PetscInt dofPerDim[], PetscSF *sfAtoB, PetscSF *sfBtoA) 3011d71ae5a4SJacob Faibussowitsch { 30120a96aa3bSJed Brown DM adaptA, adaptB; 30130a96aa3bSJed Brown DMAdaptFlag purpose; 30140a96aa3bSJed Brown 30150a96aa3bSJed Brown PetscFunctionBegin; 30169566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmA, &adaptA)); 30179566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmB, &adaptB)); 30180a96aa3bSJed Brown /* it is more efficient when the coarser mesh is the first argument: reorder if we know one is coarser than the other */ 30190a96aa3bSJed Brown if (adaptA && adaptA->data == dmB->data) { /* dmA was adapted from dmB */ 30209566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmA, &purpose)); 30210a96aa3bSJed Brown if (purpose == DM_ADAPT_REFINE) { 30229566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 30233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30240a96aa3bSJed Brown } 30250a96aa3bSJed Brown } else if (adaptB && adaptB->data == dmA->data) { /* dmB was adapted from dmA */ 30269566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmB, &purpose)); 30270a96aa3bSJed Brown if (purpose == DM_ADAPT_COARSEN) { 30289566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 30293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30300a96aa3bSJed Brown } 30310a96aa3bSJed Brown } 30321baa6e33SBarry Smith if (sfAtoB) PetscCall(DMPforestGetTransferSF_Internal(dmA, dmB, dofPerDim, sfAtoB, PETSC_TRUE, NULL)); 30331baa6e33SBarry Smith if (sfBtoA) PetscCall(DMPforestGetTransferSF_Internal(dmB, dmA, dofPerDim, sfBtoA, (PetscBool)(sfAtoB == NULL), NULL)); 30343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30350a96aa3bSJed Brown } 30360a96aa3bSJed Brown 3037d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestLabelsInitialize(DM dm, DM plex) 3038d71ae5a4SJacob Faibussowitsch { 30390a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 30400a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 30410a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, cStart, cEnd, fStart, fEnd, eStart, eEnd, vStart, vEnd; 30420a96aa3bSJed Brown PetscInt cStartBase, cEndBase, fStartBase, fEndBase, vStartBase, vEndBase, eStartBase, eEndBase; 30430a96aa3bSJed Brown PetscInt pStart, pEnd, pStartBase, pEndBase, p; 30440a96aa3bSJed Brown DM base; 30450a96aa3bSJed Brown PetscInt *star = NULL, starSize; 30460a96aa3bSJed Brown DMLabelLink next = dm->labels; 30470a96aa3bSJed Brown PetscInt guess = 0; 30480a96aa3bSJed Brown p4est_topidx_t num_trees = pforest->topo->conn->num_trees; 30490a96aa3bSJed Brown 30500a96aa3bSJed Brown PetscFunctionBegin; 30510a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 30520a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 30530a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 30549566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 30550a96aa3bSJed Brown if (!base) { 30560a96aa3bSJed Brown if (pforest->ghostName) { /* insert a label to make the boundaries, with stratum values denoting which face of the element touches the boundary */ 30570a96aa3bSJed Brown p4est_connectivity_t *conn = pforest->topo->conn; 30580a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 30590a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t *)p4est->trees->array; 30600a96aa3bSJed Brown p4est_topidx_t t, flt = p4est->first_local_tree; 30610a96aa3bSJed Brown p4est_topidx_t llt = pforest->forest->last_local_tree; 30620a96aa3bSJed Brown DMLabel ghostLabel; 30630a96aa3bSJed Brown PetscInt c; 30640a96aa3bSJed Brown 30659566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(plex, pforest->ghostName)); 30669566063dSJacob Faibussowitsch PetscCall(DMGetLabel(plex, pforest->ghostName, &ghostLabel)); 30670a96aa3bSJed Brown for (c = cLocalStart, t = flt; t <= llt; t++) { 30680a96aa3bSJed Brown p4est_tree_t *tree = &trees[t]; 30690a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 30700a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 30710a96aa3bSJed Brown PetscInt q; 30720a96aa3bSJed Brown 30730a96aa3bSJed Brown for (q = 0; q < numQuads; q++, c++) { 30740a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[q]; 30750a96aa3bSJed Brown PetscInt f; 30760a96aa3bSJed Brown 30770a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++) { 30780a96aa3bSJed Brown p4est_quadrant_t neigh; 30790a96aa3bSJed Brown int isOutside; 30800a96aa3bSJed Brown 3081792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor, (quad, f, &neigh)); 3082792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p4est_quadrant_is_outside_face, (&neigh)); 30830a96aa3bSJed Brown if (isOutside) { 30840a96aa3bSJed Brown p4est_topidx_t nt; 30850a96aa3bSJed Brown PetscInt nf; 30860a96aa3bSJed Brown 30870a96aa3bSJed Brown nt = conn->tree_to_tree[t * P4EST_FACES + f]; 30880a96aa3bSJed Brown nf = (PetscInt)conn->tree_to_face[t * P4EST_FACES + f]; 30890a96aa3bSJed Brown nf = nf % P4EST_FACES; 30900a96aa3bSJed Brown if (nt == t && nf == f) { 30910a96aa3bSJed Brown PetscInt plexF = P4estFaceToPetscFace[f]; 30920a96aa3bSJed Brown const PetscInt *cone; 30930a96aa3bSJed Brown 30949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(plex, c, &cone)); 30959566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ghostLabel, cone[plexF], plexF + 1)); 30960a96aa3bSJed Brown } 30970a96aa3bSJed Brown } 30980a96aa3bSJed Brown } 30990a96aa3bSJed Brown } 31000a96aa3bSJed Brown } 31010a96aa3bSJed Brown } 31023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31030a96aa3bSJed Brown } 31049566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, 0, &cStartBase, &cEndBase)); 31059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, 1, &fStartBase, &fEndBase)); 31069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, P4EST_DIM - 1, &eStartBase, &eEndBase)); 31079566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(base, 0, &vStartBase, &vEndBase)); 31080a96aa3bSJed Brown 31099566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, 0, &cStart, &cEnd)); 31109566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, 1, &fStart, &fEnd)); 31119566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, P4EST_DIM - 1, &eStart, &eEnd)); 31129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd)); 31130a96aa3bSJed Brown 31149566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &pStart, &pEnd)); 31159566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(base, &pStartBase, &pEndBase)); 31160a96aa3bSJed Brown /* go through the mesh: use star to find a quadrant that borders a point. Use the closure to determine the 31170a96aa3bSJed Brown * orientation of the quadrant relative to that point. Use that to relate the point to the numbering in the base 31180a96aa3bSJed Brown * mesh, and extract a label value (since the base mesh is redundantly distributed, can be found locally). */ 31190a96aa3bSJed Brown while (next) { 31200a96aa3bSJed Brown DMLabel baseLabel; 31210a96aa3bSJed Brown DMLabel label = next->label; 31220a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK, isSpmap; 31230a96aa3bSJed Brown const char *name; 31240a96aa3bSJed Brown 31259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name)); 31269566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 31270a96aa3bSJed Brown if (isDepth) { 31280a96aa3bSJed Brown next = next->next; 31290a96aa3bSJed Brown continue; 31300a96aa3bSJed Brown } 31319566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 31320a96aa3bSJed Brown if (isCellType) { 31330a96aa3bSJed Brown next = next->next; 31340a96aa3bSJed Brown continue; 31350a96aa3bSJed Brown } 31369566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 31370a96aa3bSJed Brown if (isGhost) { 31380a96aa3bSJed Brown next = next->next; 31390a96aa3bSJed Brown continue; 31400a96aa3bSJed Brown } 31419566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 31420a96aa3bSJed Brown if (isVTK) { 31430a96aa3bSJed Brown next = next->next; 31440a96aa3bSJed Brown continue; 31450a96aa3bSJed Brown } 31469566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "_forest_base_subpoint_map", &isSpmap)); 31470a96aa3bSJed Brown if (!isSpmap) { 31489566063dSJacob Faibussowitsch PetscCall(DMGetLabel(base, name, &baseLabel)); 31490a96aa3bSJed Brown if (!baseLabel) { 31500a96aa3bSJed Brown next = next->next; 31510a96aa3bSJed Brown continue; 31520a96aa3bSJed Brown } 31539566063dSJacob Faibussowitsch PetscCall(DMLabelCreateIndex(baseLabel, pStartBase, pEndBase)); 31540a96aa3bSJed Brown } else baseLabel = NULL; 31550a96aa3bSJed Brown 31560a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 31570a96aa3bSJed Brown PetscInt s, c = -1, l; 31580a96aa3bSJed Brown PetscInt *closure = NULL, closureSize; 31590a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 31600a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t *)pforest->forest->trees->array; 31610a96aa3bSJed Brown p4est_quadrant_t *q; 31620a96aa3bSJed Brown PetscInt t, val; 31630a96aa3bSJed Brown PetscBool zerosupportpoint = PETSC_FALSE; 31640a96aa3bSJed Brown 31659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star)); 31660a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 31670a96aa3bSJed Brown PetscInt point = star[2 * s]; 31680a96aa3bSJed Brown 31690a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 31709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, point, PETSC_TRUE, &closureSize, &closure)); 31710a96aa3bSJed Brown for (l = 0; l < closureSize; l++) { 31720a96aa3bSJed Brown PetscInt qParent = closure[2 * l], q, pp = p, pParent = p; 31730a96aa3bSJed Brown do { /* check parents of q */ 31740a96aa3bSJed Brown q = qParent; 31750a96aa3bSJed Brown if (q == p) { 31760a96aa3bSJed Brown c = point; 31770a96aa3bSJed Brown break; 31780a96aa3bSJed Brown } 31799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &qParent, NULL)); 31800a96aa3bSJed Brown } while (qParent != q); 31810a96aa3bSJed Brown if (c != -1) break; 31829566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, pp, &pParent, NULL)); 31830a96aa3bSJed Brown q = closure[2 * l]; 31840a96aa3bSJed Brown while (pParent != pp) { /* check parents of p */ 31850a96aa3bSJed Brown pp = pParent; 31860a96aa3bSJed Brown if (pp == q) { 31870a96aa3bSJed Brown c = point; 31880a96aa3bSJed Brown break; 31890a96aa3bSJed Brown } 31909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, pp, &pParent, NULL)); 31910a96aa3bSJed Brown } 31920a96aa3bSJed Brown if (c != -1) break; 31930a96aa3bSJed Brown } 31949566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, point, PETSC_TRUE, NULL, &closure)); 31950a96aa3bSJed Brown if (l < closureSize) break; 31960a96aa3bSJed Brown } else { 31970a96aa3bSJed Brown PetscInt supportSize; 31980a96aa3bSJed Brown 31999566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(plex, point, &supportSize)); 32000a96aa3bSJed Brown zerosupportpoint = (PetscBool)(zerosupportpoint || !supportSize); 32010a96aa3bSJed Brown } 32020a96aa3bSJed Brown } 32030a96aa3bSJed Brown if (c < 0) { 32040a96aa3bSJed Brown const char *prefix; 32050a96aa3bSJed Brown PetscBool print = PETSC_FALSE; 32060a96aa3bSJed Brown 32079566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 32089566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, prefix, "-dm_forest_print_label_error", &print, NULL)); 32090a96aa3bSJed Brown if (print) { 32100a96aa3bSJed Brown PetscInt i; 32110a96aa3bSJed Brown 321263a3b9bcSJacob 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)); 321363a3b9bcSJacob 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])); 32140a96aa3bSJed Brown } 32159566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, NULL, &star)); 32160a96aa3bSJed Brown if (zerosupportpoint) continue; 32179371c9d4SSatish Balay else 32189371c9d4SSatish 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"); 32190a96aa3bSJed Brown } 32209566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, NULL, &star)); 32210a96aa3bSJed Brown 32220a96aa3bSJed Brown if (c < cLocalStart) { 32230a96aa3bSJed Brown /* get from the beginning of the ghost layer */ 32240a96aa3bSJed Brown q = &(ghosts[c]); 32250a96aa3bSJed Brown t = (PetscInt)q->p.which_tree; 32260a96aa3bSJed Brown } else if (c < cLocalEnd) { 32270a96aa3bSJed Brown PetscInt lo = 0, hi = num_trees; 32280a96aa3bSJed Brown /* get from local quadrants: have to find the right tree */ 32290a96aa3bSJed Brown 32300a96aa3bSJed Brown c -= cLocalStart; 32310a96aa3bSJed Brown 32320a96aa3bSJed Brown do { 32330a96aa3bSJed Brown p4est_tree_t *tree; 32340a96aa3bSJed Brown 32351dca8a05SBarry Smith PetscCheck(guess >= lo && guess < num_trees && lo < hi, PETSC_COMM_SELF, PETSC_ERR_PLIB, "failed binary search"); 32360a96aa3bSJed Brown tree = &trees[guess]; 32370a96aa3bSJed Brown if (c < tree->quadrants_offset) { 32380a96aa3bSJed Brown hi = guess; 32390a96aa3bSJed Brown } else if (c < tree->quadrants_offset + (PetscInt)tree->quadrants.elem_count) { 32400a96aa3bSJed Brown q = &((p4est_quadrant_t *)tree->quadrants.array)[c - (PetscInt)tree->quadrants_offset]; 32410a96aa3bSJed Brown t = guess; 32420a96aa3bSJed Brown break; 32430a96aa3bSJed Brown } else { 32440a96aa3bSJed Brown lo = guess + 1; 32450a96aa3bSJed Brown } 32460a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 32470a96aa3bSJed Brown } while (1); 32480a96aa3bSJed Brown } else { 32490a96aa3bSJed Brown /* get from the end of the ghost layer */ 32500a96aa3bSJed Brown c -= (cLocalEnd - cLocalStart); 32510a96aa3bSJed Brown 32520a96aa3bSJed Brown q = &(ghosts[c]); 32530a96aa3bSJed Brown t = (PetscInt)q->p.which_tree; 32540a96aa3bSJed Brown } 32550a96aa3bSJed Brown 32560a96aa3bSJed Brown if (l == 0) { /* cell */ 32570a96aa3bSJed Brown if (baseLabel) { 32589566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 32590a96aa3bSJed Brown } else { 32600a96aa3bSJed Brown val = t + cStartBase; 32610a96aa3bSJed Brown } 32629566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32630a96aa3bSJed Brown } else if (l >= 1 && l < 1 + P4EST_FACES) { /* facet */ 32640a96aa3bSJed Brown p4est_quadrant_t nq; 32650a96aa3bSJed Brown int isInside; 32660a96aa3bSJed Brown 32670a96aa3bSJed Brown l = PetscFaceToP4estFace[l - 1]; 3268792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor, (q, l, &nq)); 3269792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq)); 32700a96aa3bSJed Brown if (isInside) { 32710a96aa3bSJed Brown /* this facet is in the interior of a tree, so it inherits the label of the tree */ 32720a96aa3bSJed Brown if (baseLabel) { 32739566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 32740a96aa3bSJed Brown } else { 32750a96aa3bSJed Brown val = t + cStartBase; 32760a96aa3bSJed Brown } 32779566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32780a96aa3bSJed Brown } else { 32790a96aa3bSJed Brown PetscInt f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + l]; 32800a96aa3bSJed Brown 32810a96aa3bSJed Brown if (baseLabel) { 32829566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val)); 32830a96aa3bSJed Brown } else { 32840a96aa3bSJed Brown val = f + fStartBase; 32850a96aa3bSJed Brown } 32869566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32870a96aa3bSJed Brown } 32880a96aa3bSJed Brown #if defined(P4_TO_P8) 32890a96aa3bSJed Brown } else if (l >= 1 + P4EST_FACES && l < 1 + P4EST_FACES + P8EST_EDGES) { /* edge */ 32900a96aa3bSJed Brown p4est_quadrant_t nq; 32910a96aa3bSJed Brown int isInside; 32920a96aa3bSJed Brown 32930a96aa3bSJed Brown l = PetscEdgeToP4estEdge[l - (1 + P4EST_FACES)]; 3294792fecdfSBarry Smith PetscCallP4est(p8est_quadrant_edge_neighbor, (q, l, &nq)); 3295792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq)); 32960a96aa3bSJed Brown if (isInside) { 32970a96aa3bSJed Brown /* this edge is in the interior of a tree, so it inherits the label of the tree */ 32980a96aa3bSJed Brown if (baseLabel) { 32999566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 33000a96aa3bSJed Brown } else { 33010a96aa3bSJed Brown val = t + cStartBase; 33020a96aa3bSJed Brown } 33039566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33040a96aa3bSJed Brown } else { 33050a96aa3bSJed Brown int isOutsideFace; 33060a96aa3bSJed Brown 3307792fecdfSBarry Smith PetscCallP4estReturn(isOutsideFace, p4est_quadrant_is_outside_face, (&nq)); 33080a96aa3bSJed Brown if (isOutsideFace) { 33090a96aa3bSJed Brown PetscInt f; 33100a96aa3bSJed Brown 33110a96aa3bSJed Brown if (nq.x < 0) { 33120a96aa3bSJed Brown f = 0; 33130a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 33140a96aa3bSJed Brown f = 1; 33150a96aa3bSJed Brown } else if (nq.y < 0) { 33160a96aa3bSJed Brown f = 2; 33170a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 33180a96aa3bSJed Brown f = 3; 33190a96aa3bSJed Brown } else if (nq.z < 0) { 33200a96aa3bSJed Brown f = 4; 33210a96aa3bSJed Brown } else { 33220a96aa3bSJed Brown f = 5; 33230a96aa3bSJed Brown } 33240a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 33250a96aa3bSJed Brown if (baseLabel) { 33269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val)); 33270a96aa3bSJed Brown } else { 33280a96aa3bSJed Brown val = f + fStartBase; 33290a96aa3bSJed Brown } 33309566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33310a96aa3bSJed Brown } else { /* the quadrant edge corresponds to the tree edge */ 33320a96aa3bSJed Brown PetscInt e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + l]; 33330a96aa3bSJed Brown 33340a96aa3bSJed Brown if (baseLabel) { 33359566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, e + eStartBase, &val)); 33360a96aa3bSJed Brown } else { 33370a96aa3bSJed Brown val = e + eStartBase; 33380a96aa3bSJed Brown } 33399566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33400a96aa3bSJed Brown } 33410a96aa3bSJed Brown } 33420a96aa3bSJed Brown #endif 33430a96aa3bSJed Brown } else { /* vertex */ 33440a96aa3bSJed Brown p4est_quadrant_t nq; 33450a96aa3bSJed Brown int isInside; 33460a96aa3bSJed Brown 33470a96aa3bSJed Brown #if defined(P4_TO_P8) 33480a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES + P8EST_EDGES)]; 33490a96aa3bSJed Brown #else 33500a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES)]; 33510a96aa3bSJed Brown #endif 3352792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_neighbor, (q, l, &nq)); 3353792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq)); 33540a96aa3bSJed Brown if (isInside) { 33550a96aa3bSJed Brown if (baseLabel) { 33569566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 33570a96aa3bSJed Brown } else { 33580a96aa3bSJed Brown val = t + cStartBase; 33590a96aa3bSJed Brown } 33609566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33610a96aa3bSJed Brown } else { 33620a96aa3bSJed Brown int isOutside; 33630a96aa3bSJed Brown 3364792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p4est_quadrant_is_outside_face, (&nq)); 33650a96aa3bSJed Brown if (isOutside) { 33660a96aa3bSJed Brown PetscInt f = -1; 33670a96aa3bSJed Brown 33680a96aa3bSJed Brown if (nq.x < 0) { 33690a96aa3bSJed Brown f = 0; 33700a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 33710a96aa3bSJed Brown f = 1; 33720a96aa3bSJed Brown } else if (nq.y < 0) { 33730a96aa3bSJed Brown f = 2; 33740a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 33750a96aa3bSJed Brown f = 3; 33760a96aa3bSJed Brown #if defined(P4_TO_P8) 33770a96aa3bSJed Brown } else if (nq.z < 0) { 33780a96aa3bSJed Brown f = 4; 33790a96aa3bSJed Brown } else { 33800a96aa3bSJed Brown f = 5; 33810a96aa3bSJed Brown #endif 33820a96aa3bSJed Brown } 33830a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 33840a96aa3bSJed Brown if (baseLabel) { 33859566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val)); 33860a96aa3bSJed Brown } else { 33870a96aa3bSJed Brown val = f + fStartBase; 33880a96aa3bSJed Brown } 33899566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33900a96aa3bSJed Brown continue; 33910a96aa3bSJed Brown } 33920a96aa3bSJed Brown #if defined(P4_TO_P8) 3393792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p8est_quadrant_is_outside_edge, (&nq)); 33940a96aa3bSJed Brown if (isOutside) { 33950a96aa3bSJed Brown /* outside edge */ 33960a96aa3bSJed Brown PetscInt e = -1; 33970a96aa3bSJed Brown 33980a96aa3bSJed Brown if (nq.x >= 0 && nq.x < P4EST_ROOT_LEN) { 33990a96aa3bSJed Brown if (nq.z < 0) { 34000a96aa3bSJed Brown if (nq.y < 0) { 34010a96aa3bSJed Brown e = 0; 34020a96aa3bSJed Brown } else { 34030a96aa3bSJed Brown e = 1; 34040a96aa3bSJed Brown } 34050a96aa3bSJed Brown } else { 34060a96aa3bSJed Brown if (nq.y < 0) { 34070a96aa3bSJed Brown e = 2; 34080a96aa3bSJed Brown } else { 34090a96aa3bSJed Brown e = 3; 34100a96aa3bSJed Brown } 34110a96aa3bSJed Brown } 34120a96aa3bSJed Brown } else if (nq.y >= 0 && nq.y < P4EST_ROOT_LEN) { 34130a96aa3bSJed Brown if (nq.z < 0) { 34140a96aa3bSJed Brown if (nq.x < 0) { 34150a96aa3bSJed Brown e = 4; 34160a96aa3bSJed Brown } else { 34170a96aa3bSJed Brown e = 5; 34180a96aa3bSJed Brown } 34190a96aa3bSJed Brown } else { 34200a96aa3bSJed Brown if (nq.x < 0) { 34210a96aa3bSJed Brown e = 6; 34220a96aa3bSJed Brown } else { 34230a96aa3bSJed Brown e = 7; 34240a96aa3bSJed Brown } 34250a96aa3bSJed Brown } 34260a96aa3bSJed Brown } else { 34270a96aa3bSJed Brown if (nq.y < 0) { 34280a96aa3bSJed Brown if (nq.x < 0) { 34290a96aa3bSJed Brown e = 8; 34300a96aa3bSJed Brown } else { 34310a96aa3bSJed Brown e = 9; 34320a96aa3bSJed Brown } 34330a96aa3bSJed Brown } else { 34340a96aa3bSJed Brown if (nq.x < 0) { 34350a96aa3bSJed Brown e = 10; 34360a96aa3bSJed Brown } else { 34370a96aa3bSJed Brown e = 11; 34380a96aa3bSJed Brown } 34390a96aa3bSJed Brown } 34400a96aa3bSJed Brown } 34410a96aa3bSJed Brown 34420a96aa3bSJed Brown e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + e]; 34430a96aa3bSJed Brown if (baseLabel) { 34449566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, e + eStartBase, &val)); 34450a96aa3bSJed Brown } else { 34460a96aa3bSJed Brown val = e + eStartBase; 34470a96aa3bSJed Brown } 34489566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 34490a96aa3bSJed Brown continue; 34500a96aa3bSJed Brown } 34510a96aa3bSJed Brown #endif 34520a96aa3bSJed Brown { 34530a96aa3bSJed Brown /* outside vertex: same corner as quadrant corner */ 34540a96aa3bSJed Brown PetscInt v = pforest->topo->conn->tree_to_corner[P4EST_CHILDREN * t + l]; 34550a96aa3bSJed Brown 34560a96aa3bSJed Brown if (baseLabel) { 34579566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, v + vStartBase, &val)); 34580a96aa3bSJed Brown } else { 34590a96aa3bSJed Brown val = v + vStartBase; 34600a96aa3bSJed Brown } 34619566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 34620a96aa3bSJed Brown } 34630a96aa3bSJed Brown } 34640a96aa3bSJed Brown } 34650a96aa3bSJed Brown } 34660a96aa3bSJed Brown next = next->next; 34670a96aa3bSJed Brown } 34683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34690a96aa3bSJed Brown } 34700a96aa3bSJed Brown 3471d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestLabelsFinalize(DM dm, DM plex) 3472d71ae5a4SJacob Faibussowitsch { 34730a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 34740a96aa3bSJed Brown DM adapt; 34750a96aa3bSJed Brown 34760a96aa3bSJed Brown PetscFunctionBegin; 34773ba16761SJacob Faibussowitsch if (pforest->labelsFinalized) PetscFunctionReturn(PETSC_SUCCESS); 34780a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 34799566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm, &adapt)); 34800a96aa3bSJed Brown if (!adapt) { 34810a96aa3bSJed Brown /* Initialize labels from the base dm */ 34829566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsInitialize(dm, plex)); 34830a96aa3bSJed Brown } else { 34840a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1}; 34850a96aa3bSJed Brown PetscSF transferForward, transferBackward, pointSF; 34860a96aa3bSJed Brown PetscInt pStart, pEnd, pStartA, pEndA; 34870a96aa3bSJed Brown PetscInt *values, *adaptValues; 34880a96aa3bSJed Brown DMLabelLink next = adapt->labels; 34890a96aa3bSJed Brown DMLabel adaptLabel; 34900a96aa3bSJed Brown DM adaptPlex; 34910a96aa3bSJed Brown 34929566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm, &adaptLabel)); 34939566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(adapt, &adaptPlex)); 34949566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(adapt, dm, dofPerDim, &transferForward, &transferBackward)); 34959566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &pStart, &pEnd)); 34969566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(adaptPlex, &pStartA, &pEndA)); 34979566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &values, pEndA - pStartA, &adaptValues)); 34989566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plex, &pointSF)); 34990a96aa3bSJed Brown if (PetscDefined(USE_DEBUG)) { 35000a96aa3bSJed Brown PetscInt p; 35010a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) adaptValues[p - pStartA] = -1; 35020a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p - pStart] = -2; 35030a96aa3bSJed Brown if (transferForward) { 35049566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 35059566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 35060a96aa3bSJed Brown } 35070a96aa3bSJed Brown if (transferBackward) { 350857168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 350957168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 35100a96aa3bSJed Brown } 35110a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 35120a96aa3bSJed Brown PetscInt q = p, parent; 35130a96aa3bSJed Brown 35149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35150a96aa3bSJed Brown while (parent != q) { 35160a96aa3bSJed Brown if (values[parent] == -2) values[parent] = values[q]; 35170a96aa3bSJed Brown q = parent; 35189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35190a96aa3bSJed Brown } 35200a96aa3bSJed Brown } 352157168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, values, values, MPI_MAX)); 352257168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, values, values, MPI_MAX)); 35239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 35249566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 3525ad540459SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCheck(values[p - pStart] != -2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "uncovered point %" PetscInt_FMT, p); 35260a96aa3bSJed Brown } 35270a96aa3bSJed Brown while (next) { 35280a96aa3bSJed Brown DMLabel nextLabel = next->label; 35290a96aa3bSJed Brown const char *name; 35300a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 35310a96aa3bSJed Brown DMLabel label; 35320a96aa3bSJed Brown PetscInt p; 35330a96aa3bSJed Brown 35349566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)nextLabel, &name)); 35359566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 35360a96aa3bSJed Brown if (isDepth) { 35370a96aa3bSJed Brown next = next->next; 35380a96aa3bSJed Brown continue; 35390a96aa3bSJed Brown } 35409566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 35410a96aa3bSJed Brown if (isCellType) { 35420a96aa3bSJed Brown next = next->next; 35430a96aa3bSJed Brown continue; 35440a96aa3bSJed Brown } 35459566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 35460a96aa3bSJed Brown if (isGhost) { 35470a96aa3bSJed Brown next = next->next; 35480a96aa3bSJed Brown continue; 35490a96aa3bSJed Brown } 35509566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 35510a96aa3bSJed Brown if (isVTK) { 35520a96aa3bSJed Brown next = next->next; 35530a96aa3bSJed Brown continue; 35540a96aa3bSJed Brown } 35550a96aa3bSJed Brown if (nextLabel == adaptLabel) { 35560a96aa3bSJed Brown next = next->next; 35570a96aa3bSJed Brown continue; 35580a96aa3bSJed Brown } 35590a96aa3bSJed Brown /* label was created earlier */ 35609566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 356148a46eb9SPierre Jolivet for (p = pStartA; p < pEndA; p++) PetscCall(DMLabelGetValue(nextLabel, p, &adaptValues[p])); 35620a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p] = PETSC_MIN_INT; 35630a96aa3bSJed Brown 35641baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastBegin(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 356557168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceBegin(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 35661baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastEnd(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 356757168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceEnd(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 35680a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 35690a96aa3bSJed Brown PetscInt q = p, parent; 35700a96aa3bSJed Brown 35719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35720a96aa3bSJed Brown while (parent != q) { 35730a96aa3bSJed Brown if (values[parent] == PETSC_MIN_INT) values[parent] = values[q]; 35740a96aa3bSJed Brown q = parent; 35759566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35760a96aa3bSJed Brown } 35770a96aa3bSJed Brown } 357857168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, values, values, MPI_MAX)); 357957168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, values, values, MPI_MAX)); 35809566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 35819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 35820a96aa3bSJed Brown 358348a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMLabelSetValue(label, p, values[p])); 35840a96aa3bSJed Brown next = next->next; 35850a96aa3bSJed Brown } 35869566063dSJacob Faibussowitsch PetscCall(PetscFree2(values, adaptValues)); 35879566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferForward)); 35889566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferBackward)); 35890a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 35900a96aa3bSJed Brown } 35913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35920a96aa3bSJed Brown } 35930a96aa3bSJed Brown 3594d71ae5a4SJacob Faibussowitsch 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) 3595d71ae5a4SJacob Faibussowitsch { 35960a96aa3bSJed Brown PetscInt closureSize, c, coordStart, coordEnd, coordDim; 35970a96aa3bSJed Brown PetscInt *closure = NULL; 35980a96aa3bSJed Brown PetscSection coordSec; 35990a96aa3bSJed Brown 36000a96aa3bSJed Brown PetscFunctionBegin; 36019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &coordSec)); 36029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec, &coordStart, &coordEnd)); 36039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex, &coordDim)); 36049566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, cell, PETSC_TRUE, &closureSize, &closure)); 36050a96aa3bSJed Brown for (c = 0; c < closureSize; c++) { 36060a96aa3bSJed Brown PetscInt point = closure[2 * c]; 36070a96aa3bSJed Brown 36080a96aa3bSJed Brown if (point >= coordStart && point < coordEnd) { 36090a96aa3bSJed Brown PetscInt dof, off; 36100a96aa3bSJed Brown PetscInt nCoords, i; 36119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec, point, &dof)); 361208401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Did not understand coordinate layout"); 36130a96aa3bSJed Brown nCoords = dof / coordDim; 36149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec, point, &off)); 36150a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 36160a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 36170a96aa3bSJed Brown double coordP4est[3] = {0.}; 36180a96aa3bSJed Brown double coordP4estMapped[3] = {0.}; 36190a96aa3bSJed Brown PetscInt j; 36200a96aa3bSJed Brown PetscReal treeCoords[P4EST_CHILDREN][3] = {{0.}}; 36210a96aa3bSJed Brown PetscReal eta[3] = {0.}; 36220a96aa3bSJed Brown PetscInt numRounds = 10; 36230a96aa3bSJed Brown PetscReal coordGuess[3] = {0.}; 36240a96aa3bSJed Brown 36250a96aa3bSJed Brown eta[0] = (PetscReal)q->x / (PetscReal)P4EST_ROOT_LEN; 36260a96aa3bSJed Brown eta[1] = (PetscReal)q->y / (PetscReal)P4EST_ROOT_LEN; 36270a96aa3bSJed Brown #if defined(P4_TO_P8) 36280a96aa3bSJed Brown eta[2] = (PetscReal)q->z / (PetscReal)P4EST_ROOT_LEN; 36290a96aa3bSJed Brown #endif 36300a96aa3bSJed Brown 36310a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 36320a96aa3bSJed Brown PetscInt k; 36330a96aa3bSJed Brown 36340a96aa3bSJed Brown for (k = 0; k < 3; k++) treeCoords[j][k] = conn->vertices[3 * conn->tree_to_vertex[P4EST_CHILDREN * t + j] + k]; 36350a96aa3bSJed Brown } 36360a96aa3bSJed Brown 36370a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 36380a96aa3bSJed Brown PetscInt k; 36390a96aa3bSJed Brown PetscReal prod = 1.; 36400a96aa3bSJed Brown 36410a96aa3bSJed Brown for (k = 0; k < P4EST_DIM; k++) prod *= (j & (1 << k)) ? eta[k] : (1. - eta[k]); 36420a96aa3bSJed Brown for (k = 0; k < 3; k++) coordGuess[k] += prod * treeCoords[j][k]; 36430a96aa3bSJed Brown } 36440a96aa3bSJed Brown 36450a96aa3bSJed Brown for (j = 0; j < numRounds; j++) { 36460a96aa3bSJed Brown PetscInt dir; 36470a96aa3bSJed Brown 36480a96aa3bSJed Brown for (dir = 0; dir < P4EST_DIM; dir++) { 36490a96aa3bSJed Brown PetscInt k; 36500a96aa3bSJed Brown PetscReal diff[3]; 36510a96aa3bSJed Brown PetscReal dXdeta[3] = {0.}; 36520a96aa3bSJed Brown PetscReal rhs, scale, update; 36530a96aa3bSJed Brown 36540a96aa3bSJed Brown for (k = 0; k < 3; k++) diff[k] = coordP4est[k] - coordGuess[k]; 36550a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 36560a96aa3bSJed Brown PetscInt l; 36570a96aa3bSJed Brown PetscReal prod = 1.; 36580a96aa3bSJed Brown 36590a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) { 36600a96aa3bSJed Brown if (l == dir) { 36610a96aa3bSJed Brown prod *= (k & (1 << l)) ? 1. : -1.; 36620a96aa3bSJed Brown } else { 36630a96aa3bSJed Brown prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 36640a96aa3bSJed Brown } 36650a96aa3bSJed Brown } 36660a96aa3bSJed Brown for (l = 0; l < 3; l++) dXdeta[l] += prod * treeCoords[k][l]; 36670a96aa3bSJed Brown } 36680a96aa3bSJed Brown rhs = 0.; 36690a96aa3bSJed Brown scale = 0; 36700a96aa3bSJed Brown for (k = 0; k < 3; k++) { 36710a96aa3bSJed Brown rhs += diff[k] * dXdeta[k]; 36720a96aa3bSJed Brown scale += dXdeta[k] * dXdeta[k]; 36730a96aa3bSJed Brown } 36740a96aa3bSJed Brown update = rhs / scale; 36750a96aa3bSJed Brown eta[dir] += update; 36760a96aa3bSJed Brown eta[dir] = PetscMin(eta[dir], 1.); 36770a96aa3bSJed Brown eta[dir] = PetscMax(eta[dir], 0.); 36780a96aa3bSJed Brown 36790a96aa3bSJed Brown coordGuess[0] = coordGuess[1] = coordGuess[2] = 0.; 36800a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 36810a96aa3bSJed Brown PetscInt l; 36820a96aa3bSJed Brown PetscReal prod = 1.; 36830a96aa3bSJed Brown 36840a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 36850a96aa3bSJed Brown for (l = 0; l < 3; l++) coordGuess[l] += prod * treeCoords[k][l]; 36860a96aa3bSJed Brown } 36870a96aa3bSJed Brown } 36880a96aa3bSJed Brown } 36890a96aa3bSJed Brown for (j = 0; j < 3; j++) coordP4est[j] = (double)eta[j]; 36900a96aa3bSJed Brown 36910a96aa3bSJed Brown if (geom) { 36920a96aa3bSJed Brown (geom->X)(geom, t, coordP4est, coordP4estMapped); 36930a96aa3bSJed Brown for (j = 0; j < coordDim; j++) coord[j] = (PetscScalar)coordP4estMapped[j]; 36940a96aa3bSJed Brown } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded"); 36950a96aa3bSJed Brown } 36960a96aa3bSJed Brown } 36970a96aa3bSJed Brown } 36989566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, cell, PETSC_TRUE, &closureSize, &closure)); 36993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 37000a96aa3bSJed Brown } 37010a96aa3bSJed Brown 3702d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestMapCoordinates(DM dm, DM plex) 3703d71ae5a4SJacob Faibussowitsch { 37040a96aa3bSJed Brown DM_Forest *forest; 37050a96aa3bSJed Brown DM_Forest_pforest *pforest; 37060a96aa3bSJed Brown p4est_geometry_t *geom; 37070a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd; 37080a96aa3bSJed Brown Vec coordLocalVec; 37090a96aa3bSJed Brown PetscScalar *coords; 37100a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 37110a96aa3bSJed Brown p4est_tree_t *trees; 37120a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *); 37130a96aa3bSJed Brown void *mapCtx; 37140a96aa3bSJed Brown 37150a96aa3bSJed Brown PetscFunctionBegin; 37160a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 37170a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 37180a96aa3bSJed Brown geom = pforest->topo->geom; 37199566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx)); 37203ba16761SJacob Faibussowitsch if (!geom && !map) PetscFunctionReturn(PETSC_SUCCESS); 37219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(plex, &coordLocalVec)); 37229566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordLocalVec, &coords)); 37230a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 37240a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 37250a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 37260a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 37270a96aa3bSJed Brown trees = (p4est_tree_t *)pforest->forest->trees->array; 37280a96aa3bSJed Brown if (map) { /* apply the map directly to the existing coordinates */ 37290a96aa3bSJed Brown PetscSection coordSec; 37300a96aa3bSJed Brown PetscInt coordStart, coordEnd, p, coordDim, p4estCoordDim, cStart, cEnd, cEndInterior; 37310a96aa3bSJed Brown DM base; 37320a96aa3bSJed Brown 37339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 37342827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(plex, DM_POLYTOPE_FV_GHOST, &cEndInterior, NULL)); 37350a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 37369566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 37379566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &coordSec)); 37389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec, &coordStart, &coordEnd)); 37399566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex, &coordDim)); 37400a96aa3bSJed Brown p4estCoordDim = PetscMin(coordDim, 3); 37410a96aa3bSJed Brown for (p = coordStart; p < coordEnd; p++) { 37420a96aa3bSJed Brown PetscInt *star = NULL, starSize; 37430a96aa3bSJed Brown PetscInt dof, off, cell = -1, coarsePoint = -1; 37440a96aa3bSJed Brown PetscInt nCoords, i; 37459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec, p, &dof)); 374608401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Did not understand coordinate layout"); 37470a96aa3bSJed Brown nCoords = dof / coordDim; 37489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec, p, &off)); 37499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star)); 37500a96aa3bSJed Brown for (i = 0; i < starSize; i++) { 37510a96aa3bSJed Brown PetscInt point = star[2 * i]; 37520a96aa3bSJed Brown 37530a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 37540a96aa3bSJed Brown cell = point; 37550a96aa3bSJed Brown break; 37560a96aa3bSJed Brown } 37570a96aa3bSJed Brown } 37589566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star)); 37590a96aa3bSJed Brown if (cell >= 0) { 37600a96aa3bSJed Brown if (cell < cLocalStart) { 37610a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37620a96aa3bSJed Brown 37630a96aa3bSJed Brown coarsePoint = ghosts[cell].p.which_tree; 37640a96aa3bSJed Brown } else if (cell < cLocalEnd) { 37650a96aa3bSJed Brown cell -= cLocalStart; 37660a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 37670a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 37680a96aa3bSJed Brown 37690a96aa3bSJed Brown if (cell >= tree->quadrants_offset && (size_t)cell < tree->quadrants_offset + tree->quadrants.elem_count) { 37700a96aa3bSJed Brown coarsePoint = t; 37710a96aa3bSJed Brown break; 37720a96aa3bSJed Brown } 37730a96aa3bSJed Brown } 37740a96aa3bSJed Brown } else { 37750a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37760a96aa3bSJed Brown 37770a96aa3bSJed Brown coarsePoint = ghosts[cell - cLocalEnd].p.which_tree; 37780a96aa3bSJed Brown } 37790a96aa3bSJed Brown } 37800a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 37810a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 37820a96aa3bSJed Brown PetscReal coordP4est[3] = {0.}; 37830a96aa3bSJed Brown PetscReal coordP4estMapped[3] = {0.}; 37840a96aa3bSJed Brown PetscInt j; 37850a96aa3bSJed Brown 37860a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coordP4est[j] = PetscRealPart(coord[j]); 37879566063dSJacob Faibussowitsch PetscCall((map)(base, coarsePoint, p4estCoordDim, coordP4est, coordP4estMapped, mapCtx)); 37880a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coord[j] = (PetscScalar)coordP4estMapped[j]; 37890a96aa3bSJed Brown } 37900a96aa3bSJed Brown } 37910a96aa3bSJed Brown } else { /* we have to transform coordinates back to the unit cube (where geom is defined), and then apply geom */ 37920a96aa3bSJed Brown PetscInt cStart, cEnd, cEndInterior; 37930a96aa3bSJed Brown 37949566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 37952827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(plex, DM_POLYTOPE_FV_GHOST, &cEndInterior, NULL)); 37960a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 37970a96aa3bSJed Brown if (cLocalStart > 0) { 37980a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37990a96aa3bSJed Brown PetscInt count; 38000a96aa3bSJed Brown 38010a96aa3bSJed Brown for (count = 0; count < cLocalStart; count++) { 38020a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count]; 38030a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 38040a96aa3bSJed Brown 38059566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count, quad, t, pforest->topo->conn, coords)); 38060a96aa3bSJed Brown } 38070a96aa3bSJed Brown } 38080a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 38090a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 38100a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset, i; 38110a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 38120a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 38130a96aa3bSJed Brown 38140a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 38150a96aa3bSJed Brown PetscInt count = i + offset; 38160a96aa3bSJed Brown 38179566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count, &quads[i], t, pforest->topo->conn, coords)); 38180a96aa3bSJed Brown } 38190a96aa3bSJed Brown } 38200a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 38210a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 38220a96aa3bSJed Brown PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count; 38230a96aa3bSJed Brown PetscInt count; 38240a96aa3bSJed Brown 38250a96aa3bSJed Brown for (count = 0; count < numGhosts - cLocalStart; count++) { 38260a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 38270a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 38280a96aa3bSJed Brown 38299566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count + cLocalEnd, quad, t, pforest->topo->conn, coords)); 38300a96aa3bSJed Brown } 38310a96aa3bSJed Brown } 38320a96aa3bSJed Brown } 38339566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordLocalVec, &coords)); 38343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38350a96aa3bSJed Brown } 38360a96aa3bSJed Brown 3837d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestQuadrantIsInterior(p4est_quadrant_t *quad, PetscBool *is_interior) 3838d71ae5a4SJacob Faibussowitsch { 3839852b71a7SToby Isaac PetscFunctionBegin; 3840852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level); 3841852b71a7SToby Isaac if ((quad->x > 0) && (quad->x + h < P4EST_ROOT_LEN) 3842852b71a7SToby Isaac #ifdef P4_TO_P8 3843852b71a7SToby Isaac && (quad->z > 0) && (quad->z + h < P4EST_ROOT_LEN) 3844852b71a7SToby Isaac #endif 3845852b71a7SToby Isaac && (quad->y > 0) && (quad->y + h < P4EST_ROOT_LEN)) { 3846852b71a7SToby Isaac *is_interior = PETSC_TRUE; 3847852b71a7SToby Isaac } else { 3848852b71a7SToby Isaac *is_interior = PETSC_FALSE; 3849852b71a7SToby Isaac } 38503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3851852b71a7SToby Isaac } 3852852b71a7SToby Isaac 3853852b71a7SToby Isaac /* We always use DG coordinates with p4est: if they do not match the vertex 3854852b71a7SToby Isaac coordinates, add space for them in the section */ 3855d71ae5a4SJacob Faibussowitsch 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) 3856d71ae5a4SJacob Faibussowitsch { 3857852b71a7SToby Isaac PetscBool is_interior; 3858852b71a7SToby Isaac 3859852b71a7SToby Isaac PetscFunctionBegin; 3860852b71a7SToby Isaac PetscCall(PforestQuadrantIsInterior(quad, &is_interior)); 3861852b71a7SToby Isaac if (is_interior) { // quads in the interior of a coarse cell can't touch periodic interfaces 3862852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3863852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3864852b71a7SToby Isaac } else { 3865852b71a7SToby Isaac PetscInt cSize; 3866852b71a7SToby Isaac PetscScalar *values = NULL; 3867852b71a7SToby Isaac PetscBool same_coords = PETSC_TRUE; 3868852b71a7SToby Isaac 3869852b71a7SToby Isaac PetscCall(DMPlexVecGetClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3870852b71a7SToby Isaac PetscAssert(cSize == cDim * P4EST_CHILDREN, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected closure size"); 3871852b71a7SToby Isaac for (int c = 0; c < P4EST_CHILDREN; c++) { 3872852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3873852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level); 3874852b71a7SToby Isaac double corner_coords[3]; 3875852b71a7SToby Isaac double vert_coords[3]; 3876852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 3877852b71a7SToby Isaac 3878ad540459SPierre Jolivet for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) vert_coords[d] = PetscRealPart(values[c * cDim + d]); 3879852b71a7SToby Isaac 3880852b71a7SToby Isaac quad_coords[0] = quad->x; 3881852b71a7SToby Isaac quad_coords[1] = quad->y; 3882852b71a7SToby Isaac #ifdef P4_TO_P8 3883852b71a7SToby Isaac quad_coords[2] = quad->z; 3884852b71a7SToby Isaac #endif 3885ad540459SPierre Jolivet for (int d = 0; d < 3; d++) quad_coords[d] += (corner & (1 << d)) ? h : 0; 3886852b71a7SToby Isaac #ifndef P4_TO_P8 3887648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 3888852b71a7SToby Isaac #else 3889648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 3890852b71a7SToby Isaac #endif 3891852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) { 3892852b71a7SToby Isaac if (fabs(vert_coords[d] - corner_coords[d]) > PETSC_SMALL) { 3893852b71a7SToby Isaac same_coords = PETSC_FALSE; 3894852b71a7SToby Isaac break; 3895852b71a7SToby Isaac } 3896852b71a7SToby Isaac } 3897852b71a7SToby Isaac } 3898852b71a7SToby Isaac if (same_coords) { 3899852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3900852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3901852b71a7SToby Isaac } else { 3902852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, cSize)); 3903852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, cSize)); 3904852b71a7SToby Isaac } 3905852b71a7SToby Isaac PetscCall(DMPlexVecRestoreClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3906852b71a7SToby Isaac } 39073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3908852b71a7SToby Isaac } 3909852b71a7SToby Isaac 3910d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestLocalizeCell(DM plex, PetscInt cDim, DM_Forest_pforest *pforest, PetscSection newSection, PetscInt cell, PetscInt coarsePoint, p4est_quadrant_t *quad, PetscScalar coords[]) 3911d71ae5a4SJacob Faibussowitsch { 3912852b71a7SToby Isaac PetscInt cdof, off; 3913852b71a7SToby Isaac 3914852b71a7SToby Isaac PetscFunctionBegin; 3915852b71a7SToby Isaac PetscCall(PetscSectionGetDof(newSection, cell, &cdof)); 39163ba16761SJacob Faibussowitsch if (!cdof) PetscFunctionReturn(PETSC_SUCCESS); 3917852b71a7SToby Isaac 3918852b71a7SToby Isaac PetscCall(PetscSectionGetOffset(newSection, cell, &off)); 3919852b71a7SToby Isaac for (PetscInt c = 0, pos = off; c < P4EST_CHILDREN; c++) { 3920852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3921852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level); 3922852b71a7SToby Isaac double corner_coords[3]; 3923852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 3924852b71a7SToby Isaac 3925852b71a7SToby Isaac quad_coords[0] = quad->x; 3926852b71a7SToby Isaac quad_coords[1] = quad->y; 3927852b71a7SToby Isaac #ifdef P4_TO_P8 3928852b71a7SToby Isaac quad_coords[2] = quad->z; 3929852b71a7SToby Isaac #endif 3930ad540459SPierre Jolivet for (int d = 0; d < 3; d++) quad_coords[d] += (corner & (1 << d)) ? h : 0; 3931852b71a7SToby Isaac #ifndef P4_TO_P8 3932648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 3933852b71a7SToby Isaac #else 3934648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 3935852b71a7SToby Isaac #endif 3936ad540459SPierre Jolivet for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) coords[pos++] = corner_coords[d]; 3937ad540459SPierre Jolivet for (PetscInt d = PetscMin(cDim, 3); d < cDim; d++) coords[pos++] = 0.; 3938852b71a7SToby Isaac } 39393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3940852b71a7SToby Isaac } 3941852b71a7SToby Isaac 3942d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestLocalizeCoordinates(DM dm, DM plex) 3943d71ae5a4SJacob Faibussowitsch { 39440a96aa3bSJed Brown DM_Forest *forest; 39450a96aa3bSJed Brown DM_Forest_pforest *pforest; 39466858538eSMatthew G. Knepley DM base, cdm, cdmCell; 3947852b71a7SToby Isaac Vec cVec, cVecOld; 3948852b71a7SToby Isaac PetscSection oldSection, newSection; 39490a96aa3bSJed Brown PetscScalar *coords2; 39506858538eSMatthew G. Knepley const PetscReal *L; 39510a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, coarsePoint; 3952852b71a7SToby Isaac PetscInt cDim, newStart, newEnd; 3953852b71a7SToby Isaac PetscInt v, vStart, vEnd, cp, cStart, cEnd, cEndInterior; 39540a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 39550a96aa3bSJed Brown p4est_tree_t *trees; 39566858538eSMatthew G. Knepley PetscBool baseLocalized = PETSC_FALSE; 39570a96aa3bSJed Brown 39580a96aa3bSJed Brown PetscFunctionBegin; 39594fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, NULL, NULL, &L)); 39600a96aa3bSJed Brown /* we localize on all cells if we don't have a base DM or the base DM coordinates have not been localized */ 39619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cDim)); 39629566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 39636858538eSMatthew G. Knepley if (base) PetscCall(DMGetCoordinatesLocalized(base, &baseLocalized)); 39640a96aa3bSJed Brown if (!baseLocalized) base = NULL; 39653ba16761SJacob Faibussowitsch if (!baseLocalized && !L) PetscFunctionReturn(PETSC_SUCCESS); 39669566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &newStart, &newEnd)); 39670a96aa3bSJed Brown 39689566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newSection)); 39699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(newSection, 1)); 39709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(newSection, 0, cDim)); 39719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSection, newStart, newEnd)); 39720a96aa3bSJed Brown 39739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &oldSection)); 39749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd)); 3975852b71a7SToby Isaac PetscCall(DMGetCoordinatesLocal(plex, &cVecOld)); 39760a96aa3bSJed Brown 39770a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 39780a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 39790a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 39800a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 39810a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 39820a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 39830a96aa3bSJed Brown trees = (p4est_tree_t *)pforest->forest->trees->array; 39840a96aa3bSJed Brown 39859566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 39862827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(plex, DM_POLYTOPE_FV_GHOST, &cEndInterior, NULL)); 39870a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 3988852b71a7SToby Isaac cp = 0; 39890a96aa3bSJed Brown if (cLocalStart > 0) { 39900a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 3991852b71a7SToby Isaac PetscInt cell; 39920a96aa3bSJed Brown 3993852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 3994852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 3995852b71a7SToby Isaac 39960a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 3997852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 39980a96aa3bSJed Brown } 39990a96aa3bSJed Brown } 40000a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 40010a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 40020a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 40030a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 4004852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 40050a96aa3bSJed Brown PetscInt i; 40060a96aa3bSJed Brown 40070a96aa3bSJed Brown if (!numQuads) continue; 40080a96aa3bSJed Brown coarsePoint = t; 4009852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 4010852b71a7SToby Isaac PetscInt cell = i + offset; 4011852b71a7SToby Isaac p4est_quadrant_t *quad = &quads[i]; 40120a96aa3bSJed Brown 4013852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 40140a96aa3bSJed Brown } 40150a96aa3bSJed Brown } 40160a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 40170a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 40180a96aa3bSJed Brown PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count; 40190a96aa3bSJed Brown PetscInt count; 40200a96aa3bSJed Brown 4021852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 40220a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 40230a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 4024852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 40250a96aa3bSJed Brown 4026852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 40270a96aa3bSJed Brown } 40280a96aa3bSJed Brown } 4029852b71a7SToby Isaac PetscAssert(cp == cEnd - cStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected number of fine cells %" PetscInt_FMT " != %" PetscInt_FMT, cp, cEnd - cStart); 40300a96aa3bSJed Brown 40319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSection)); 40326858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(plex, &cdm)); 40336858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 40346858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(plex, cdmCell)); 40356858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 40366858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(plex, cDim, newSection)); 40379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &v)); 40389566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &cVec)); 40399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)cVec, "coordinates")); 40409566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(cVec, cDim)); 40419566063dSJacob Faibussowitsch PetscCall(VecSetSizes(cVec, v, PETSC_DETERMINE)); 40429566063dSJacob Faibussowitsch PetscCall(VecSetType(cVec, VECSTANDARD)); 40439566063dSJacob Faibussowitsch PetscCall(VecSet(cVec, PETSC_MIN_REAL)); 40440a96aa3bSJed Brown 40450a96aa3bSJed Brown /* Localize coordinates on cells if needed */ 40466858538eSMatthew G. Knepley PetscCall(VecGetArray(cVec, &coords2)); 4047852b71a7SToby Isaac cp = 0; 4048852b71a7SToby Isaac if (cLocalStart > 0) { 4049852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 4050852b71a7SToby Isaac PetscInt cell; 4051852b71a7SToby Isaac 4052852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 4053852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 4054852b71a7SToby Isaac 4055852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 4056852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 4057852b71a7SToby Isaac } 4058852b71a7SToby Isaac } 40590a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 40600a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 40610a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 40620a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 4063852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 4064852b71a7SToby Isaac PetscInt i; 40650a96aa3bSJed Brown 40660a96aa3bSJed Brown if (!numQuads) continue; 4067852b71a7SToby Isaac coarsePoint = t; 4068852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 4069852b71a7SToby Isaac PetscInt cell = i + offset; 40700a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[i]; 40710a96aa3bSJed Brown 4072852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 4073852b71a7SToby Isaac } 4074852b71a7SToby Isaac } 4075852b71a7SToby Isaac if (cLocalEnd - cLocalStart < cEnd - cStart) { 4076852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 4077852b71a7SToby Isaac PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count; 4078852b71a7SToby Isaac PetscInt count; 40790a96aa3bSJed Brown 4080852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 4081852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 4082852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 4083852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 40840a96aa3bSJed Brown 4085852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 40860a96aa3bSJed Brown } 40870a96aa3bSJed Brown } 40889566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cVec, &coords2)); 40896858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(plex, cVec)); 40909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cVec)); 40919566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newSection)); 40923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40930a96aa3bSJed Brown } 40940a96aa3bSJed Brown 40950a96aa3bSJed Brown #define DMForestClearAdaptivityForest_pforest _append_pforest(DMForestClearAdaptivityForest) 4096d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestClearAdaptivityForest_pforest(DM dm) 4097d71ae5a4SJacob Faibussowitsch { 40980a96aa3bSJed Brown DM_Forest *forest; 40990a96aa3bSJed Brown DM_Forest_pforest *pforest; 41000a96aa3bSJed Brown 41010a96aa3bSJed Brown PetscFunctionBegin; 41020a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 41030a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 41049566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&(pforest->pointAdaptToSelfSF))); 41059566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&(pforest->pointSelfToAdaptSF))); 41069566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 41079566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 41083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41090a96aa3bSJed Brown } 41100a96aa3bSJed Brown 4111d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMConvert_pforest_plex(DM dm, DMType newtype, DM *plex) 4112d71ae5a4SJacob Faibussowitsch { 41130a96aa3bSJed Brown DM_Forest *forest; 41140a96aa3bSJed Brown DM_Forest_pforest *pforest; 41150a96aa3bSJed Brown DM refTree, newPlex, base; 41160a96aa3bSJed Brown PetscInt adjDim, adjCodim, coordDim; 41170a96aa3bSJed Brown MPI_Comm comm; 41180a96aa3bSJed Brown PetscBool isPforest; 41190a96aa3bSJed Brown PetscInt dim; 41200a96aa3bSJed Brown PetscInt overlap; 41210a96aa3bSJed Brown p4est_connect_type_t ctype; 41220a96aa3bSJed Brown p4est_locidx_t first_local_quad = -1; 41230a96aa3bSJed Brown sc_array_t *points_per_dim, *cone_sizes, *cones, *cone_orientations, *coords, *children, *parents, *childids, *leaves, *remotes; 41240a96aa3bSJed Brown PetscSection parentSection; 41250a96aa3bSJed Brown PetscSF pointSF; 41260a96aa3bSJed Brown size_t zz, count; 41270a96aa3bSJed Brown PetscInt pStart, pEnd; 41280a96aa3bSJed Brown DMLabel ghostLabelBase = NULL; 41290a96aa3bSJed Brown 41300a96aa3bSJed Brown PetscFunctionBegin; 41310a96aa3bSJed Brown 41320a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41330a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 41349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPFOREST, &isPforest)); 413528b400f6SJacob Faibussowitsch PetscCheck(isPforest, comm, PETSC_ERR_ARG_WRONG, "Expected DM type %s, got %s", DMPFOREST, ((PetscObject)dm)->type_name); 41369566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 413763a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM, comm, PETSC_ERR_ARG_WRONG, "Expected DM dimension %d, got %" PetscInt_FMT, P4EST_DIM, dim); 41380a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 41390a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 41409566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 414148a46eb9SPierre Jolivet if (base) PetscCall(DMGetLabel(base, "ghost", &ghostLabelBase)); 41420a96aa3bSJed Brown if (!pforest->plex) { 41430a96aa3bSJed Brown PetscMPIInt size; 41440a96aa3bSJed Brown 41459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 41469566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &newPlex)); 41479566063dSJacob Faibussowitsch PetscCall(DMSetType(newPlex, DMPLEX)); 41489566063dSJacob Faibussowitsch PetscCall(DMSetMatType(newPlex, dm->mattype)); 41490a96aa3bSJed Brown /* share labels */ 41509566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, newPlex, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 41519566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyDimension(dm, &adjDim)); 41529566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyCodimension(dm, &adjCodim)); 41539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim)); 41540a96aa3bSJed Brown if (adjDim == 0) { 41550a96aa3bSJed Brown ctype = P4EST_CONNECT_FULL; 41560a96aa3bSJed Brown } else if (adjCodim == 1) { 41570a96aa3bSJed Brown ctype = P4EST_CONNECT_FACE; 41580a96aa3bSJed Brown #if defined(P4_TO_P8) 41590a96aa3bSJed Brown } else if (adjDim == 1) { 41600a96aa3bSJed Brown ctype = P8EST_CONNECT_EDGE; 41610a96aa3bSJed Brown #endif 41620a96aa3bSJed Brown } else { 416363a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid adjacency dimension %" PetscInt_FMT, adjDim); 41640a96aa3bSJed Brown } 416563a3b9bcSJacob 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); 41669566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 416760667520SVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(newPlex, NULL, overlap)); 41680a96aa3bSJed Brown 41690a96aa3bSJed Brown points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 41700a96aa3bSJed Brown cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 41710a96aa3bSJed Brown cones = sc_array_new(sizeof(p4est_locidx_t)); 41720a96aa3bSJed Brown cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 41730a96aa3bSJed Brown coords = sc_array_new(3 * sizeof(double)); 41740a96aa3bSJed Brown children = sc_array_new(sizeof(p4est_locidx_t)); 41750a96aa3bSJed Brown parents = sc_array_new(sizeof(p4est_locidx_t)); 41760a96aa3bSJed Brown childids = sc_array_new(sizeof(p4est_locidx_t)); 41770a96aa3bSJed Brown leaves = sc_array_new(sizeof(p4est_locidx_t)); 41780a96aa3bSJed Brown remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 41790a96aa3bSJed Brown 4180792fecdfSBarry 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)); 41810a96aa3bSJed Brown 41820a96aa3bSJed Brown pforest->cLocalStart = (PetscInt)first_local_quad; 41830a96aa3bSJed Brown pforest->cLocalEnd = pforest->cLocalStart + (PetscInt)pforest->forest->local_num_quadrants; 41849566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 41859566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 41869566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 41879566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 41889566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, coordDim)); 41899566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(children)); 41909566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(parents)); 41919566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(childids)); 41929566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(leaves)); 41939566063dSJacob Faibussowitsch PetscCall(locidx_pair_to_PetscSFNode(remotes)); 41940a96aa3bSJed Brown 41959566063dSJacob Faibussowitsch PetscCall(DMSetDimension(newPlex, P4EST_DIM)); 41969566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(newPlex, coordDim)); 41979566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(newPlex, P4EST_DIM - 1)); 41989566063dSJacob 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)); 41999566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(newPlex)); 42009566063dSJacob Faibussowitsch PetscCall(DMCreateReferenceTree_pforest(comm, &refTree)); 42019566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlex, refTree)); 42029566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &parentSection)); 42039566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(newPlex, &pStart, &pEnd)); 42049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd)); 42050a96aa3bSJed Brown count = children->elem_count; 42060a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 42070a96aa3bSJed Brown PetscInt child = *((PetscInt *)sc_array_index(children, zz)); 42080a96aa3bSJed Brown 42099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(parentSection, child, 1)); 42100a96aa3bSJed Brown } 42119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 42129566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(newPlex, parentSection, (PetscInt *)parents->array, (PetscInt *)childids->array)); 42139566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 42149566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &pointSF)); 42150a96aa3bSJed Brown /* 42160a96aa3bSJed Brown These arrays defining the sf are from the p4est library, but the code there shows the leaves being populated in increasing order. 42170a96aa3bSJed Brown https://gitlab.com/petsc/petsc/merge_requests/2248#note_240186391 42180a96aa3bSJed Brown */ 42199566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(pointSF, pEnd - pStart, (PetscInt)leaves->elem_count, (PetscInt *)leaves->array, PETSC_COPY_VALUES, (PetscSFNode *)remotes->array, PETSC_COPY_VALUES)); 42209566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(newPlex, pointSF)); 42219566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 42220a96aa3bSJed Brown { 42230a96aa3bSJed Brown DM coordDM; 42240a96aa3bSJed Brown 42259566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex, &coordDM)); 42269566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(coordDM, pointSF)); 42270a96aa3bSJed Brown } 42289566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointSF)); 42290a96aa3bSJed Brown sc_array_destroy(points_per_dim); 42300a96aa3bSJed Brown sc_array_destroy(cone_sizes); 42310a96aa3bSJed Brown sc_array_destroy(cones); 42320a96aa3bSJed Brown sc_array_destroy(cone_orientations); 42330a96aa3bSJed Brown sc_array_destroy(coords); 42340a96aa3bSJed Brown sc_array_destroy(children); 42350a96aa3bSJed Brown sc_array_destroy(parents); 42360a96aa3bSJed Brown sc_array_destroy(childids); 42370a96aa3bSJed Brown sc_array_destroy(leaves); 42380a96aa3bSJed Brown sc_array_destroy(remotes); 42390a96aa3bSJed Brown 42400a96aa3bSJed Brown { 42414fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 42420a96aa3bSJed Brown 42434fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 42444fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(newPlex, maxCell, Lstart, L)); 42459566063dSJacob Faibussowitsch PetscCall(DMPforestLocalizeCoordinates(dm, newPlex)); 42460a96aa3bSJed Brown } 42470a96aa3bSJed Brown 42480a96aa3bSJed Brown if (overlap > 0) { /* the p4est routine can't set all of the coordinates in its routine if there is overlap */ 42490a96aa3bSJed Brown Vec coordsGlobal, coordsLocal; 42500a96aa3bSJed Brown const PetscScalar *globalArray; 42510a96aa3bSJed Brown PetscScalar *localArray; 42520a96aa3bSJed Brown PetscSF coordSF; 42530a96aa3bSJed Brown DM coordDM; 42540a96aa3bSJed Brown 42559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex, &coordDM)); 42569566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(coordDM, &coordSF)); 42579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(newPlex, &coordsGlobal)); 42589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coordsLocal)); 42599566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordsGlobal, &globalArray)); 42609566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordsLocal, &localArray)); 42619566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coordSF, MPIU_SCALAR, globalArray, localArray, MPI_REPLACE)); 42629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coordSF, MPIU_SCALAR, globalArray, localArray, MPI_REPLACE)); 42639566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordsLocal, &localArray)); 42649566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordsGlobal, &globalArray)); 42659566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(newPlex, coordsLocal)); 42660a96aa3bSJed Brown } 42679566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates(dm, newPlex)); 42680a96aa3bSJed Brown 42690a96aa3bSJed Brown pforest->plex = newPlex; 42700a96aa3bSJed Brown 42710a96aa3bSJed Brown /* copy labels */ 42729566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsFinalize(dm, newPlex)); 42730a96aa3bSJed Brown 42740a96aa3bSJed Brown if (ghostLabelBase || pforest->ghostName) { /* we have to do this after copying labels because the labels drive the construction of ghost cells */ 42750a96aa3bSJed Brown PetscInt numAdded; 42760a96aa3bSJed Brown DM newPlexGhosted; 42770a96aa3bSJed Brown void *ctx; 42780a96aa3bSJed Brown 42799566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(newPlex, pforest->ghostName, &numAdded, &newPlexGhosted)); 42809566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(newPlex, &ctx)); 42819566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(newPlexGhosted, ctx)); 42820a96aa3bSJed Brown /* we want the sf for the ghost dm to be the one for the p4est dm as well */ 42839566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(newPlexGhosted, &pointSF)); 42849566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 42859566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newPlex)); 42869566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlexGhosted, refTree)); 42879566063dSJacob Faibussowitsch PetscCall(DMForestClearAdaptivityForest_pforest(dm)); 42880a96aa3bSJed Brown newPlex = newPlexGhosted; 42890a96aa3bSJed Brown 42900a96aa3bSJed Brown /* share the labels back */ 42919566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 42929566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(newPlex, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 42930a96aa3bSJed Brown pforest->plex = newPlex; 42940a96aa3bSJed Brown } 42959566063dSJacob Faibussowitsch PetscCall(DMDestroy(&refTree)); 42960a96aa3bSJed Brown if (dm->setfromoptionscalled) { 4297d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)newPlex); 4298dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(newPlex, PetscOptionsObject)); 4299dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)newPlex, PetscOptionsObject)); 4300d0609cedSBarry Smith PetscOptionsEnd(); 43010a96aa3bSJed Brown } 43029566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(newPlex, NULL, "-dm_p4est_plex_view")); 43030a96aa3bSJed Brown { 43046858538eSMatthew G. Knepley DM cdm; 43050a96aa3bSJed Brown PetscSection coordsSec; 43060a96aa3bSJed Brown Vec coords; 43070a96aa3bSJed Brown PetscInt cDim; 43080a96aa3bSJed Brown 43099566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(newPlex, &cDim)); 43109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(newPlex, &coordsSec)); 43119566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dm, cDim, coordsSec)); 43129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coords)); 43139566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 43146858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex, &cdm)); 43156858538eSMatthew G. Knepley if (cdm) PetscCall(DMSetCellCoordinateDM(dm, cdm)); 43166858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(newPlex, &coordsSec)); 43176858538eSMatthew G. Knepley if (coordsSec) PetscCall(DMSetCellCoordinateSection(dm, cDim, coordsSec)); 43186858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(newPlex, &coords)); 43196858538eSMatthew G. Knepley if (coords) PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 43200a96aa3bSJed Brown } 43210a96aa3bSJed Brown } 43220a96aa3bSJed Brown newPlex = pforest->plex; 43230a96aa3bSJed Brown if (plex) { 43249566063dSJacob Faibussowitsch PetscCall(DMClone(newPlex, plex)); 43256858538eSMatthew G. Knepley #if 0 43269566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM)); 43279566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(*plex,coordDM)); 43286858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex,&coordDM)); 43296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*plex,coordDM)); 43306858538eSMatthew G. Knepley #endif 43319566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm, *plex)); 43320a96aa3bSJed Brown } 43333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43340a96aa3bSJed Brown } 43350a96aa3bSJed Brown 4336d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_pforest(DM dm, PetscOptionItems *PetscOptionsObject) 4337d71ae5a4SJacob Faibussowitsch { 43380a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 43390a96aa3bSJed Brown char stringBuffer[256]; 43400a96aa3bSJed Brown PetscBool flg; 43410a96aa3bSJed Brown 43420a96aa3bSJed Brown PetscFunctionBegin; 4343dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Forest(dm, PetscOptionsObject)); 4344d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DM" P4EST_STRING " options"); 43459566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_p4est_partition_for_coarsening", "partition forest to allow for coarsening", "DMP4estSetPartitionForCoarsening", pforest->partition_for_coarsening, &(pforest->partition_for_coarsening), NULL)); 43469566063dSJacob 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)); 4347d0609cedSBarry Smith PetscOptionsHeadEnd(); 43480a96aa3bSJed Brown if (flg) { 43499566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName)); 43509566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(stringBuffer, &pforest->ghostName)); 43510a96aa3bSJed Brown } 43523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43530a96aa3bSJed Brown } 43540a96aa3bSJed Brown 43550a96aa3bSJed Brown #if !defined(P4_TO_P8) 43560a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP4estGetPartitionForCoarsening 43570a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP4estSetPartitionForCoarsening 43580a96aa3bSJed Brown #else 43590a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP8estGetPartitionForCoarsening 43600a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP8estSetPartitionForCoarsening 43610a96aa3bSJed Brown #endif 43620a96aa3bSJed Brown 4363d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMPforestGetPartitionForCoarsening(DM dm, PetscBool *flg) 4364d71ae5a4SJacob Faibussowitsch { 43650a96aa3bSJed Brown DM_Forest_pforest *pforest; 43660a96aa3bSJed Brown 43670a96aa3bSJed Brown PetscFunctionBegin; 43680a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43690a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 43700a96aa3bSJed Brown *flg = pforest->partition_for_coarsening; 43713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43720a96aa3bSJed Brown } 43730a96aa3bSJed Brown 4374d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMPforestSetPartitionForCoarsening(DM dm, PetscBool flg) 4375d71ae5a4SJacob Faibussowitsch { 43760a96aa3bSJed Brown DM_Forest_pforest *pforest; 43770a96aa3bSJed Brown 43780a96aa3bSJed Brown PetscFunctionBegin; 43790a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43800a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 43810a96aa3bSJed Brown pforest->partition_for_coarsening = flg; 43823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43830a96aa3bSJed Brown } 43840a96aa3bSJed Brown 4385d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetPlex(DM dm, DM *plex) 4386d71ae5a4SJacob Faibussowitsch { 43870a96aa3bSJed Brown DM_Forest_pforest *pforest; 43880a96aa3bSJed Brown 43890a96aa3bSJed Brown PetscFunctionBegin; 43900a96aa3bSJed Brown if (plex) *plex = NULL; 43919566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 43920a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 439348a46eb9SPierre Jolivet if (!pforest->plex) PetscCall(DMConvert_pforest_plex(dm, DMPLEX, NULL)); 43949566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm, pforest->plex)); 43950a96aa3bSJed Brown if (plex) *plex = pforest->plex; 43963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43970a96aa3bSJed Brown } 43980a96aa3bSJed Brown 43990a96aa3bSJed Brown #define DMCreateInterpolation_pforest _append_pforest(DMCreateInterpolation) 4400d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateInterpolation_pforest(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 4401d71ae5a4SJacob Faibussowitsch { 44020a96aa3bSJed Brown PetscSection gsc, gsf; 44030a96aa3bSJed Brown PetscInt m, n; 44040a96aa3bSJed Brown DM cdm; 44050a96aa3bSJed Brown 44060a96aa3bSJed Brown PetscFunctionBegin; 44079566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 44089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 44099566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 44109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 44110a96aa3bSJed Brown 44129566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmFine), interpolation)); 44139566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 44149566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, MATAIJ)); 44150a96aa3bSJed Brown 44169566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 441708401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse, PetscObjectComm((PetscObject)dmFine), PETSC_ERR_SUP, "Only interpolation from coarse DM for now"); 44180a96aa3bSJed Brown 44190a96aa3bSJed Brown { 44200a96aa3bSJed Brown DM plexF, plexC; 44210a96aa3bSJed Brown PetscSF sf; 44220a96aa3bSJed Brown PetscInt *cids; 44230a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1}; 44240a96aa3bSJed Brown 44259566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse, &plexC)); 44269566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine, &plexF)); 44279566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 44289566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 44299566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInterpolatorTree(plexC, plexF, sf, cids, *interpolation)); 44309566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 44319566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 44320a96aa3bSJed Brown } 44339566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 44340a96aa3bSJed Brown /* Use naive scaling */ 44359566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 44363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44370a96aa3bSJed Brown } 44380a96aa3bSJed Brown 44390a96aa3bSJed Brown #define DMCreateInjection_pforest _append_pforest(DMCreateInjection) 4440d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateInjection_pforest(DM dmCoarse, DM dmFine, Mat *injection) 4441d71ae5a4SJacob Faibussowitsch { 44420a96aa3bSJed Brown PetscSection gsc, gsf; 44430a96aa3bSJed Brown PetscInt m, n; 44440a96aa3bSJed Brown DM cdm; 44450a96aa3bSJed Brown 44460a96aa3bSJed Brown PetscFunctionBegin; 44479566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 44489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &n)); 44499566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 44509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &m)); 44510a96aa3bSJed Brown 44529566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmFine), injection)); 44539566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*injection, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 44549566063dSJacob Faibussowitsch PetscCall(MatSetType(*injection, MATAIJ)); 44550a96aa3bSJed Brown 44569566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 445708401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse, PetscObjectComm((PetscObject)dmFine), PETSC_ERR_SUP, "Only injection to coarse DM for now"); 44580a96aa3bSJed Brown 44590a96aa3bSJed Brown { 44600a96aa3bSJed Brown DM plexF, plexC; 44610a96aa3bSJed Brown PetscSF sf; 44620a96aa3bSJed Brown PetscInt *cids; 44630a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1}; 44640a96aa3bSJed Brown 44659566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse, &plexC)); 44669566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine, &plexF)); 44679566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 44689566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 44699566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorTree(plexC, plexF, sf, cids, *injection)); 44709566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 44719566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 44720a96aa3bSJed Brown } 44739566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*injection, NULL, "-inject_mat_view")); 44740a96aa3bSJed Brown /* Use naive scaling */ 44753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44760a96aa3bSJed Brown } 44770a96aa3bSJed Brown 44780a96aa3bSJed Brown #define DMForestTransferVecFromBase_pforest _append_pforest(DMForestTransferVecFromBase) 4479d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestTransferVecFromBase_pforest(DM dm, Vec vecIn, Vec vecOut) 4480d71ae5a4SJacob Faibussowitsch { 44810a96aa3bSJed Brown DM dmIn, dmVecIn, base, basec, plex, coarseDM; 44820a96aa3bSJed Brown DM *hierarchy; 44830a96aa3bSJed Brown PetscSF sfRed = NULL; 44840a96aa3bSJed Brown PetscDS ds; 44850a96aa3bSJed Brown Vec vecInLocal, vecOutLocal; 44860a96aa3bSJed Brown DMLabel subpointMap; 44870a96aa3bSJed Brown PetscInt minLevel, mh, n_hi, i; 44880a96aa3bSJed Brown PetscBool hiforest, *hierarchy_forest; 44890a96aa3bSJed Brown 44900a96aa3bSJed Brown PetscFunctionBegin; 44919566063dSJacob Faibussowitsch PetscCall(VecGetDM(vecIn, &dmVecIn)); 44929566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmVecIn, &ds)); 449328b400f6SJacob Faibussowitsch PetscCheck(ds, PetscObjectComm((PetscObject)dmVecIn), PETSC_ERR_SUP, "Cannot transfer without a PetscDS object"); 44940a96aa3bSJed Brown { /* we cannot stick user contexts into function callbacks for DMProjectFieldLocal! */ 44950a96aa3bSJed Brown PetscSection section; 44960a96aa3bSJed Brown PetscInt Nf; 44970a96aa3bSJed Brown 44989566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn, §ion)); 44999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 450063a3b9bcSJacob 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); 45010a96aa3bSJed Brown } 45029566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel)); 450363a3b9bcSJacob Faibussowitsch PetscCheck(!minLevel, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot transfer with minimum refinement set to %" PetscInt_FMT ". Rerun with DMForestSetMinimumRefinement(dm,0)", minLevel); 45049566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 450528b400f6SJacob Faibussowitsch PetscCheck(base, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing base DM"); 45060a96aa3bSJed Brown 45079566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0)); 45080a96aa3bSJed Brown if (dmVecIn == base) { /* sequential runs */ 45099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 45100a96aa3bSJed Brown } else { 45110a96aa3bSJed Brown PetscSection secIn, secInRed; 45120a96aa3bSJed Brown Vec vecInRed, vecInLocal; 45130a96aa3bSJed Brown 45149566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)base, "_base_migration_sf", (PetscObject *)&sfRed)); 451528b400f6SJacob Faibussowitsch PetscCheck(sfRed, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not the DM set with DMForestSetBaseDM()"); 45169566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmVecIn), &secInRed)); 45179566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &vecInRed)); 45189566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn, &secIn)); 45199566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmVecIn, &vecInLocal)); 45209566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmVecIn, vecIn, INSERT_VALUES, vecInLocal)); 45219566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmVecIn, vecIn, INSERT_VALUES, vecInLocal)); 45229566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dmVecIn, sfRed, secIn, vecInLocal, secInRed, vecInRed)); 45239566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmVecIn, &vecInLocal)); 45249566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secInRed)); 45250a96aa3bSJed Brown vecIn = vecInRed; 45260a96aa3bSJed Brown } 45270a96aa3bSJed Brown 45280a96aa3bSJed Brown /* we first search through the AdaptivityForest hierarchy 45290a96aa3bSJed Brown once we found the first disconnected forest, we upsweep the DM hierarchy */ 45300a96aa3bSJed Brown hiforest = PETSC_TRUE; 45310a96aa3bSJed Brown 45320a96aa3bSJed Brown /* upsweep to the coarsest DM */ 45330a96aa3bSJed Brown n_hi = 0; 45340a96aa3bSJed Brown coarseDM = dm; 45350a96aa3bSJed Brown do { 45360a96aa3bSJed Brown PetscBool isforest; 45370a96aa3bSJed Brown 45380a96aa3bSJed Brown dmIn = coarseDM; 45390a96aa3bSJed Brown /* need to call DMSetUp to have the hierarchy recursively setup */ 45409566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmIn)); 45419566063dSJacob Faibussowitsch PetscCall(DMIsForest(dmIn, &isforest)); 454228b400f6SJacob Faibussowitsch PetscCheck(isforest, PetscObjectComm((PetscObject)dmIn), PETSC_ERR_SUP, "Cannot currently transfer through a mixed hierarchy! Found DM type %s", ((PetscObject)dmIn)->type_name); 45430a96aa3bSJed Brown coarseDM = NULL; 454448a46eb9SPierre Jolivet if (hiforest) PetscCall(DMForestGetAdaptivityForest(dmIn, &coarseDM)); 45450a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 45460a96aa3bSJed Brown hiforest = PETSC_FALSE; 45479566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn, &coarseDM)); 45480a96aa3bSJed Brown } 45490a96aa3bSJed Brown n_hi++; 45500a96aa3bSJed Brown } while (coarseDM); 45510a96aa3bSJed Brown 45529566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n_hi, &hierarchy, n_hi, &hierarchy_forest)); 45530a96aa3bSJed Brown 45540a96aa3bSJed Brown i = 0; 45550a96aa3bSJed Brown hiforest = PETSC_TRUE; 45560a96aa3bSJed Brown coarseDM = dm; 45570a96aa3bSJed Brown do { 45580a96aa3bSJed Brown dmIn = coarseDM; 45590a96aa3bSJed Brown coarseDM = NULL; 456048a46eb9SPierre Jolivet if (hiforest) PetscCall(DMForestGetAdaptivityForest(dmIn, &coarseDM)); 45610a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 45620a96aa3bSJed Brown hiforest = PETSC_FALSE; 45639566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn, &coarseDM)); 45640a96aa3bSJed Brown } 45650a96aa3bSJed Brown i++; 45660a96aa3bSJed Brown hierarchy[n_hi - i] = dmIn; 45670a96aa3bSJed Brown } while (coarseDM); 45680a96aa3bSJed Brown 45690a96aa3bSJed Brown /* project base vector on the coarsest forest (minimum refinement = 0) */ 45709566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn, &plex)); 45710a96aa3bSJed Brown 45720a96aa3bSJed Brown /* Check this plex is compatible with the base */ 45730a96aa3bSJed Brown { 45740a96aa3bSJed Brown IS gnum[2]; 45750a96aa3bSJed Brown PetscInt ncells[2], gncells[2]; 45760a96aa3bSJed Brown 45779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(base, &gnum[0])); 45789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(plex, &gnum[1])); 45799566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[0], NULL, &ncells[0])); 45809566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[1], NULL, &ncells[1])); 45811c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(ncells, gncells, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 458263a3b9bcSJacob 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); 45830a96aa3bSJed Brown } 45840a96aa3bSJed Brown 45859566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmIn, "_forest_base_subpoint_map", &subpointMap)); 458628b400f6SJacob Faibussowitsch PetscCheck(subpointMap, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing _forest_base_subpoint_map label"); 45870a96aa3bSJed Brown 45889566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(base, &mh)); 45899566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(plex, mh)); 45900a96aa3bSJed Brown 45919566063dSJacob Faibussowitsch PetscCall(DMClone(base, &basec)); 45929566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmVecIn, basec)); 45930a96aa3bSJed Brown if (sfRed) { 45949566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 45950a96aa3bSJed Brown vecInLocal = vecIn; 45960a96aa3bSJed Brown } else { 45979566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(basec, &vecInLocal)); 45989566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(basec, vecIn, INSERT_VALUES, vecInLocal)); 45999566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(basec, vecIn, INSERT_VALUES, vecInLocal)); 46000a96aa3bSJed Brown } 46010a96aa3bSJed Brown 46029566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecOutLocal)); 46030a96aa3bSJed Brown { /* get degrees of freedom ordered onto dmIn */ 46040a96aa3bSJed Brown PetscSF basetocoarse; 46050a96aa3bSJed Brown PetscInt bStart, bEnd, nroots; 46060a96aa3bSJed Brown PetscInt iStart, iEnd, nleaves, leaf; 46070a96aa3bSJed Brown PetscMPIInt rank; 46080a96aa3bSJed Brown PetscSFNode *remotes; 46090a96aa3bSJed Brown PetscSection secIn, secOut; 46100a96aa3bSJed Brown PetscInt *remoteOffsets; 46110a96aa3bSJed Brown PetscSF transferSF; 46120a96aa3bSJed Brown const PetscScalar *inArray; 46130a96aa3bSJed Brown PetscScalar *outArray; 46140a96aa3bSJed Brown 46159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)basec), &rank)); 46169566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(basec, &bStart, &bEnd)); 46170a96aa3bSJed Brown nroots = PetscMax(bEnd - bStart, 0); 46189566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &iStart, &iEnd)); 46190a96aa3bSJed Brown nleaves = PetscMax(iEnd - iStart, 0); 46200a96aa3bSJed Brown 46219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotes)); 46220a96aa3bSJed Brown for (leaf = iStart; leaf < iEnd; leaf++) { 46230a96aa3bSJed Brown PetscInt index; 46240a96aa3bSJed Brown 46250a96aa3bSJed Brown remotes[leaf - iStart].rank = rank; 46269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, leaf, &index)); 46270a96aa3bSJed Brown remotes[leaf - iStart].index = index; 46280a96aa3bSJed Brown } 46290a96aa3bSJed Brown 46309566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)basec), &basetocoarse)); 46319566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(basetocoarse, nroots, nleaves, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 46329566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(basetocoarse)); 46339566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(basec, &secIn)); 46349566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmIn), &secOut)); 46359566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(basetocoarse, secIn, &remoteOffsets, secOut)); 46369566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(basetocoarse, secIn, remoteOffsets, secOut, &transferSF)); 46379566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 46389566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(vecOutLocal, &outArray)); 46399566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecInLocal, &inArray)); 46409566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferSF, MPIU_SCALAR, inArray, outArray, MPI_REPLACE)); 46419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferSF, MPIU_SCALAR, inArray, outArray, MPI_REPLACE)); 46429566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecInLocal, &inArray)); 46439566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(vecOutLocal, &outArray)); 46449566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferSF)); 46459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secOut)); 46469566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&basetocoarse)); 46470a96aa3bSJed Brown } 46489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecInLocal)); 46499566063dSJacob Faibussowitsch PetscCall(DMDestroy(&basec)); 46509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecIn)); 46510a96aa3bSJed Brown 46520a96aa3bSJed Brown /* output */ 46530a96aa3bSJed Brown if (n_hi > 1) { /* downsweep the stored hierarchy */ 46540a96aa3bSJed Brown Vec vecOut1, vecOut2; 46550a96aa3bSJed Brown DM fineDM; 46560a96aa3bSJed Brown 46579566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmIn, &vecOut1)); 46589566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn, vecOutLocal, INSERT_VALUES, vecOut1)); 46599566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecOutLocal)); 46600a96aa3bSJed Brown for (i = 1; i < n_hi - 1; i++) { 46610a96aa3bSJed Brown fineDM = hierarchy[i]; 46629566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(fineDM, &vecOut2)); 46639566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn, vecOut1, fineDM, vecOut2, PETSC_TRUE, 0.0)); 46649566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn, &vecOut1)); 46650a96aa3bSJed Brown vecOut1 = vecOut2; 46660a96aa3bSJed Brown dmIn = fineDM; 46670a96aa3bSJed Brown } 46689566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn, vecOut1, dm, vecOut, PETSC_TRUE, 0.0)); 46699566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn, &vecOut1)); 46700a96aa3bSJed Brown } else { 46719566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn, vecOutLocal, INSERT_VALUES, vecOut)); 46729566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecOutLocal)); 46730a96aa3bSJed Brown } 46749566063dSJacob Faibussowitsch PetscCall(PetscFree2(hierarchy, hierarchy_forest)); 46753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46760a96aa3bSJed Brown } 46770a96aa3bSJed Brown 46780a96aa3bSJed Brown #define DMForestTransferVec_pforest _append_pforest(DMForestTransferVec) 4679d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestTransferVec_pforest(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time) 4680d71ae5a4SJacob Faibussowitsch { 46810a96aa3bSJed Brown DM adaptIn, adaptOut, plexIn, plexOut; 46820a96aa3bSJed Brown DM_Forest *forestIn, *forestOut, *forestAdaptIn, *forestAdaptOut; 46830a96aa3bSJed Brown PetscInt dofPerDim[] = {1, 1, 1, 1}; 46840a96aa3bSJed Brown PetscSF inSF = NULL, outSF = NULL; 46850a96aa3bSJed Brown PetscInt *inCids = NULL, *outCids = NULL; 46860a96aa3bSJed Brown DMAdaptFlag purposeIn, purposeOut; 46870a96aa3bSJed Brown 46880a96aa3bSJed Brown PetscFunctionBegin; 46890a96aa3bSJed Brown forestOut = (DM_Forest *)dmOut->data; 46900a96aa3bSJed Brown forestIn = (DM_Forest *)dmIn->data; 46910a96aa3bSJed Brown 46929566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmOut, &adaptOut)); 46939566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmOut, &purposeOut)); 46940a96aa3bSJed Brown forestAdaptOut = adaptOut ? (DM_Forest *)adaptOut->data : NULL; 46950a96aa3bSJed Brown 46969566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn, &adaptIn)); 46979566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmIn, &purposeIn)); 46980a96aa3bSJed Brown forestAdaptIn = adaptIn ? (DM_Forest *)adaptIn->data : NULL; 46990a96aa3bSJed Brown 47000a96aa3bSJed Brown if (forestAdaptOut == forestIn) { 47010a96aa3bSJed Brown switch (purposeOut) { 47020a96aa3bSJed Brown case DM_ADAPT_REFINE: 47039566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 47049566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47050a96aa3bSJed Brown break; 47060a96aa3bSJed Brown case DM_ADAPT_COARSEN: 47070a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 47089566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_TRUE, &outCids)); 47099566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 47100a96aa3bSJed Brown break; 47110a96aa3bSJed Brown default: 47129566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 47139566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_FALSE, &outCids)); 47149566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47159566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 47160a96aa3bSJed Brown } 47170a96aa3bSJed Brown } else if (forestAdaptIn == forestOut) { 47180a96aa3bSJed Brown switch (purposeIn) { 47190a96aa3bSJed Brown case DM_ADAPT_REFINE: 47209566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_TRUE, &inCids)); 47219566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 47220a96aa3bSJed Brown break; 47230a96aa3bSJed Brown case DM_ADAPT_COARSEN: 47240a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 47259566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 47269566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47270a96aa3bSJed Brown break; 47280a96aa3bSJed Brown default: 47299566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 47309566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_FALSE, &outCids)); 47319566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47329566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 47330a96aa3bSJed Brown } 47340a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dmIn), PETSC_ERR_SUP, "Only support transfer from pre-adaptivity to post-adaptivity right now"); 47359566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn, &plexIn)); 47369566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmOut, &plexOut)); 47370a96aa3bSJed Brown 47389566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree(plexIn, vecIn, plexOut, vecOut, inSF, outSF, inCids, outCids, useBCs, time)); 47399566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 47409566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 47419566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&inSF)); 47429566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&outSF)); 47439566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 47449566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 47453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47460a96aa3bSJed Brown } 47470a96aa3bSJed Brown 47480a96aa3bSJed Brown #define DMCreateCoordinateDM_pforest _append_pforest(DMCreateCoordinateDM) 4749d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateCoordinateDM_pforest(DM dm, DM *cdm) 4750d71ae5a4SJacob Faibussowitsch { 47510a96aa3bSJed Brown DM plex; 47520a96aa3bSJed Brown 47530a96aa3bSJed Brown PetscFunctionBegin; 47540a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47559566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(plex, cdm)); 47579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*cdm)); 47583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47590a96aa3bSJed Brown } 47600a96aa3bSJed Brown 47610a96aa3bSJed Brown #define VecViewLocal_pforest _append_pforest(VecViewLocal) 4762d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecViewLocal_pforest(Vec vec, PetscViewer viewer) 4763d71ae5a4SJacob Faibussowitsch { 47640a96aa3bSJed Brown DM dm, plex; 47650a96aa3bSJed Brown 47660a96aa3bSJed Brown PetscFunctionBegin; 47679566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 47689566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47699566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 47709566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(vec, viewer)); 47719566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 47723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47730a96aa3bSJed Brown } 47740a96aa3bSJed Brown 47750a96aa3bSJed Brown #define VecView_pforest _append_pforest(VecView) 4776d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_pforest(Vec vec, PetscViewer viewer) 4777d71ae5a4SJacob Faibussowitsch { 47780a96aa3bSJed Brown DM dm, plex; 47790a96aa3bSJed Brown 47800a96aa3bSJed Brown PetscFunctionBegin; 47819566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 47829566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47839566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 47849566063dSJacob Faibussowitsch PetscCall(VecView_Plex(vec, viewer)); 47859566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 47863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47870a96aa3bSJed Brown } 47880a96aa3bSJed Brown 47890a96aa3bSJed Brown #define VecView_pforest_Native _infix_pforest(VecView, _Native) 4790d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_pforest_Native(Vec vec, PetscViewer viewer) 4791d71ae5a4SJacob Faibussowitsch { 47920a96aa3bSJed Brown DM dm, plex; 47930a96aa3bSJed Brown 47940a96aa3bSJed Brown PetscFunctionBegin; 47959566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 47969566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47979566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 47989566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Native(vec, viewer)); 47999566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 48003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48010a96aa3bSJed Brown } 48020a96aa3bSJed Brown 48030a96aa3bSJed Brown #define VecLoad_pforest _append_pforest(VecLoad) 4804d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecLoad_pforest(Vec vec, PetscViewer viewer) 4805d71ae5a4SJacob Faibussowitsch { 48060a96aa3bSJed Brown DM dm, plex; 48070a96aa3bSJed Brown 48080a96aa3bSJed Brown PetscFunctionBegin; 48099566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 48109566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48119566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 48129566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex(vec, viewer)); 48139566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 48143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48150a96aa3bSJed Brown } 48160a96aa3bSJed Brown 48170a96aa3bSJed Brown #define VecLoad_pforest_Native _infix_pforest(VecLoad, _Native) 4818d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecLoad_pforest_Native(Vec vec, PetscViewer viewer) 4819d71ae5a4SJacob Faibussowitsch { 48200a96aa3bSJed Brown DM dm, plex; 48210a96aa3bSJed Brown 48220a96aa3bSJed Brown PetscFunctionBegin; 48239566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 48249566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48259566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 48269566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_Native(vec, viewer)); 48279566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 48283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48290a96aa3bSJed Brown } 48300a96aa3bSJed Brown 48310a96aa3bSJed Brown #define DMCreateGlobalVector_pforest _append_pforest(DMCreateGlobalVector) 4832d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_pforest(DM dm, Vec *vec) 4833d71ae5a4SJacob Faibussowitsch { 48340a96aa3bSJed Brown PetscFunctionBegin; 48359566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 48369566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 48379566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_pforest)); 48389566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_pforest_Native)); 48399566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_pforest)); 48409566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_pforest_Native)); 48413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48420a96aa3bSJed Brown } 48430a96aa3bSJed Brown 48440a96aa3bSJed Brown #define DMCreateLocalVector_pforest _append_pforest(DMCreateLocalVector) 4845d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_pforest(DM dm, Vec *vec) 4846d71ae5a4SJacob Faibussowitsch { 48470a96aa3bSJed Brown PetscFunctionBegin; 48489566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 48499566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecViewLocal_pforest)); 48503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48510a96aa3bSJed Brown } 48520a96aa3bSJed Brown 48530a96aa3bSJed Brown #define DMCreateMatrix_pforest _append_pforest(DMCreateMatrix) 4854d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_pforest(DM dm, Mat *mat) 4855d71ae5a4SJacob Faibussowitsch { 48560a96aa3bSJed Brown DM plex; 48570a96aa3bSJed Brown 48580a96aa3bSJed Brown PetscFunctionBegin; 48590a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48609566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48610a96aa3bSJed Brown if (plex->prealloc_only != dm->prealloc_only) plex->prealloc_only = dm->prealloc_only; /* maybe this should go into forest->plex */ 48629566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(plex, mat)); 48639566063dSJacob Faibussowitsch PetscCall(MatSetDM(*mat, dm)); 48643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48650a96aa3bSJed Brown } 48660a96aa3bSJed Brown 48670a96aa3bSJed Brown #define DMProjectFunctionLocal_pforest _append_pforest(DMProjectFunctionLocal) 4868d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMProjectFunctionLocal_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 4869d71ae5a4SJacob Faibussowitsch { 48700a96aa3bSJed Brown DM plex; 48710a96aa3bSJed Brown 48720a96aa3bSJed Brown PetscFunctionBegin; 48730a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48749566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48759566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLocal(plex, time, funcs, ctxs, mode, localX)); 48763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48770a96aa3bSJed Brown } 48780a96aa3bSJed Brown 48790a96aa3bSJed Brown #define DMProjectFunctionLabelLocal_pforest _append_pforest(DMProjectFunctionLabelLocal) 4880d71ae5a4SJacob Faibussowitsch 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) 4881d71ae5a4SJacob Faibussowitsch { 48820a96aa3bSJed Brown DM plex; 48830a96aa3bSJed Brown 48840a96aa3bSJed Brown PetscFunctionBegin; 48850a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48869566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48879566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLabelLocal(plex, time, label, numIds, ids, Ncc, comps, funcs, ctxs, mode, localX)); 48883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48890a96aa3bSJed Brown } 48900a96aa3bSJed Brown 48910a96aa3bSJed Brown #define DMProjectFieldLocal_pforest _append_pforest(DMProjectFieldLocal) 4892d71ae5a4SJacob Faibussowitsch 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) 4893d71ae5a4SJacob Faibussowitsch { 48940a96aa3bSJed Brown DM plex; 48950a96aa3bSJed Brown 48960a96aa3bSJed Brown PetscFunctionBegin; 48970a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48989566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48999566063dSJacob Faibussowitsch PetscCall(DMProjectFieldLocal(plex, time, localU, funcs, mode, localX)); 49003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49010a96aa3bSJed Brown } 49020a96aa3bSJed Brown 49030a96aa3bSJed Brown #define DMComputeL2Diff_pforest _append_pforest(DMComputeL2Diff) 4904d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 4905d71ae5a4SJacob Faibussowitsch { 49060a96aa3bSJed Brown DM plex; 49070a96aa3bSJed Brown 49080a96aa3bSJed Brown PetscFunctionBegin; 49090a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49109566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49119566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(plex, time, funcs, ctxs, X, diff)); 49123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49130a96aa3bSJed Brown } 49140a96aa3bSJed Brown 49150a96aa3bSJed Brown #define DMComputeL2FieldDiff_pforest _append_pforest(DMComputeL2FieldDiff) 4916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 4917d71ae5a4SJacob Faibussowitsch { 49180a96aa3bSJed Brown DM plex; 49190a96aa3bSJed Brown 49200a96aa3bSJed Brown PetscFunctionBegin; 49210a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49229566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49239566063dSJacob Faibussowitsch PetscCall(DMComputeL2FieldDiff(plex, time, funcs, ctxs, X, diff)); 49243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49250a96aa3bSJed Brown } 49260a96aa3bSJed Brown 49270a96aa3bSJed Brown #define DMCreatelocalsection_pforest _append_pforest(DMCreatelocalsection) 4928d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreatelocalsection_pforest(DM dm) 4929d71ae5a4SJacob Faibussowitsch { 49300a96aa3bSJed Brown DM plex; 49310a96aa3bSJed Brown PetscSection section; 49320a96aa3bSJed Brown 49330a96aa3bSJed Brown PetscFunctionBegin; 49340a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49359566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49369566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(plex, §ion)); 49379566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(dm, section)); 49383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49390a96aa3bSJed Brown } 49400a96aa3bSJed Brown 49410a96aa3bSJed Brown #define DMCreateDefaultConstraints_pforest _append_pforest(DMCreateDefaultConstraints) 4942d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateDefaultConstraints_pforest(DM dm) 4943d71ae5a4SJacob Faibussowitsch { 49440a96aa3bSJed Brown DM plex; 49450a96aa3bSJed Brown Mat mat; 494679769bd5SJed Brown Vec bias; 49470a96aa3bSJed Brown PetscSection section; 49480a96aa3bSJed Brown 49490a96aa3bSJed Brown PetscFunctionBegin; 49500a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49519566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49529566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(plex, §ion, &mat, &bias)); 49539566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, section, mat, bias)); 49543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49550a96aa3bSJed Brown } 49560a96aa3bSJed Brown 49570a96aa3bSJed Brown #define DMGetDimPoints_pforest _append_pforest(DMGetDimPoints) 4958d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_pforest(DM dm, PetscInt dim, PetscInt *cStart, PetscInt *cEnd) 4959d71ae5a4SJacob Faibussowitsch { 49600a96aa3bSJed Brown DM plex; 49610a96aa3bSJed Brown 49620a96aa3bSJed Brown PetscFunctionBegin; 49630a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49649566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49659566063dSJacob Faibussowitsch PetscCall(DMGetDimPoints(plex, dim, cStart, cEnd)); 49663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49670a96aa3bSJed Brown } 49680a96aa3bSJed Brown 49690a96aa3bSJed Brown /* Need to forward declare */ 49700a96aa3bSJed Brown #define DMInitialize_pforest _append_pforest(DMInitialize) 49710a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm); 49720a96aa3bSJed Brown 49730a96aa3bSJed Brown #define DMClone_pforest _append_pforest(DMClone) 4974d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMClone_pforest(DM dm, DM *newdm) 4975d71ae5a4SJacob Faibussowitsch { 49760a96aa3bSJed Brown PetscFunctionBegin; 49779566063dSJacob Faibussowitsch PetscCall(DMClone_Forest(dm, newdm)); 49789566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(*newdm)); 49793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49800a96aa3bSJed Brown } 49810a96aa3bSJed Brown 49820a96aa3bSJed Brown #define DMForestCreateCellChart_pforest _append_pforest(DMForestCreateCellChart) 4983d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestCreateCellChart_pforest(DM dm, PetscInt *cStart, PetscInt *cEnd) 4984d71ae5a4SJacob Faibussowitsch { 49850a96aa3bSJed Brown DM_Forest *forest; 49860a96aa3bSJed Brown DM_Forest_pforest *pforest; 49870a96aa3bSJed Brown PetscInt overlap; 49880a96aa3bSJed Brown 49890a96aa3bSJed Brown PetscFunctionBegin; 49909566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 49910a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 49920a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 49930a96aa3bSJed Brown *cStart = 0; 49949566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 49950a96aa3bSJed Brown if (overlap && pforest->ghost) { 49960a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[pforest->forest->mpisize]; 49970a96aa3bSJed Brown } else { 49980a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants; 49990a96aa3bSJed Brown } 50003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50010a96aa3bSJed Brown } 50020a96aa3bSJed Brown 50030a96aa3bSJed Brown #define DMForestCreateCellSF_pforest _append_pforest(DMForestCreateCellSF) 5004d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestCreateCellSF_pforest(DM dm, PetscSF *cellSF) 5005d71ae5a4SJacob Faibussowitsch { 50060a96aa3bSJed Brown DM_Forest *forest; 50070a96aa3bSJed Brown DM_Forest_pforest *pforest; 50080a96aa3bSJed Brown PetscMPIInt rank; 50090a96aa3bSJed Brown PetscInt overlap; 50100a96aa3bSJed Brown PetscInt cStart, cEnd, cLocalStart, cLocalEnd; 50110a96aa3bSJed Brown PetscInt nRoots, nLeaves, *mine = NULL; 50120a96aa3bSJed Brown PetscSFNode *remote = NULL; 50130a96aa3bSJed Brown PetscSF sf; 50140a96aa3bSJed Brown 50150a96aa3bSJed Brown PetscFunctionBegin; 50169566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(dm, &cStart, &cEnd)); 50170a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 50180a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 50190a96aa3bSJed Brown nRoots = cEnd - cStart; 50200a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 50210a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 50220a96aa3bSJed Brown nLeaves = 0; 50239566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 50249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 50250a96aa3bSJed Brown if (overlap && pforest->ghost) { 50260a96aa3bSJed Brown PetscSFNode *mirror; 50270a96aa3bSJed Brown p4est_quadrant_t *mirror_array; 50280a96aa3bSJed Brown PetscInt nMirror, nGhostPre, nSelf, q; 50290a96aa3bSJed Brown void **mirrorPtrs; 50300a96aa3bSJed Brown 50310a96aa3bSJed Brown nMirror = (PetscInt)pforest->ghost->mirrors.elem_count; 50320a96aa3bSJed Brown nSelf = cLocalEnd - cLocalStart; 50330a96aa3bSJed Brown nLeaves = nRoots - nSelf; 50340a96aa3bSJed Brown nGhostPre = (PetscInt)pforest->ghost->proc_offsets[rank]; 50359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &mine)); 50369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &remote)); 50379566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nMirror, &mirror, nMirror, &mirrorPtrs)); 50380a96aa3bSJed Brown mirror_array = (p4est_quadrant_t *)pforest->ghost->mirrors.array; 50390a96aa3bSJed Brown for (q = 0; q < nMirror; q++) { 50400a96aa3bSJed Brown p4est_quadrant_t *mir = &(mirror_array[q]); 50410a96aa3bSJed Brown 50420a96aa3bSJed Brown mirror[q].rank = rank; 50430a96aa3bSJed Brown mirror[q].index = (PetscInt)mir->p.piggy3.local_num + cLocalStart; 50440a96aa3bSJed Brown mirrorPtrs[q] = (void *)&(mirror[q]); 50450a96aa3bSJed Brown } 5046792fecdfSBarry Smith PetscCallP4est(p4est_ghost_exchange_custom, (pforest->forest, pforest->ghost, sizeof(PetscSFNode), mirrorPtrs, remote)); 50479566063dSJacob Faibussowitsch PetscCall(PetscFree2(mirror, mirrorPtrs)); 50480a96aa3bSJed Brown for (q = 0; q < nGhostPre; q++) mine[q] = q; 50490a96aa3bSJed Brown for (; q < nLeaves; q++) mine[q] = (q - nGhostPre) + cLocalEnd; 50500a96aa3bSJed Brown } 50519566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &sf)); 50529566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nRoots, nLeaves, mine, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER)); 50530a96aa3bSJed Brown *cellSF = sf; 50543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50550a96aa3bSJed Brown } 50560a96aa3bSJed Brown 5057d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateNeumannOverlap_pforest(DM dm, IS *ovl, Mat *J, PetscErrorCode (**setup)(Mat, PetscReal, Vec, Vec, PetscReal, IS, void *), void **setup_ctx) 5058d71ae5a4SJacob Faibussowitsch { 50590a96aa3bSJed Brown DM plex; 50600a96aa3bSJed Brown 50610a96aa3bSJed Brown PetscFunctionBegin; 50629566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 50639566063dSJacob Faibussowitsch PetscCall(DMCreateNeumannOverlap_Plex(plex, ovl, J, setup, setup_ctx)); 50640a96aa3bSJed Brown if (!*setup) { 50659566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", setup)); 506648a46eb9SPierre Jolivet if (*setup) PetscCall(PetscObjectCompose((PetscObject)*ovl, "_DM_Original_HPDDM", (PetscObject)dm)); 50670a96aa3bSJed Brown } 50683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50690a96aa3bSJed Brown } 50700a96aa3bSJed Brown 5071d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_pforest(DM dm) 5072d71ae5a4SJacob Faibussowitsch { 50730a96aa3bSJed Brown PetscFunctionBegin; 50740a96aa3bSJed Brown dm->ops->setup = DMSetUp_pforest; 50750a96aa3bSJed Brown dm->ops->view = DMView_pforest; 50760a96aa3bSJed Brown dm->ops->clone = DMClone_pforest; 50770a96aa3bSJed Brown dm->ops->createinterpolation = DMCreateInterpolation_pforest; 50780a96aa3bSJed Brown dm->ops->createinjection = DMCreateInjection_pforest; 50790a96aa3bSJed Brown dm->ops->setfromoptions = DMSetFromOptions_pforest; 50800a96aa3bSJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_pforest; 50810a96aa3bSJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_pforest; 50820a96aa3bSJed Brown dm->ops->createlocalvector = DMCreateLocalVector_pforest; 50830a96aa3bSJed Brown dm->ops->creatematrix = DMCreateMatrix_pforest; 50840a96aa3bSJed Brown dm->ops->projectfunctionlocal = DMProjectFunctionLocal_pforest; 50850a96aa3bSJed Brown dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_pforest; 50860a96aa3bSJed Brown dm->ops->projectfieldlocal = DMProjectFieldLocal_pforest; 50870a96aa3bSJed Brown dm->ops->createlocalsection = DMCreatelocalsection_pforest; 50880a96aa3bSJed Brown dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_pforest; 50890a96aa3bSJed Brown dm->ops->computel2diff = DMComputeL2Diff_pforest; 50900a96aa3bSJed Brown dm->ops->computel2fielddiff = DMComputeL2FieldDiff_pforest; 50910a96aa3bSJed Brown dm->ops->getdimpoints = DMGetDimPoints_pforest; 50920a96aa3bSJed Brown 50939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_plex_pforest) "_C", DMConvert_plex_pforest)); 50949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_pforest_plex) "_C", DMConvert_pforest_plex)); 50959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_pforest)); 50969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMForestGetPartitionOverlap)); 50973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50980a96aa3bSJed Brown } 50990a96aa3bSJed Brown 51000a96aa3bSJed Brown #define DMCreate_pforest _append_pforest(DMCreate) 5101d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_pforest(DM dm) 5102d71ae5a4SJacob Faibussowitsch { 51030a96aa3bSJed Brown DM_Forest *forest; 51040a96aa3bSJed Brown DM_Forest_pforest *pforest; 51050a96aa3bSJed Brown 51060a96aa3bSJed Brown PetscFunctionBegin; 51079566063dSJacob Faibussowitsch PetscCall(PetscP4estInitialize()); 51089566063dSJacob Faibussowitsch PetscCall(DMCreate_Forest(dm)); 51099566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(dm)); 51109566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, P4EST_DIM)); 51110a96aa3bSJed Brown 51120a96aa3bSJed Brown /* set forest defaults */ 51139566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm, "unit")); 51149566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(dm, 0)); 51159566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(dm, 0)); 51169566063dSJacob Faibussowitsch PetscCall(DMForestSetMaximumRefinement(dm, P4EST_QMAXLEVEL)); 51179566063dSJacob Faibussowitsch PetscCall(DMForestSetGradeFactor(dm, 2)); 51189566063dSJacob Faibussowitsch PetscCall(DMForestSetAdjacencyDimension(dm, 0)); 51199566063dSJacob Faibussowitsch PetscCall(DMForestSetPartitionOverlap(dm, 0)); 51200a96aa3bSJed Brown 51210a96aa3bSJed Brown /* create p4est data */ 51224dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&pforest)); 51230a96aa3bSJed Brown 51240a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 51250a96aa3bSJed Brown forest->data = pforest; 51260a96aa3bSJed Brown forest->destroy = DMForestDestroy_pforest; 51270a96aa3bSJed Brown forest->ftemplate = DMForestTemplate_pforest; 51280a96aa3bSJed Brown forest->transfervec = DMForestTransferVec_pforest; 51290a96aa3bSJed Brown forest->transfervecfrombase = DMForestTransferVecFromBase_pforest; 51300a96aa3bSJed Brown forest->createcellchart = DMForestCreateCellChart_pforest; 51310a96aa3bSJed Brown forest->createcellsf = DMForestCreateCellSF_pforest; 51320a96aa3bSJed Brown forest->clearadaptivityforest = DMForestClearAdaptivityForest_pforest; 51330a96aa3bSJed Brown forest->getadaptivitysuccess = DMForestGetAdaptivitySuccess_pforest; 51340a96aa3bSJed Brown pforest->topo = NULL; 51350a96aa3bSJed Brown pforest->forest = NULL; 51360a96aa3bSJed Brown pforest->ghost = NULL; 51370a96aa3bSJed Brown pforest->lnodes = NULL; 51380a96aa3bSJed Brown pforest->partition_for_coarsening = PETSC_TRUE; 51390a96aa3bSJed Brown pforest->coarsen_hierarchy = PETSC_FALSE; 51400a96aa3bSJed Brown pforest->cLocalStart = -1; 51410a96aa3bSJed Brown pforest->cLocalEnd = -1; 51420a96aa3bSJed Brown pforest->labelsFinalized = PETSC_FALSE; 51430a96aa3bSJed Brown pforest->ghostName = NULL; 51443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51450a96aa3bSJed Brown } 51460a96aa3bSJed Brown 51470a96aa3bSJed Brown #endif /* defined(PETSC_HAVE_P4EST) */ 5148