1a4963045SJacob Faibussowitsch #pragma once 23ea99036SJacob Faibussowitsch 30a96aa3bSJed Brown #include <petscds.h> 4707c51c7SToby Isaac #include <petscfe.h> 50a96aa3bSJed Brown #include <petsc/private/dmimpl.h> 60a96aa3bSJed Brown #include <petsc/private/dmforestimpl.h> 70a96aa3bSJed Brown #include <petsc/private/dmpleximpl.h> 80a96aa3bSJed Brown #include <petsc/private/dmlabelimpl.h> 90a96aa3bSJed Brown #include <petsc/private/viewerimpl.h> 100a96aa3bSJed Brown #include <../src/sys/classes/viewer/impls/vtk/vtkvimpl.h> 110a96aa3bSJed Brown #include "petsc_p4est_package.h" 120a96aa3bSJed Brown 130a96aa3bSJed Brown #if defined(PETSC_HAVE_P4EST) 140a96aa3bSJed Brown 150a96aa3bSJed Brown #if !defined(P4_TO_P8) 160a96aa3bSJed Brown #include <p4est.h> 170a96aa3bSJed Brown #include <p4est_extended.h> 180a96aa3bSJed Brown #include <p4est_geometry.h> 190a96aa3bSJed Brown #include <p4est_ghost.h> 200a96aa3bSJed Brown #include <p4est_lnodes.h> 210a96aa3bSJed Brown #include <p4est_vtk.h> 220a96aa3bSJed Brown #include <p4est_plex.h> 230a96aa3bSJed Brown #include <p4est_bits.h> 240a96aa3bSJed Brown #include <p4est_algorithms.h> 250a96aa3bSJed Brown #else 260a96aa3bSJed Brown #include <p8est.h> 270a96aa3bSJed Brown #include <p8est_extended.h> 280a96aa3bSJed Brown #include <p8est_geometry.h> 290a96aa3bSJed Brown #include <p8est_ghost.h> 300a96aa3bSJed Brown #include <p8est_lnodes.h> 310a96aa3bSJed Brown #include <p8est_vtk.h> 320a96aa3bSJed Brown #include <p8est_plex.h> 330a96aa3bSJed Brown #include <p8est_bits.h> 340a96aa3bSJed Brown #include <p8est_algorithms.h> 350a96aa3bSJed Brown #endif 360a96aa3bSJed Brown 379371c9d4SSatish Balay typedef enum { 389371c9d4SSatish Balay PATTERN_HASH, 399371c9d4SSatish Balay PATTERN_FRACTAL, 409371c9d4SSatish Balay PATTERN_CORNER, 419371c9d4SSatish Balay PATTERN_CENTER, 429371c9d4SSatish Balay PATTERN_COUNT 439371c9d4SSatish Balay } DMRefinePattern; 440a96aa3bSJed Brown static const char *DMRefinePatternName[PATTERN_COUNT] = {"hash", "fractal", "corner", "center"}; 450a96aa3bSJed Brown 469371c9d4SSatish Balay typedef struct _DMRefinePatternCtx { 470a96aa3bSJed Brown PetscInt corner; 480a96aa3bSJed Brown PetscBool fractal[P4EST_CHILDREN]; 490a96aa3bSJed Brown PetscReal hashLikelihood; 500a96aa3bSJed Brown PetscInt maxLevel; 510a96aa3bSJed Brown p4est_refine_t refine_fn; 529371c9d4SSatish Balay } DMRefinePatternCtx; 530a96aa3bSJed Brown 54d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Corner(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 55d71ae5a4SJacob Faibussowitsch { 560a96aa3bSJed Brown p4est_quadrant_t root, rootcorner; 570a96aa3bSJed Brown DMRefinePatternCtx *ctx; 580a96aa3bSJed Brown 590a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 600a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 610a96aa3bSJed Brown 620a96aa3bSJed Brown root.x = root.y = 0; 630a96aa3bSJed Brown #if defined(P4_TO_P8) 640a96aa3bSJed Brown root.z = 0; 650a96aa3bSJed Brown #endif 660a96aa3bSJed Brown root.level = 0; 670a96aa3bSJed Brown p4est_quadrant_corner_descendant(&root, &rootcorner, ctx->corner, quadrant->level); 680a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant, &rootcorner)) return 1; 690a96aa3bSJed Brown return 0; 700a96aa3bSJed Brown } 710a96aa3bSJed Brown 72d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Center(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 73d71ae5a4SJacob Faibussowitsch { 740a96aa3bSJed Brown int cid; 750a96aa3bSJed Brown p4est_quadrant_t ancestor, ancestorcorner; 760a96aa3bSJed Brown DMRefinePatternCtx *ctx; 770a96aa3bSJed Brown 780a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 790a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 800a96aa3bSJed Brown if (quadrant->level <= 1) return 1; 810a96aa3bSJed Brown 820a96aa3bSJed Brown p4est_quadrant_ancestor(quadrant, 1, &ancestor); 830a96aa3bSJed Brown cid = p4est_quadrant_child_id(&ancestor); 840a96aa3bSJed Brown p4est_quadrant_corner_descendant(&ancestor, &ancestorcorner, P4EST_CHILDREN - 1 - cid, quadrant->level); 850a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant, &ancestorcorner)) return 1; 860a96aa3bSJed Brown return 0; 870a96aa3bSJed Brown } 880a96aa3bSJed Brown 89d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Fractal(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 90d71ae5a4SJacob Faibussowitsch { 910a96aa3bSJed Brown int cid; 920a96aa3bSJed Brown DMRefinePatternCtx *ctx; 930a96aa3bSJed Brown 940a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 950a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 960a96aa3bSJed Brown if (!quadrant->level) return 1; 970a96aa3bSJed Brown cid = p4est_quadrant_child_id(quadrant); 980a96aa3bSJed Brown if (ctx->fractal[cid ^ ((int)(quadrant->level % P4EST_CHILDREN))]) return 1; 990a96aa3bSJed Brown return 0; 1000a96aa3bSJed Brown } 1010a96aa3bSJed Brown 1020a96aa3bSJed Brown /* simplified from MurmurHash3 by Austin Appleby */ 1030a96aa3bSJed Brown #define DMPROT32(x, y) ((x << y) | (x >> (32 - y))) 104d71ae5a4SJacob Faibussowitsch static uint32_t DMPforestHash(const uint32_t *blocks, uint32_t nblocks) 105d71ae5a4SJacob Faibussowitsch { 1060a96aa3bSJed Brown uint32_t c1 = 0xcc9e2d51; 1070a96aa3bSJed Brown uint32_t c2 = 0x1b873593; 1080a96aa3bSJed Brown uint32_t r1 = 15; 1090a96aa3bSJed Brown uint32_t r2 = 13; 1100a96aa3bSJed Brown uint32_t m = 5; 1110a96aa3bSJed Brown uint32_t n = 0xe6546b64; 1120a96aa3bSJed Brown uint32_t hash = 0; 1130a96aa3bSJed Brown int len = nblocks * 4; 1140a96aa3bSJed Brown uint32_t i; 1150a96aa3bSJed Brown 1160a96aa3bSJed Brown for (i = 0; i < nblocks; i++) { 1170a96aa3bSJed Brown uint32_t k; 1180a96aa3bSJed Brown 1190a96aa3bSJed Brown k = blocks[i]; 1200a96aa3bSJed Brown k *= c1; 1210a96aa3bSJed Brown k = DMPROT32(k, r1); 1220a96aa3bSJed Brown k *= c2; 1230a96aa3bSJed Brown 1240a96aa3bSJed Brown hash ^= k; 1250a96aa3bSJed Brown hash = DMPROT32(hash, r2) * m + n; 1260a96aa3bSJed Brown } 1270a96aa3bSJed Brown 1280a96aa3bSJed Brown hash ^= len; 1290a96aa3bSJed Brown hash ^= (hash >> 16); 1300a96aa3bSJed Brown hash *= 0x85ebca6b; 1310a96aa3bSJed Brown hash ^= (hash >> 13); 1320a96aa3bSJed Brown hash *= 0xc2b2ae35; 1330a96aa3bSJed Brown hash ^= (hash >> 16); 1340a96aa3bSJed Brown 1350a96aa3bSJed Brown return hash; 1360a96aa3bSJed Brown } 1370a96aa3bSJed Brown 1380a96aa3bSJed Brown #if defined(UINT32_MAX) 1390a96aa3bSJed Brown #define DMP4EST_HASH_MAX UINT32_MAX 1400a96aa3bSJed Brown #else 1410a96aa3bSJed Brown #define DMP4EST_HASH_MAX ((uint32_t)0xffffffff) 1420a96aa3bSJed Brown #endif 1430a96aa3bSJed Brown 144d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Hash(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 145d71ae5a4SJacob Faibussowitsch { 1460a96aa3bSJed Brown uint32_t data[5]; 1470a96aa3bSJed Brown uint32_t result; 1480a96aa3bSJed Brown DMRefinePatternCtx *ctx; 1490a96aa3bSJed Brown 1500a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer; 1510a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 1520a96aa3bSJed Brown data[0] = ((uint32_t)quadrant->level) << 24; 1530a96aa3bSJed Brown data[1] = (uint32_t)which_tree; 1540a96aa3bSJed Brown data[2] = (uint32_t)quadrant->x; 1550a96aa3bSJed Brown data[3] = (uint32_t)quadrant->y; 1560a96aa3bSJed Brown #if defined(P4_TO_P8) 1570a96aa3bSJed Brown data[4] = (uint32_t)quadrant->z; 1580a96aa3bSJed Brown #endif 1590a96aa3bSJed Brown 1600a96aa3bSJed Brown result = DMPforestHash(data, 2 + P4EST_DIM); 1610a96aa3bSJed Brown if (((double)result / (double)DMP4EST_HASH_MAX) < ctx->hashLikelihood) return 1; 1620a96aa3bSJed Brown return 0; 1630a96aa3bSJed Brown } 1640a96aa3bSJed Brown 1650a96aa3bSJed Brown #define DMConvert_pforest_plex _infix_pforest(DMConvert, _plex) 1660a96aa3bSJed Brown static PetscErrorCode DMConvert_pforest_plex(DM, DMType, DM *); 1670a96aa3bSJed Brown 1680a96aa3bSJed Brown #define DMFTopology_pforest _append_pforest(DMFTopology) 1690a96aa3bSJed Brown typedef struct { 1700a96aa3bSJed Brown PetscInt refct; 1710a96aa3bSJed Brown p4est_connectivity_t *conn; 1720a96aa3bSJed Brown p4est_geometry_t *geom; 1730a96aa3bSJed Brown PetscInt *tree_face_to_uniq; /* p4est does not explicitly enumerate facets, but we must to keep track of labels */ 1740a96aa3bSJed Brown } DMFTopology_pforest; 1750a96aa3bSJed Brown 1760a96aa3bSJed Brown #define DM_Forest_pforest _append_pforest(DM_Forest) 1770a96aa3bSJed Brown typedef struct { 1780a96aa3bSJed Brown DMFTopology_pforest *topo; 1790a96aa3bSJed Brown p4est_t *forest; 1800a96aa3bSJed Brown p4est_ghost_t *ghost; 1810a96aa3bSJed Brown p4est_lnodes_t *lnodes; 1820a96aa3bSJed Brown PetscBool partition_for_coarsening; 1830a96aa3bSJed Brown PetscBool coarsen_hierarchy; 1840a96aa3bSJed Brown PetscBool labelsFinalized; 1850a96aa3bSJed Brown PetscBool adaptivitySuccess; 1860a96aa3bSJed Brown PetscInt cLocalStart; 1870a96aa3bSJed Brown PetscInt cLocalEnd; 1880a96aa3bSJed Brown DM plex; 1890a96aa3bSJed Brown char *ghostName; 1900a96aa3bSJed Brown PetscSF pointAdaptToSelfSF; 1910a96aa3bSJed Brown PetscSF pointSelfToAdaptSF; 1920a96aa3bSJed Brown PetscInt *pointAdaptToSelfCids; 1930a96aa3bSJed Brown PetscInt *pointSelfToAdaptCids; 1940a96aa3bSJed Brown } DM_Forest_pforest; 1950a96aa3bSJed Brown 1960a96aa3bSJed Brown #define DM_Forest_geometry_pforest _append_pforest(DM_Forest_geometry) 1970a96aa3bSJed Brown typedef struct { 1980a96aa3bSJed Brown DM base; 1990a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *); 2000a96aa3bSJed Brown void *mapCtx; 2010a96aa3bSJed Brown PetscInt coordDim; 2020a96aa3bSJed Brown p4est_geometry_t *inner; 2039371c9d4SSatish Balay } DM_Forest_geometry_pforest; 2040a96aa3bSJed Brown 2050a96aa3bSJed Brown #define GeometryMapping_pforest _append_pforest(GeometryMapping) 206d71ae5a4SJacob Faibussowitsch static void GeometryMapping_pforest(p4est_geometry_t *geom, p4est_topidx_t which_tree, const double abc[3], double xyz[3]) 207d71ae5a4SJacob Faibussowitsch { 2080a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest *)geom->user; 2090a96aa3bSJed Brown PetscReal PetscABC[3] = {0.}; 2100a96aa3bSJed Brown PetscReal PetscXYZ[3] = {0.}; 2110a96aa3bSJed Brown PetscInt i, d = PetscMin(3, geom_pforest->coordDim); 2120a96aa3bSJed Brown double ABC[3]; 2130a96aa3bSJed Brown PetscErrorCode ierr; 2140a96aa3bSJed Brown 2150a96aa3bSJed Brown (geom_pforest->inner->X)(geom_pforest->inner, which_tree, abc, ABC); 2160a96aa3bSJed Brown 2170a96aa3bSJed Brown for (i = 0; i < d; i++) PetscABC[i] = ABC[i]; 2189371c9d4SSatish Balay ierr = (geom_pforest->map)(geom_pforest->base, (PetscInt)which_tree, geom_pforest->coordDim, PetscABC, PetscXYZ, geom_pforest->mapCtx); 2199371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr); 2200a96aa3bSJed Brown for (i = 0; i < d; i++) xyz[i] = PetscXYZ[i]; 2210a96aa3bSJed Brown } 2220a96aa3bSJed Brown 2230a96aa3bSJed Brown #define GeometryDestroy_pforest _append_pforest(GeometryDestroy) 224d71ae5a4SJacob Faibussowitsch static void GeometryDestroy_pforest(p4est_geometry_t *geom) 225d71ae5a4SJacob Faibussowitsch { 2260a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest *)geom->user; 2270a96aa3bSJed Brown PetscErrorCode ierr; 2280a96aa3bSJed Brown 2290a96aa3bSJed Brown p4est_geometry_destroy(geom_pforest->inner); 2309371c9d4SSatish Balay ierr = PetscFree(geom->user); 2319371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr); 2329371c9d4SSatish Balay ierr = PetscFree(geom); 2339371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr); 2340a96aa3bSJed Brown } 2350a96aa3bSJed Brown 2360a96aa3bSJed Brown #define DMFTopologyDestroy_pforest _append_pforest(DMFTopologyDestroy) 237d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFTopologyDestroy_pforest(DMFTopology_pforest **topo) 238d71ae5a4SJacob Faibussowitsch { 2390a96aa3bSJed Brown PetscFunctionBegin; 2404ad8454bSPierre Jolivet if (!*topo) PetscFunctionReturn(PETSC_SUCCESS); 2410a96aa3bSJed Brown if (--((*topo)->refct) > 0) { 2420a96aa3bSJed Brown *topo = NULL; 2433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2440a96aa3bSJed Brown } 245792fecdfSBarry Smith if ((*topo)->geom) PetscCallP4est(p4est_geometry_destroy, ((*topo)->geom)); 246792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy, ((*topo)->conn)); 2479566063dSJacob Faibussowitsch PetscCall(PetscFree((*topo)->tree_face_to_uniq)); 2489566063dSJacob Faibussowitsch PetscCall(PetscFree(*topo)); 2490a96aa3bSJed Brown *topo = NULL; 2503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2510a96aa3bSJed Brown } 2520a96aa3bSJed Brown 2530a96aa3bSJed Brown static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *, PetscInt **); 2540a96aa3bSJed Brown 2550a96aa3bSJed Brown #define DMFTopologyCreateBrick_pforest _append_pforest(DMFTopologyCreateBrick) 256d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFTopologyCreateBrick_pforest(DM dm, PetscInt N[], PetscInt P[], PetscReal B[], DMFTopology_pforest **topo, PetscBool useMorton) 257d71ae5a4SJacob Faibussowitsch { 2580a96aa3bSJed Brown double *vertices; 2590a96aa3bSJed Brown PetscInt i, numVerts; 2600a96aa3bSJed Brown 2610a96aa3bSJed Brown PetscFunctionBegin; 26228b400f6SJacob Faibussowitsch PetscCheck(useMorton, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Lexicographic ordering not implemented yet"); 2634dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(topo)); 2640a96aa3bSJed Brown 2650a96aa3bSJed Brown (*topo)->refct = 1; 2660a96aa3bSJed Brown #if !defined(P4_TO_P8) 267792fecdfSBarry 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)); 2680a96aa3bSJed Brown #else 269792fecdfSBarry 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)); 2700a96aa3bSJed Brown #endif 2710a96aa3bSJed Brown numVerts = (*topo)->conn->num_vertices; 2720a96aa3bSJed Brown vertices = (*topo)->conn->vertices; 2730a96aa3bSJed Brown for (i = 0; i < 3 * numVerts; i++) { 2740a96aa3bSJed Brown PetscInt j = i % 3; 2750a96aa3bSJed Brown 2760a96aa3bSJed Brown vertices[i] = B[2 * j] + (vertices[i] / N[j]) * (B[2 * j + 1] - B[2 * j]); 2770a96aa3bSJed Brown } 2780a96aa3bSJed Brown (*topo)->geom = NULL; 2799566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn, &(*topo)->tree_face_to_uniq)); 2803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2810a96aa3bSJed Brown } 2820a96aa3bSJed Brown 2830a96aa3bSJed Brown #define DMFTopologyCreate_pforest _append_pforest(DMFTopologyCreate) 284d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFTopologyCreate_pforest(DM dm, DMForestTopology topologyName, DMFTopology_pforest **topo) 285d71ae5a4SJacob Faibussowitsch { 2860a96aa3bSJed Brown const char *name = (const char *)topologyName; 2870a96aa3bSJed Brown const char *prefix; 2880a96aa3bSJed Brown PetscBool isBrick, isShell, isSphere, isMoebius; 2890a96aa3bSJed Brown 2900a96aa3bSJed Brown PetscFunctionBegin; 2910a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2924f572ea9SToby Isaac PetscAssertPointer(name, 2); 2934f572ea9SToby Isaac PetscAssertPointer(topo, 3); 2949566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "brick", &isBrick)); 2959566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "shell", &isShell)); 2969566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "sphere", &isSphere)); 2979566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "moebius", &isMoebius)); 2989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 2990a96aa3bSJed Brown if (isBrick) { 3000a96aa3bSJed Brown PetscBool flgN, flgP, flgM, flgB, useMorton = PETSC_TRUE, periodic = PETSC_FALSE; 3010a96aa3bSJed Brown PetscInt N[3] = {2, 2, 2}, P[3] = {0, 0, 0}, nretN = P4EST_DIM, nretP = P4EST_DIM, nretB = 2 * P4EST_DIM, i; 3024fb89dddSMatthew 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}; 3030a96aa3bSJed Brown 3040a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_size", N, &nretN, &flgN)); 3069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_periodicity", P, &nretP, &flgP)); 3079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_bounds", B, &nretB, &flgB)); 3089566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_use_morton_curve", &useMorton, &flgM)); 3091dca8a05SBarry 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); 3101dca8a05SBarry 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); 3111dca8a05SBarry 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); 3120a96aa3bSJed Brown } 3130a96aa3bSJed Brown for (i = 0; i < P4EST_DIM; i++) { 3140a96aa3bSJed Brown P[i] = (P[i] ? DM_BOUNDARY_PERIODIC : DM_BOUNDARY_NONE); 3150a96aa3bSJed Brown periodic = (PetscBool)(P[i] || periodic); 3160a96aa3bSJed Brown if (!flgB) B[2 * i + 1] = N[i]; 3176858538eSMatthew G. Knepley if (P[i]) { 3184fb89dddSMatthew G. Knepley Lstart[i] = B[2 * i + 0]; 3194fb89dddSMatthew G. Knepley L[i] = B[2 * i + 1] - B[2 * i + 0]; 3206858538eSMatthew G. Knepley maxCell[i] = 1.1 * (L[i] / N[i]); 3216858538eSMatthew G. Knepley } 3220a96aa3bSJed Brown } 3239566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm, N, P, B, topo, useMorton)); 3244fb89dddSMatthew G. Knepley if (periodic) PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 3250a96aa3bSJed Brown } else { 3264dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(topo)); 3270a96aa3bSJed Brown 3280a96aa3bSJed Brown (*topo)->refct = 1; 329792fecdfSBarry Smith PetscCallP4estReturn((*topo)->conn, p4est_connectivity_new_byname, (name)); 3300a96aa3bSJed Brown (*topo)->geom = NULL; 3311baa6e33SBarry Smith if (isMoebius) PetscCall(DMSetCoordinateDim(dm, 3)); 3320a96aa3bSJed Brown #if defined(P4_TO_P8) 3330a96aa3bSJed Brown if (isShell) { 3340a96aa3bSJed Brown PetscReal R2 = 1., R1 = .55; 3350a96aa3bSJed Brown 3360a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_shell_outer_radius", &R2, NULL)); 3389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_shell_inner_radius", &R1, NULL)); 3390a96aa3bSJed Brown } 340792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom, p8est_geometry_new_shell, ((*topo)->conn, R2, R1)); 3410a96aa3bSJed Brown } else if (isSphere) { 3420a96aa3bSJed Brown PetscReal R2 = 1., R1 = 0.191728, R0 = 0.039856; 3430a96aa3bSJed Brown 3440a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3459566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_outer_radius", &R2, NULL)); 3469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_inner_radius", &R1, NULL)); 3479566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_core_radius", &R0, NULL)); 3480a96aa3bSJed Brown } 349792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom, p8est_geometry_new_sphere, ((*topo)->conn, R2, R1, R0)); 3500a96aa3bSJed Brown } 3510a96aa3bSJed Brown #endif 3529566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn, &(*topo)->tree_face_to_uniq)); 3530a96aa3bSJed Brown } 3543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3550a96aa3bSJed Brown } 3560a96aa3bSJed Brown 3570a96aa3bSJed Brown #define DMConvert_plex_pforest _append_pforest(DMConvert_plex) 358d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMConvert_plex_pforest(DM dm, DMType newtype, DM *pforest) 359d71ae5a4SJacob Faibussowitsch { 3600a96aa3bSJed Brown MPI_Comm comm; 3610a96aa3bSJed Brown PetscBool isPlex; 3620a96aa3bSJed Brown PetscInt dim; 3630a96aa3bSJed Brown void *ctx; 3640a96aa3bSJed Brown 3650a96aa3bSJed Brown PetscFunctionBegin; 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(PetscFree(pforest->ghostName)); 3979566063dSJacob Faibussowitsch PetscCall(DMDestroy(&pforest->plex)); 3989566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointAdaptToSelfSF)); 3999566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointSelfToAdaptSF)); 4009566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 4019566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 4029566063dSJacob Faibussowitsch PetscCall(PetscFree(forest->data)); 4033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4040a96aa3bSJed Brown } 4050a96aa3bSJed Brown 4060a96aa3bSJed Brown #define DMForestTemplate_pforest _append_pforest(DMForestTemplate) 407d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestTemplate_pforest(DM dm, DM tdm) 408d71ae5a4SJacob Faibussowitsch { 4090a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 4100a96aa3bSJed Brown DM_Forest_pforest *tpforest = (DM_Forest_pforest *)((DM_Forest *)tdm->data)->data; 4110a96aa3bSJed Brown 4120a96aa3bSJed Brown PetscFunctionBegin; 4130a96aa3bSJed Brown if (pforest->topo) pforest->topo->refct++; 414f4f49eeaSPierre Jolivet PetscCall(DMFTopologyDestroy_pforest(&tpforest->topo)); 4150a96aa3bSJed Brown tpforest->topo = pforest->topo; 4163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4170a96aa3bSJed Brown } 4180a96aa3bSJed Brown 4190a96aa3bSJed Brown #define DMPlexCreateConnectivity_pforest _append_pforest(DMPlexCreateConnectivity) 4200a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM, p4est_connectivity_t **, PetscInt **); 4210a96aa3bSJed Brown 4229371c9d4SSatish Balay typedef struct _PforestAdaptCtx { 4230a96aa3bSJed Brown PetscInt maxLevel; 4240a96aa3bSJed Brown PetscInt minLevel; 4250a96aa3bSJed Brown PetscInt currLevel; 4260a96aa3bSJed Brown PetscBool anyChange; 4279371c9d4SSatish Balay } PforestAdaptCtx; 4280a96aa3bSJed Brown 429d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_currlevel(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 430d71ae5a4SJacob Faibussowitsch { 4310a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4320a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4330a96aa3bSJed Brown PetscInt currLevel = ctx->currLevel; 4340a96aa3bSJed Brown 4350a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4360a96aa3bSJed Brown return (int)((PetscInt)quadrants[0]->level == currLevel); 4370a96aa3bSJed Brown } 4380a96aa3bSJed Brown 439d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_uniform(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 440d71ae5a4SJacob Faibussowitsch { 4410a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4420a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4430a96aa3bSJed Brown 4440a96aa3bSJed Brown return (int)((PetscInt)quadrants[0]->level > minLevel); 4450a96aa3bSJed Brown } 4460a96aa3bSJed Brown 447d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_flag_any(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 448d71ae5a4SJacob Faibussowitsch { 4490a96aa3bSJed Brown PetscInt i; 4500a96aa3bSJed Brown PetscBool any = PETSC_FALSE; 4510a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4520a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4530a96aa3bSJed Brown 4540a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4550a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 4560a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_KEEP) { 4570a96aa3bSJed Brown any = PETSC_FALSE; 4580a96aa3bSJed Brown break; 4590a96aa3bSJed Brown } 4600a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_COARSEN) { 4610a96aa3bSJed Brown any = PETSC_TRUE; 4620a96aa3bSJed Brown break; 4630a96aa3bSJed Brown } 4640a96aa3bSJed Brown } 4650a96aa3bSJed Brown return any ? 1 : 0; 4660a96aa3bSJed Brown } 4670a96aa3bSJed Brown 468d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_flag_all(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 469d71ae5a4SJacob Faibussowitsch { 4700a96aa3bSJed Brown PetscInt i; 4710a96aa3bSJed Brown PetscBool all = PETSC_TRUE; 4720a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4730a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4740a96aa3bSJed Brown 4750a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4760a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 4770a96aa3bSJed Brown if (quadrants[i]->p.user_int != DM_ADAPT_COARSEN) { 4780a96aa3bSJed Brown all = PETSC_FALSE; 4790a96aa3bSJed Brown break; 4800a96aa3bSJed Brown } 4810a96aa3bSJed Brown } 4820a96aa3bSJed Brown return all ? 1 : 0; 4830a96aa3bSJed Brown } 4840a96aa3bSJed Brown 485d71ae5a4SJacob Faibussowitsch static void pforest_init_determine(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 486d71ae5a4SJacob Faibussowitsch { 4870a96aa3bSJed Brown quadrant->p.user_int = DM_ADAPT_DETERMINE; 4880a96aa3bSJed Brown } 4890a96aa3bSJed Brown 490d71ae5a4SJacob Faibussowitsch static int pforest_refine_uniform(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 491d71ae5a4SJacob Faibussowitsch { 4920a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 4930a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 4940a96aa3bSJed Brown 4954ad8454bSPierre Jolivet return (PetscInt)quadrant->level < maxLevel; 4960a96aa3bSJed Brown } 4970a96aa3bSJed Brown 498d71ae5a4SJacob Faibussowitsch static int pforest_refine_flag(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 499d71ae5a4SJacob Faibussowitsch { 5000a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer; 5010a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 5020a96aa3bSJed Brown 5030a96aa3bSJed Brown if ((PetscInt)quadrant->level >= maxLevel) return 0; 5040a96aa3bSJed Brown 5054ad8454bSPierre Jolivet return quadrant->p.user_int == DM_ADAPT_REFINE; 5060a96aa3bSJed Brown } 5070a96aa3bSJed Brown 508d71ae5a4SJacob 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) 509d71ae5a4SJacob Faibussowitsch { 5100a96aa3bSJed Brown PetscMPIInt rank = p4estFrom->mpirank; 5110a96aa3bSJed Brown p4est_topidx_t t; 5120a96aa3bSJed Brown PetscInt toFineLeaves = 0, fromFineLeaves = 0; 5130a96aa3bSJed Brown 5140a96aa3bSJed Brown PetscFunctionBegin; 5155a96e07bSStefano Zampini /* -Wmaybe-uninitialized */ 5165a96e07bSStefano Zampini *toFineLeavesCount = 0; 5175a96e07bSStefano Zampini *fromFineLeavesCount = 0; 5180a96aa3bSJed Brown for (t = flt; t <= llt; t++) { /* count roots and leaves */ 5190a96aa3bSJed Brown p4est_tree_t *treeFrom = &(((p4est_tree_t *)p4estFrom->trees->array)[t]); 5200a96aa3bSJed Brown p4est_tree_t *treeTo = &(((p4est_tree_t *)p4estTo->trees->array)[t]); 5210a96aa3bSJed Brown p4est_quadrant_t *firstFrom = &treeFrom->first_desc; 5220a96aa3bSJed Brown p4est_quadrant_t *firstTo = &treeTo->first_desc; 5230a96aa3bSJed Brown PetscInt numFrom = (PetscInt)treeFrom->quadrants.elem_count; 5240a96aa3bSJed Brown PetscInt numTo = (PetscInt)treeTo->quadrants.elem_count; 5250a96aa3bSJed Brown p4est_quadrant_t *quadsFrom = (p4est_quadrant_t *)treeFrom->quadrants.array; 5260a96aa3bSJed Brown p4est_quadrant_t *quadsTo = (p4est_quadrant_t *)treeTo->quadrants.array; 5270a96aa3bSJed Brown PetscInt currentFrom, currentTo; 5280a96aa3bSJed Brown PetscInt treeOffsetFrom = (PetscInt)treeFrom->quadrants_offset; 5290a96aa3bSJed Brown PetscInt treeOffsetTo = (PetscInt)treeTo->quadrants_offset; 5300a96aa3bSJed Brown int comp; 5310a96aa3bSJed Brown 532792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (firstFrom, firstTo)); 53328b400f6SJacob Faibussowitsch PetscCheck(comp, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "non-matching partitions"); 5340a96aa3bSJed Brown 5350a96aa3bSJed Brown for (currentFrom = 0, currentTo = 0; currentFrom < numFrom && currentTo < numTo;) { 5360a96aa3bSJed Brown p4est_quadrant_t *quadFrom = &quadsFrom[currentFrom]; 5370a96aa3bSJed Brown p4est_quadrant_t *quadTo = &quadsTo[currentTo]; 5380a96aa3bSJed Brown 5390a96aa3bSJed Brown if (quadFrom->level == quadTo->level) { 5400a96aa3bSJed Brown if (toLeaves) { 5410a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5420a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5430a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5440a96aa3bSJed Brown } 5450a96aa3bSJed Brown toFineLeaves++; 5460a96aa3bSJed Brown currentFrom++; 5470a96aa3bSJed Brown currentTo++; 5480a96aa3bSJed Brown } else { 5490a96aa3bSJed Brown int fromIsAncestor; 5500a96aa3bSJed Brown 551792fecdfSBarry Smith PetscCallP4estReturn(fromIsAncestor, p4est_quadrant_is_ancestor, (quadFrom, quadTo)); 5520a96aa3bSJed Brown if (fromIsAncestor) { 5530a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5540a96aa3bSJed Brown 5550a96aa3bSJed Brown if (toLeaves) { 5560a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5570a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5580a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5590a96aa3bSJed Brown } 5600a96aa3bSJed Brown toFineLeaves++; 5610a96aa3bSJed Brown currentTo++; 562792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant, (quadFrom, &lastDesc, quadTo->level)); 563792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (quadTo, &lastDesc)); 5640a96aa3bSJed Brown if (comp) currentFrom++; 5650a96aa3bSJed Brown } else { 5660a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5670a96aa3bSJed Brown 5680a96aa3bSJed Brown if (fromLeaves) { 5690a96aa3bSJed Brown fromLeaves[fromFineLeaves] = currentFrom + treeOffsetFrom + FromOffset; 5700a96aa3bSJed Brown toRoots[fromFineLeaves].rank = rank; 5710a96aa3bSJed Brown toRoots[fromFineLeaves].index = currentTo + treeOffsetTo + ToOffset; 5720a96aa3bSJed Brown } 5730a96aa3bSJed Brown fromFineLeaves++; 5740a96aa3bSJed Brown currentFrom++; 575792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant, (quadTo, &lastDesc, quadFrom->level)); 576792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (quadFrom, &lastDesc)); 5770a96aa3bSJed Brown if (comp) currentTo++; 5780a96aa3bSJed Brown } 5790a96aa3bSJed Brown } 5800a96aa3bSJed Brown } 5810a96aa3bSJed Brown } 5820a96aa3bSJed Brown *toFineLeavesCount = toFineLeaves; 5830a96aa3bSJed Brown *fromFineLeavesCount = fromFineLeaves; 5843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5850a96aa3bSJed Brown } 5860a96aa3bSJed Brown 5870a96aa3bSJed Brown /* Compute the maximum level across all the trees */ 588d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetRefinementLevel(DM dm, PetscInt *lev) 589d71ae5a4SJacob Faibussowitsch { 5900a96aa3bSJed Brown p4est_topidx_t t, flt, llt; 5910a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 5920a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 5930a96aa3bSJed Brown PetscInt maxlevelloc = 0; 5940a96aa3bSJed Brown p4est_t *p4est; 5950a96aa3bSJed Brown 5960a96aa3bSJed Brown PetscFunctionBegin; 59728b400f6SJacob Faibussowitsch PetscCheck(pforest, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing DM_Forest_pforest"); 59828b400f6SJacob Faibussowitsch PetscCheck(pforest->forest, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing p4est_t"); 5990a96aa3bSJed Brown p4est = pforest->forest; 6000a96aa3bSJed Brown flt = p4est->first_local_tree; 6010a96aa3bSJed Brown llt = p4est->last_local_tree; 6020a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 6030a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4est->trees->array)[t]); 6040a96aa3bSJed Brown maxlevelloc = PetscMax((PetscInt)tree->maxlevel, maxlevelloc); 6050a96aa3bSJed Brown } 6061c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&maxlevelloc, lev, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 6073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6080a96aa3bSJed Brown } 6090a96aa3bSJed Brown 6100a96aa3bSJed Brown /* Puts identity in coarseToFine */ 6110a96aa3bSJed Brown /* assumes a matching partition */ 612d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestComputeLocalCellTransferSF(MPI_Comm comm, p4est_t *p4estFrom, PetscInt FromOffset, p4est_t *p4estTo, PetscInt ToOffset, PetscSF *fromCoarseToFine, PetscSF *toCoarseFromFine) 613d71ae5a4SJacob Faibussowitsch { 6140a96aa3bSJed Brown p4est_topidx_t flt, llt; 6150a96aa3bSJed Brown PetscSF fromCoarse, toCoarse; 6160a96aa3bSJed Brown PetscInt numRootsFrom, numRootsTo, numLeavesFrom, numLeavesTo; 6170a96aa3bSJed Brown PetscInt *fromLeaves = NULL, *toLeaves = NULL; 6180a96aa3bSJed Brown PetscSFNode *fromRoots = NULL, *toRoots = NULL; 6190a96aa3bSJed Brown 6200a96aa3bSJed Brown PetscFunctionBegin; 6210a96aa3bSJed Brown flt = p4estFrom->first_local_tree; 6220a96aa3bSJed Brown llt = p4estFrom->last_local_tree; 6239566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &fromCoarse)); 62448a46eb9SPierre Jolivet if (toCoarseFromFine) PetscCall(PetscSFCreate(comm, &toCoarse)); 6250a96aa3bSJed Brown numRootsFrom = p4estFrom->local_num_quadrants + FromOffset; 6260a96aa3bSJed Brown numRootsTo = p4estTo->local_num_quadrants + ToOffset; 6279566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom, FromOffset, p4estTo, ToOffset, flt, llt, &numLeavesTo, NULL, NULL, &numLeavesFrom, NULL, NULL)); 6289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo, &toLeaves)); 6299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo, &fromRoots)); 6300a96aa3bSJed Brown if (toCoarseFromFine) { 6319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom, &fromLeaves)); 6329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom, &fromRoots)); 6330a96aa3bSJed Brown } 6349566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom, FromOffset, p4estTo, ToOffset, flt, llt, &numLeavesTo, toLeaves, fromRoots, &numLeavesFrom, fromLeaves, toRoots)); 6350a96aa3bSJed Brown if (!ToOffset && (numLeavesTo == numRootsTo)) { /* compress */ 6369566063dSJacob Faibussowitsch PetscCall(PetscFree(toLeaves)); 6379566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(fromCoarse, numRootsFrom, numLeavesTo, NULL, PETSC_OWN_POINTER, fromRoots, PETSC_OWN_POINTER)); 6381baa6e33SBarry Smith } else PetscCall(PetscSFSetGraph(fromCoarse, numRootsFrom, numLeavesTo, toLeaves, PETSC_OWN_POINTER, fromRoots, PETSC_OWN_POINTER)); 6390a96aa3bSJed Brown *fromCoarseToFine = fromCoarse; 6400a96aa3bSJed Brown if (toCoarseFromFine) { 6419566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(toCoarse, numRootsTo, numLeavesFrom, fromLeaves, PETSC_OWN_POINTER, toRoots, PETSC_OWN_POINTER)); 6420a96aa3bSJed Brown *toCoarseFromFine = toCoarse; 6430a96aa3bSJed Brown } 6443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6450a96aa3bSJed Brown } 6460a96aa3bSJed Brown 6470a96aa3bSJed Brown /* range of processes whose B sections overlap this ranks A section */ 648d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestComputeOverlappingRanks(PetscMPIInt size, PetscMPIInt rank, p4est_t *p4estA, p4est_t *p4estB, PetscInt *startB, PetscInt *endB) 649d71ae5a4SJacob Faibussowitsch { 650f4f49eeaSPierre Jolivet p4est_quadrant_t *myCoarseStart = &p4estA->global_first_position[rank]; 651f4f49eeaSPierre Jolivet p4est_quadrant_t *myCoarseEnd = &p4estA->global_first_position[rank + 1]; 6520a96aa3bSJed Brown p4est_quadrant_t *globalFirstB = p4estB->global_first_position; 6530a96aa3bSJed Brown 6540a96aa3bSJed Brown PetscFunctionBegin; 6550a96aa3bSJed Brown *startB = -1; 6560a96aa3bSJed Brown *endB = -1; 6570a96aa3bSJed Brown if (p4estA->local_num_quadrants) { 6580a96aa3bSJed Brown PetscInt lo, hi, guess; 6590a96aa3bSJed Brown /* binary search to find interval containing myCoarseStart */ 6600a96aa3bSJed Brown lo = 0; 6610a96aa3bSJed Brown hi = size; 6620a96aa3bSJed Brown guess = rank; 6630a96aa3bSJed Brown while (1) { 6640a96aa3bSJed Brown int startCompMy, myCompEnd; 6650a96aa3bSJed Brown 666792fecdfSBarry Smith PetscCallP4estReturn(startCompMy, p4est_quadrant_compare_piggy, (&globalFirstB[guess], myCoarseStart)); 667792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd, p4est_quadrant_compare_piggy, (myCoarseStart, &globalFirstB[guess + 1])); 6680a96aa3bSJed Brown if (startCompMy <= 0 && myCompEnd < 0) { 6690a96aa3bSJed Brown *startB = guess; 6700a96aa3bSJed Brown break; 6710a96aa3bSJed Brown } else if (startCompMy > 0) { /* guess is to high */ 6720a96aa3bSJed Brown hi = guess; 6730a96aa3bSJed Brown } else { /* guess is to low */ 6740a96aa3bSJed Brown lo = guess + 1; 6750a96aa3bSJed Brown } 6760a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6770a96aa3bSJed Brown } 6780a96aa3bSJed Brown /* reset bounds, but not guess */ 6790a96aa3bSJed Brown lo = 0; 6800a96aa3bSJed Brown hi = size; 6810a96aa3bSJed Brown while (1) { 6820a96aa3bSJed Brown int startCompMy, myCompEnd; 6830a96aa3bSJed Brown 684792fecdfSBarry Smith PetscCallP4estReturn(startCompMy, p4est_quadrant_compare_piggy, (&globalFirstB[guess], myCoarseEnd)); 685792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd, p4est_quadrant_compare_piggy, (myCoarseEnd, &globalFirstB[guess + 1])); 6860a96aa3bSJed Brown if (startCompMy < 0 && myCompEnd <= 0) { /* notice that the comparison operators are different from above */ 6870a96aa3bSJed Brown *endB = guess + 1; 6880a96aa3bSJed Brown break; 6890a96aa3bSJed Brown } else if (startCompMy >= 0) { /* guess is to high */ 6900a96aa3bSJed Brown hi = guess; 6910a96aa3bSJed Brown } else { /* guess is to low */ 6920a96aa3bSJed Brown lo = guess + 1; 6930a96aa3bSJed Brown } 6940a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6950a96aa3bSJed Brown } 6960a96aa3bSJed Brown } 6973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6980a96aa3bSJed Brown } 6990a96aa3bSJed Brown 7000a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM, DM *); 7010a96aa3bSJed Brown 7020a96aa3bSJed Brown #define DMSetUp_pforest _append_pforest(DMSetUp) 703d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetUp_pforest(DM dm) 704d71ae5a4SJacob Faibussowitsch { 7050a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 7060a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 7070a96aa3bSJed Brown DM base, adaptFrom; 7080a96aa3bSJed Brown DMForestTopology topoName; 7090a96aa3bSJed Brown PetscSF preCoarseToFine = NULL, coarseToPreFine = NULL; 7100a96aa3bSJed Brown PforestAdaptCtx ctx; 7110a96aa3bSJed Brown 7120a96aa3bSJed Brown PetscFunctionBegin; 7130a96aa3bSJed Brown ctx.minLevel = PETSC_MAX_INT; 7140a96aa3bSJed Brown ctx.maxLevel = 0; 7150a96aa3bSJed Brown ctx.currLevel = 0; 7160a96aa3bSJed Brown ctx.anyChange = PETSC_FALSE; 7170a96aa3bSJed Brown /* sanity check */ 7189566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm, &adaptFrom)); 7199566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 7209566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm, &topoName)); 7211dca8a05SBarry 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"); 7220a96aa3bSJed Brown 7230a96aa3bSJed Brown /* === Step 1: DMFTopology === */ 7240a96aa3bSJed Brown if (adaptFrom) { /* reference already created topology */ 7250a96aa3bSJed Brown PetscBool ispforest; 7260a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest *)adaptFrom->data; 7270a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest *)aforest->data; 7280a96aa3bSJed Brown 7299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)adaptFrom, DMPFOREST, &ispforest)); 73028b400f6SJacob Faibussowitsch PetscCheck(ispforest, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NOTSAMETYPE, "Trying to adapt from %s, which is not %s", ((PetscObject)adaptFrom)->type_name, DMPFOREST); 73128b400f6SJacob Faibussowitsch PetscCheck(apforest->topo, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "The pre-adaptation forest must have a topology"); 7329566063dSJacob Faibussowitsch PetscCall(DMSetUp(adaptFrom)); 7339566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 7349566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm, &topoName)); 7350a96aa3bSJed Brown } else if (base) { /* construct a connectivity from base */ 7360a96aa3bSJed Brown PetscBool isPlex, isDA; 7370a96aa3bSJed Brown 7389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)base, &topoName)); 7399566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm, topoName)); 7409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base, DMPLEX, &isPlex)); 7419566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base, DMDA, &isDA)); 7420a96aa3bSJed Brown if (isPlex) { 7430a96aa3bSJed Brown MPI_Comm comm = PetscObjectComm((PetscObject)dm); 7440a96aa3bSJed Brown PetscInt depth; 7450a96aa3bSJed Brown PetscMPIInt size; 7460a96aa3bSJed Brown p4est_connectivity_t *conn = NULL; 7470a96aa3bSJed Brown DMFTopology_pforest *topo; 7480a96aa3bSJed Brown PetscInt *tree_face_to_uniq = NULL; 7490a96aa3bSJed Brown 7509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(base, &depth)); 7510a96aa3bSJed Brown if (depth == 1) { 7520a96aa3bSJed Brown DM connDM; 7530a96aa3bSJed Brown 7549566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(base, &connDM)); 7550a96aa3bSJed Brown base = connDM; 7569566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm, base)); 7579566063dSJacob Faibussowitsch PetscCall(DMDestroy(&connDM)); 75863a3b9bcSJacob 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); 7599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 7600a96aa3bSJed Brown if (size > 1) { 7610a96aa3bSJed Brown DM dmRedundant; 7620a96aa3bSJed Brown PetscSF sf; 7630a96aa3bSJed Brown 7649566063dSJacob Faibussowitsch PetscCall(DMPlexGetRedundantDM(base, &sf, &dmRedundant)); 76528b400f6SJacob Faibussowitsch PetscCheck(dmRedundant, comm, PETSC_ERR_PLIB, "Could not create redundant DM"); 7669566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dmRedundant, "_base_migration_sf", (PetscObject)sf)); 7679566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 7680a96aa3bSJed Brown base = dmRedundant; 7699566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm, base)); 7709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRedundant)); 7710a96aa3bSJed Brown } 7729566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(base, NULL, "-dm_p4est_base_view")); 7739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConnectivity_pforest(base, &conn, &tree_face_to_uniq)); 7744dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&topo)); 7750a96aa3bSJed Brown topo->refct = 1; 7760a96aa3bSJed Brown topo->conn = conn; 7770a96aa3bSJed Brown topo->geom = NULL; 7780a96aa3bSJed Brown { 7790a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *); 7800a96aa3bSJed Brown void *mapCtx; 7810a96aa3bSJed Brown 7829566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx)); 7830a96aa3bSJed Brown if (map) { 7840a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest; 7850a96aa3bSJed Brown p4est_geometry_t *geom; 7860a96aa3bSJed Brown 7879566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom_pforest)); 7889566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &geom_pforest->coordDim)); 7890a96aa3bSJed Brown geom_pforest->map = map; 7900a96aa3bSJed Brown geom_pforest->mapCtx = mapCtx; 791792fecdfSBarry Smith PetscCallP4estReturn(geom_pforest->inner, p4est_geometry_new_connectivity, (conn)); 7929566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom)); 7930a96aa3bSJed Brown geom->name = topoName; 7940a96aa3bSJed Brown geom->user = geom_pforest; 7950a96aa3bSJed Brown geom->X = GeometryMapping_pforest; 7960a96aa3bSJed Brown geom->destroy = GeometryDestroy_pforest; 7970a96aa3bSJed Brown topo->geom = geom; 7980a96aa3bSJed Brown } 7990a96aa3bSJed Brown } 8000a96aa3bSJed Brown topo->tree_face_to_uniq = tree_face_to_uniq; 8010a96aa3bSJed Brown pforest->topo = topo; 80228b400f6SJacob Faibussowitsch } else PetscCheck(!isDA, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Not implemented yet"); 8030a96aa3bSJed Brown #if 0 8040a96aa3bSJed Brown PetscInt N[3], P[3]; 8050a96aa3bSJed Brown 8060a96aa3bSJed Brown /* get the sizes, periodicities */ 8070a96aa3bSJed Brown /* ... */ 8080a96aa3bSJed Brown /* don't use Morton order */ 8099566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm,N,P,&pforest->topo,PETSC_FALSE)); 8100a96aa3bSJed Brown #endif 8110a96aa3bSJed Brown { 8120a96aa3bSJed Brown PetscInt numLabels, l; 8130a96aa3bSJed Brown 8149566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(base, &numLabels)); 8150a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 8160a96aa3bSJed Brown PetscBool isDepth, isGhost, isVTK, isDim, isCellType; 8170a96aa3bSJed Brown DMLabel label, labelNew; 8180a96aa3bSJed Brown PetscInt defVal; 8190a96aa3bSJed Brown const char *name; 8200a96aa3bSJed Brown 8219566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(base, l, &name)); 8229566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(base, l, &label)); 8239566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 8240a96aa3bSJed Brown if (isDepth) continue; 8259566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "dim", &isDim)); 8260a96aa3bSJed Brown if (isDim) continue; 8279566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 8280a96aa3bSJed Brown if (isCellType) continue; 8299566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 8300a96aa3bSJed Brown if (isGhost) continue; 8319566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 8320a96aa3bSJed Brown if (isVTK) continue; 8339566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 8349566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &labelNew)); 8359566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defVal)); 8369566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew, defVal)); 8370a96aa3bSJed Brown } 8380a96aa3bSJed Brown /* map dm points (internal plex) to base 8390a96aa3bSJed Brown we currently create the subpoint_map for the entire hierarchy, starting from the finest forest 8400a96aa3bSJed Brown and propagating back to the coarsest 8410a96aa3bSJed Brown This is not an optimal approach, since we need the map only on the coarsest level 8420a96aa3bSJed Brown during DMForestTransferVecFromBase */ 8439566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &l)); 84448a46eb9SPierre Jolivet if (!l) PetscCall(DMCreateLabel(dm, "_forest_base_subpoint_map")); 8450a96aa3bSJed Brown } 8460a96aa3bSJed Brown } else { /* construct from topology name */ 8470a96aa3bSJed Brown DMFTopology_pforest *topo; 8480a96aa3bSJed Brown 8499566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreate_pforest(dm, topoName, &topo)); 8500a96aa3bSJed Brown pforest->topo = topo; 8510a96aa3bSJed Brown /* TODO: construct base? */ 8520a96aa3bSJed Brown } 8530a96aa3bSJed Brown 8540a96aa3bSJed Brown /* === Step 2: get the leaves of the forest === */ 8550a96aa3bSJed Brown if (adaptFrom) { /* start with the old forest */ 8560a96aa3bSJed Brown DMLabel adaptLabel; 8570a96aa3bSJed Brown PetscInt defaultValue; 8580a96aa3bSJed Brown PetscInt numValues, numValuesGlobal, cLocalStart, count; 8590a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest *)adaptFrom->data; 8600a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest *)aforest->data; 8610a96aa3bSJed Brown PetscBool computeAdaptSF; 8620a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 8630a96aa3bSJed Brown 8640a96aa3bSJed Brown flt = apforest->forest->first_local_tree; 8650a96aa3bSJed Brown llt = apforest->forest->last_local_tree; 8660a96aa3bSJed Brown cLocalStart = apforest->cLocalStart; 8679566063dSJacob Faibussowitsch PetscCall(DMForestGetComputeAdaptivitySF(dm, &computeAdaptSF)); 868792fecdfSBarry Smith PetscCallP4estReturn(pforest->forest, p4est_copy, (apforest->forest, 0)); /* 0 indicates no data copying */ 8699566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm, &adaptLabel)); 8700a96aa3bSJed Brown if (adaptLabel) { 8710a96aa3bSJed Brown /* apply the refinement/coarsening by flags, plus minimum/maximum refinement */ 8729566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(adaptLabel, &numValues)); 873712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &numValuesGlobal, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)adaptFrom))); 8749566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(adaptLabel, &defaultValue)); 8750a96aa3bSJed Brown if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN_LAST) { /* uniform coarsen of the last level only (equivalent to DM_ADAPT_COARSEN for conforming grids) */ 8769566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel)); 8779566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm, &ctx.currLevel)); 8780a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 879792fecdfSBarry Smith PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_currlevel, NULL)); 8800a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 881792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 8820a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 88348a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), pforest->forest, 0, apforest->forest, apforest->cLocalStart, &coarseToPreFine, NULL)); 8840a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN) { /* uniform coarsen */ 8859566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel)); 8860a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 887792fecdfSBarry Smith PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_uniform, NULL)); 8880a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 889792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 8900a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 89148a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), pforest->forest, 0, apforest->forest, apforest->cLocalStart, &coarseToPreFine, NULL)); 8920a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_REFINE) { /* uniform refine */ 8939566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &ctx.maxLevel)); 8940a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 895792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 0, pforest_refine_uniform, NULL)); 8960a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 897792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 8980a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 89948a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), apforest->forest, apforest->cLocalStart, pforest->forest, 0, &preCoarseToFine, NULL)); 9000a96aa3bSJed Brown } else if (numValuesGlobal) { 9010a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 9020a96aa3bSJed Brown PetscInt *cellFlags; 9030a96aa3bSJed Brown DMForestAdaptivityStrategy strategy; 9040a96aa3bSJed Brown PetscSF cellSF; 9050a96aa3bSJed Brown PetscInt c, cStart, cEnd; 9060a96aa3bSJed Brown PetscBool adaptAny; 9070a96aa3bSJed Brown 9089566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &ctx.maxLevel)); 9099566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel)); 9109566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityStrategy(dm, &strategy)); 9119566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(strategy, "any", 3, &adaptAny)); 9129566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(adaptFrom, &cStart, &cEnd)); 9139566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(adaptFrom, &cellSF)); 9149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cStart, &cellFlags)); 9159566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; c++) PetscCall(DMLabelGetValue(adaptLabel, c, &cellFlags[c - cStart])); 9160a96aa3bSJed Brown if (cellSF) { 9170a96aa3bSJed Brown if (adaptAny) { 9189566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MAX)); 9199566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MAX)); 9200a96aa3bSJed Brown } else { 9219566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MIN)); 9229566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MIN)); 9230a96aa3bSJed Brown } 9240a96aa3bSJed Brown } 9250a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9260a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4est->trees->array)[t]); 9270a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count, i; 9280a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 9290a96aa3bSJed Brown 9300a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9310a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9320a96aa3bSJed Brown q->p.user_int = cellFlags[count++]; 9330a96aa3bSJed Brown } 9340a96aa3bSJed Brown } 9359566063dSJacob Faibussowitsch PetscCall(PetscFree(cellFlags)); 9360a96aa3bSJed Brown 9370a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx; 938792fecdfSBarry Smith if (adaptAny) PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_flag_any, pforest_init_determine)); 939792fecdfSBarry Smith else PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_flag_all, pforest_init_determine)); 940792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 0, pforest_refine_flag, NULL)); 9410a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 942792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 94348a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), apforest->forest, apforest->cLocalStart, pforest->forest, 0, &preCoarseToFine, &coarseToPreFine)); 9440a96aa3bSJed Brown } 9450a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9460a96aa3bSJed Brown p4est_tree_t *atree = &(((p4est_tree_t *)apforest->forest->trees->array)[t]); 9470a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)pforest->forest->trees->array)[t]); 9480a96aa3bSJed Brown PetscInt anumQuads = (PetscInt)atree->quadrants.elem_count, i; 9490a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 9500a96aa3bSJed Brown p4est_quadrant_t *aquads = (p4est_quadrant_t *)atree->quadrants.array; 9510a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 9520a96aa3bSJed Brown 9530a96aa3bSJed Brown if (anumQuads != numQuads) { 9540a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9550a96aa3bSJed Brown } else { 9560a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9570a96aa3bSJed Brown p4est_quadrant_t *aq = &aquads[i]; 9580a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9590a96aa3bSJed Brown 9600a96aa3bSJed Brown if (aq->level != q->level) { 9610a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9620a96aa3bSJed Brown break; 9630a96aa3bSJed Brown } 9640a96aa3bSJed Brown } 9650a96aa3bSJed Brown } 966ad540459SPierre Jolivet if (ctx.anyChange) break; 9670a96aa3bSJed Brown } 9680a96aa3bSJed Brown } 9690a96aa3bSJed Brown { 9700a96aa3bSJed Brown PetscInt numLabels, l; 9710a96aa3bSJed Brown 9729566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(adaptFrom, &numLabels)); 9730a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 9740a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 9750a96aa3bSJed Brown DMLabel label, labelNew; 9760a96aa3bSJed Brown PetscInt defVal; 9770a96aa3bSJed Brown const char *name; 9780a96aa3bSJed Brown 9799566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(adaptFrom, l, &name)); 9809566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(adaptFrom, l, &label)); 9819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 9820a96aa3bSJed Brown if (isDepth) continue; 9839566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 9840a96aa3bSJed Brown if (isCellType) continue; 9859566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 9860a96aa3bSJed Brown if (isGhost) continue; 9879566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 9880a96aa3bSJed Brown if (isVTK) continue; 9899566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 9909566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &labelNew)); 9919566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defVal)); 9929566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew, defVal)); 9930a96aa3bSJed Brown } 9940a96aa3bSJed Brown } 9950a96aa3bSJed Brown } else { /* initial */ 9960a96aa3bSJed Brown PetscInt initLevel, minLevel; 99766c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI) 99866c0a4b5SToby Isaac sc_MPI_Comm comm = sc_MPI_COMM_WORLD; 99966c0a4b5SToby Isaac #else 100066c0a4b5SToby Isaac MPI_Comm comm = PetscObjectComm((PetscObject)dm); 100166c0a4b5SToby Isaac #endif 10020a96aa3bSJed Brown 10039566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm, &initLevel)); 10049566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel)); 10059371c9d4SSatish Balay PetscCallP4estReturn(pforest->forest, p4est_new_ext, 10069371c9d4SSatish Balay (comm, pforest->topo->conn, 0, /* minimum number of quadrants per processor */ 10070a96aa3bSJed Brown initLevel, /* level of refinement */ 10080a96aa3bSJed Brown 1, /* uniform refinement */ 10090a96aa3bSJed Brown 0, /* we don't allocate any per quadrant data */ 10100a96aa3bSJed Brown NULL, /* there is no special quadrant initialization */ 10110a96aa3bSJed Brown (void *)dm)); /* this dm is the user context */ 10120a96aa3bSJed Brown 10130a96aa3bSJed Brown if (initLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 10140a96aa3bSJed Brown if (dm->setfromoptionscalled) { 10150a96aa3bSJed Brown PetscBool flgPattern, flgFractal; 10160a96aa3bSJed Brown PetscInt corner = 0; 10170a96aa3bSJed Brown PetscInt corners[P4EST_CHILDREN], ncorner = P4EST_CHILDREN; 10180a96aa3bSJed Brown PetscReal likelihood = 1. / P4EST_DIM; 10190a96aa3bSJed Brown PetscInt pattern; 10200a96aa3bSJed Brown const char *prefix; 10210a96aa3bSJed Brown 10229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 10239566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEList(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_pattern", DMRefinePatternName, PATTERN_COUNT, &pattern, &flgPattern)); 10249566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_corner", &corner, NULL)); 10259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_fractal_corners", corners, &ncorner, &flgFractal)); 10269566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_hash_likelihood", &likelihood, NULL)); 10270a96aa3bSJed Brown 10280a96aa3bSJed Brown if (flgPattern) { 10290a96aa3bSJed Brown DMRefinePatternCtx *ctx; 10300a96aa3bSJed Brown PetscInt maxLevel; 10310a96aa3bSJed Brown 10329566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &maxLevel)); 10334dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ctx)); 10340a96aa3bSJed Brown ctx->maxLevel = PetscMin(maxLevel, P4EST_QMAXLEVEL); 10350a96aa3bSJed Brown if (initLevel + ctx->maxLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 10360a96aa3bSJed Brown switch (pattern) { 10370a96aa3bSJed Brown case PATTERN_HASH: 10380a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Hash; 10390a96aa3bSJed Brown ctx->hashLikelihood = likelihood; 10400a96aa3bSJed Brown break; 10410a96aa3bSJed Brown case PATTERN_CORNER: 10420a96aa3bSJed Brown ctx->corner = corner; 10430a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Corner; 10440a96aa3bSJed Brown break; 1045d71ae5a4SJacob Faibussowitsch case PATTERN_CENTER: 1046d71ae5a4SJacob Faibussowitsch ctx->refine_fn = DMRefinePattern_Center; 1047d71ae5a4SJacob Faibussowitsch break; 10480a96aa3bSJed Brown case PATTERN_FRACTAL: 10490a96aa3bSJed Brown if (flgFractal) { 10500a96aa3bSJed Brown PetscInt i; 10510a96aa3bSJed Brown 10520a96aa3bSJed Brown for (i = 0; i < ncorner; i++) ctx->fractal[corners[i]] = PETSC_TRUE; 10530a96aa3bSJed Brown } else { 10540a96aa3bSJed Brown #if !defined(P4_TO_P8) 10550a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[1] = ctx->fractal[2] = PETSC_TRUE; 10560a96aa3bSJed Brown #else 10570a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[3] = ctx->fractal[5] = ctx->fractal[6] = PETSC_TRUE; 10580a96aa3bSJed Brown #endif 10590a96aa3bSJed Brown } 10600a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Fractal; 10610a96aa3bSJed Brown break; 1062d71ae5a4SJacob Faibussowitsch default: 1063d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Not a valid refinement pattern"); 10640a96aa3bSJed Brown } 10650a96aa3bSJed Brown 10660a96aa3bSJed Brown pforest->forest->user_pointer = (void *)ctx; 1067792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 1, ctx->refine_fn, NULL)); 1068792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL)); 10699566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 10700a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm; 10710a96aa3bSJed Brown } 10720a96aa3bSJed Brown } 10730a96aa3bSJed Brown } 10740a96aa3bSJed Brown if (pforest->coarsen_hierarchy) { 10750a96aa3bSJed Brown PetscInt initLevel, currLevel, minLevel; 10760a96aa3bSJed Brown 10779566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm, &currLevel)); 10789566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm, &initLevel)); 10799566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel)); 1080156acca6SStefano Zampini /* allow using PCMG and SNESFAS */ 1081156acca6SStefano Zampini PetscCall(DMSetRefineLevel(dm, currLevel - minLevel)); 10820a96aa3bSJed Brown if (currLevel > minLevel) { 10830a96aa3bSJed Brown DM_Forest_pforest *coarse_pforest; 10840a96aa3bSJed Brown DMLabel coarsen; 10850a96aa3bSJed Brown DM coarseDM; 10860a96aa3bSJed Brown 10879566063dSJacob Faibussowitsch PetscCall(DMForestTemplate(dm, MPI_COMM_NULL, &coarseDM)); 10889566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityPurpose(coarseDM, DM_ADAPT_COARSEN)); 10899566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "coarsen", &coarsen)); 10909566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(coarsen, DM_ADAPT_COARSEN)); 10919566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityLabel(coarseDM, coarsen)); 10929566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&coarsen)); 10939566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 10949566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 10950a96aa3bSJed Brown initLevel = currLevel == initLevel ? initLevel - 1 : initLevel; 10969566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(coarseDM, initLevel)); 10979566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(coarseDM, minLevel)); 10980a96aa3bSJed Brown coarse_pforest = (DM_Forest_pforest *)((DM_Forest *)coarseDM->data)->data; 10990a96aa3bSJed Brown coarse_pforest->coarsen_hierarchy = PETSC_TRUE; 11000a96aa3bSJed Brown } 11010a96aa3bSJed Brown } 11020a96aa3bSJed Brown 11030a96aa3bSJed Brown { /* repartitioning and overlap */ 11040a96aa3bSJed Brown PetscMPIInt size, rank; 11050a96aa3bSJed Brown 11069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 11079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1108217f96c1SStefano Zampini if (size > 1 && (pforest->partition_for_coarsening || forest->cellWeights || forest->weightCapacity != 1. || forest->weightsFactor != 1.)) { 11090a96aa3bSJed Brown PetscBool copyForest = PETSC_FALSE; 11100a96aa3bSJed Brown p4est_t *forest_copy = NULL; 11110a96aa3bSJed Brown p4est_gloidx_t shipped = 0; 11120a96aa3bSJed Brown 11130a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) copyForest = PETSC_TRUE; 1114792fecdfSBarry Smith if (copyForest) PetscCallP4estReturn(forest_copy, p4est_copy, (pforest->forest, 0)); 11150a96aa3bSJed Brown 11160a96aa3bSJed Brown if (!forest->cellWeights && forest->weightCapacity == 1. && forest->weightsFactor == 1.) { 1117792fecdfSBarry Smith PetscCallP4estReturn(shipped, p4est_partition_ext, (pforest->forest, (int)pforest->partition_for_coarsening, NULL)); 11180a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Non-uniform partition cases not implemented yet"); 11190a96aa3bSJed Brown if (shipped) ctx.anyChange = PETSC_TRUE; 11200a96aa3bSJed Brown if (forest_copy) { 11210a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 11220a96aa3bSJed Brown PetscSF repartSF; /* repartSF has roots in the old partition */ 11230a96aa3bSJed Brown PetscInt pStart = -1, pEnd = -1, p; 11240a96aa3bSJed Brown PetscInt numRoots, numLeaves; 11250a96aa3bSJed Brown PetscSFNode *repartRoots; 11260a96aa3bSJed Brown p4est_gloidx_t postStart = pforest->forest->global_first_quadrant[rank]; 11270a96aa3bSJed Brown p4est_gloidx_t postEnd = pforest->forest->global_first_quadrant[rank + 1]; 11280a96aa3bSJed Brown p4est_gloidx_t partOffset = postStart; 11290a96aa3bSJed Brown 11300a96aa3bSJed Brown numRoots = (PetscInt)(forest_copy->global_first_quadrant[rank + 1] - forest_copy->global_first_quadrant[rank]); 11310a96aa3bSJed Brown numLeaves = (PetscInt)(postEnd - postStart); 11329566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(size, rank, pforest->forest, forest_copy, &pStart, &pEnd)); 11339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((PetscInt)pforest->forest->local_num_quadrants, &repartRoots)); 11340a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 11350a96aa3bSJed Brown p4est_gloidx_t preStart = forest_copy->global_first_quadrant[p]; 11360a96aa3bSJed Brown p4est_gloidx_t preEnd = forest_copy->global_first_quadrant[p + 1]; 11370a96aa3bSJed Brown PetscInt q; 11380a96aa3bSJed Brown 11390a96aa3bSJed Brown if (preEnd == preStart) continue; 114008401ef6SPierre Jolivet PetscCheck(preStart <= postStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad partition overlap computation"); 11410a96aa3bSJed Brown preEnd = preEnd > postEnd ? postEnd : preEnd; 11420a96aa3bSJed Brown for (q = partOffset; q < preEnd; q++) { 11430a96aa3bSJed Brown repartRoots[q - postStart].rank = p; 11440a96aa3bSJed Brown repartRoots[q - postStart].index = partOffset - preStart; 11450a96aa3bSJed Brown } 11460a96aa3bSJed Brown partOffset = preEnd; 11470a96aa3bSJed Brown } 11489566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &repartSF)); 11499566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(repartSF, numRoots, numLeaves, NULL, PETSC_OWN_POINTER, repartRoots, PETSC_OWN_POINTER)); 11509566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(repartSF)); 11510a96aa3bSJed Brown if (preCoarseToFine) { 11520a96aa3bSJed Brown PetscSF repartSFembed, preCoarseToFineNew; 11530a96aa3bSJed Brown PetscInt nleaves; 11540a96aa3bSJed Brown const PetscInt *leaves; 11550a96aa3bSJed Brown 11569566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 11579566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine, NULL, &nleaves, &leaves, NULL)); 11580a96aa3bSJed Brown if (leaves) { 11599566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(repartSF, nleaves, leaves, &repartSFembed)); 11600a96aa3bSJed Brown } else { 11610a96aa3bSJed Brown repartSFembed = repartSF; 11629566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)repartSFembed)); 11630a96aa3bSJed Brown } 11649566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(preCoarseToFine, repartSFembed, &preCoarseToFineNew)); 11659566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 11669566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFembed)); 11670a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 11680a96aa3bSJed Brown } 11690a96aa3bSJed Brown if (coarseToPreFine) { 11700a96aa3bSJed Brown PetscSF repartSFinv, coarseToPreFineNew; 11710a96aa3bSJed Brown 11729566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(repartSF, &repartSFinv)); 11739566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(repartSFinv, coarseToPreFine, &coarseToPreFineNew)); 11749566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 11759566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFinv)); 11760a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 11770a96aa3bSJed Brown } 11789566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSF)); 11790a96aa3bSJed Brown } 1180792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (forest_copy)); 11810a96aa3bSJed Brown } 11820a96aa3bSJed Brown } 11830a96aa3bSJed Brown if (size > 1) { 11840a96aa3bSJed Brown PetscInt overlap; 11850a96aa3bSJed Brown 11869566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 11870a96aa3bSJed Brown 11880a96aa3bSJed Brown if (adaptFrom) { 11890a96aa3bSJed Brown PetscInt aoverlap; 11900a96aa3bSJed Brown 11919566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(adaptFrom, &aoverlap)); 1192ad540459SPierre Jolivet if (aoverlap != overlap) ctx.anyChange = PETSC_TRUE; 11930a96aa3bSJed Brown } 11940a96aa3bSJed Brown 11950a96aa3bSJed Brown if (overlap > 0) { 11960a96aa3bSJed Brown PetscInt i, cLocalStart; 11970a96aa3bSJed Brown PetscInt cEnd; 11980a96aa3bSJed Brown PetscSF preCellSF = NULL, cellSF = NULL; 11990a96aa3bSJed Brown 1200792fecdfSBarry Smith PetscCallP4estReturn(pforest->ghost, p4est_ghost_new, (pforest->forest, P4EST_CONNECT_FULL)); 1201792fecdfSBarry Smith PetscCallP4estReturn(pforest->lnodes, p4est_lnodes_new, (pforest->forest, pforest->ghost, -P4EST_DIM)); 1202792fecdfSBarry Smith PetscCallP4est(p4est_ghost_support_lnodes, (pforest->forest, pforest->lnodes, pforest->ghost)); 1203792fecdfSBarry Smith for (i = 1; i < overlap; i++) PetscCallP4est(p4est_ghost_expand_by_lnodes, (pforest->forest, pforest->lnodes, pforest->ghost)); 12040a96aa3bSJed Brown 12050a96aa3bSJed Brown cLocalStart = pforest->cLocalStart = pforest->ghost->proc_offsets[rank]; 12060a96aa3bSJed Brown cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[size]; 12070a96aa3bSJed Brown 12080a96aa3bSJed Brown /* shift sfs by cLocalStart, expand by cell SFs */ 12090a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 12109566063dSJacob Faibussowitsch if (adaptFrom) PetscCall(DMForestGetCellSF(adaptFrom, &preCellSF)); 12110a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 12129566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(dm, &cellSF)); 12130a96aa3bSJed Brown } 12140a96aa3bSJed Brown if (preCoarseToFine) { 12150a96aa3bSJed Brown PetscSF preCoarseToFineNew; 12160a96aa3bSJed Brown PetscInt nleaves, nroots, *leavesNew, i, nleavesNew; 12170a96aa3bSJed Brown const PetscInt *leaves; 12180a96aa3bSJed Brown const PetscSFNode *remotes; 12190a96aa3bSJed Brown PetscSFNode *remotesAll; 12200a96aa3bSJed Brown 12219566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 12229566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine, &nroots, &nleaves, &leaves, &remotes)); 12239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd, &remotesAll)); 12240a96aa3bSJed Brown for (i = 0; i < cEnd; i++) { 12250a96aa3bSJed Brown remotesAll[i].rank = -1; 12260a96aa3bSJed Brown remotesAll[i].index = -1; 12270a96aa3bSJed Brown } 12280a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesAll[(leaves ? leaves[i] : i) + cLocalStart] = remotes[i]; 12299566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(cellSF)); 12309566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(cellSF, MPIU_2INT, remotesAll, remotesAll, MPI_REPLACE)); 12319566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(cellSF, MPIU_2INT, remotesAll, remotesAll, MPI_REPLACE)); 12320a96aa3bSJed Brown nleavesNew = 0; 12330a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12340a96aa3bSJed Brown if (remotesAll[i].rank >= 0) nleavesNew++; 12350a96aa3bSJed Brown } 12369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesNew, &leavesNew)); 12370a96aa3bSJed Brown nleavesNew = 0; 12380a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12390a96aa3bSJed Brown if (remotesAll[i].rank >= 0) { 12400a96aa3bSJed Brown leavesNew[nleavesNew] = i; 12410a96aa3bSJed Brown if (i > nleavesNew) remotesAll[nleavesNew] = remotesAll[i]; 12420a96aa3bSJed Brown nleavesNew++; 12430a96aa3bSJed Brown } 12440a96aa3bSJed Brown } 12459566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &preCoarseToFineNew)); 12460a96aa3bSJed Brown if (nleavesNew < cEnd) { 12479566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew, nroots, nleavesNew, leavesNew, PETSC_OWN_POINTER, remotesAll, PETSC_COPY_VALUES)); 12480a96aa3bSJed Brown } else { /* all cells are leaves */ 12499566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 12509566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew, nroots, nleavesNew, NULL, PETSC_OWN_POINTER, remotesAll, PETSC_COPY_VALUES)); 12510a96aa3bSJed Brown } 12529566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesAll)); 12539566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 12540a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12550a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12560a96aa3bSJed Brown } 12570a96aa3bSJed Brown if (coarseToPreFine) { 12580a96aa3bSJed Brown PetscSF coarseToPreFineNew; 12590a96aa3bSJed Brown PetscInt nleaves, nroots, i, nleavesCellSF, nleavesExpanded, *leavesNew; 12600a96aa3bSJed Brown const PetscInt *leaves; 12610a96aa3bSJed Brown const PetscSFNode *remotes; 12620a96aa3bSJed Brown PetscSFNode *remotesNew, *remotesNewRoot, *remotesExpanded; 12630a96aa3bSJed Brown 12649566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(coarseToPreFine)); 12659566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToPreFine, &nroots, &nleaves, &leaves, &remotes)); 12669566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCellSF, NULL, &nleavesCellSF, NULL, NULL)); 12679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &remotesNewRoot)); 12689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotesNew)); 12690a96aa3bSJed Brown for (i = 0; i < nroots; i++) { 12700a96aa3bSJed Brown remotesNewRoot[i].rank = rank; 12710a96aa3bSJed Brown remotesNewRoot[i].index = i + cLocalStart; 12720a96aa3bSJed Brown } 12739566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToPreFine, MPIU_2INT, remotesNewRoot, remotesNew, MPI_REPLACE)); 12749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToPreFine, MPIU_2INT, remotesNewRoot, remotesNew, MPI_REPLACE)); 12759566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNewRoot)); 12769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesCellSF, &remotesExpanded)); 12770a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12780a96aa3bSJed Brown remotesExpanded[i].rank = -1; 12790a96aa3bSJed Brown remotesExpanded[i].index = -1; 12800a96aa3bSJed Brown } 12810a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesExpanded[leaves ? leaves[i] : i] = remotesNew[i]; 12829566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNew)); 12839566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(preCellSF, MPIU_2INT, remotesExpanded, remotesExpanded, MPI_REPLACE)); 12849566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(preCellSF, MPIU_2INT, remotesExpanded, remotesExpanded, MPI_REPLACE)); 12850a96aa3bSJed Brown 12860a96aa3bSJed Brown nleavesExpanded = 0; 12870a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12880a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) nleavesExpanded++; 12890a96aa3bSJed Brown } 12909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesExpanded, &leavesNew)); 12910a96aa3bSJed Brown nleavesExpanded = 0; 12920a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12930a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) { 12940a96aa3bSJed Brown leavesNew[nleavesExpanded] = i; 12950a96aa3bSJed Brown if (i > nleavesExpanded) remotesExpanded[nleavesExpanded] = remotes[i]; 12960a96aa3bSJed Brown nleavesExpanded++; 12970a96aa3bSJed Brown } 12980a96aa3bSJed Brown } 12999566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &coarseToPreFineNew)); 13000a96aa3bSJed Brown if (nleavesExpanded < nleavesCellSF) { 13019566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew, cEnd, nleavesExpanded, leavesNew, PETSC_OWN_POINTER, remotesExpanded, PETSC_COPY_VALUES)); 13020a96aa3bSJed Brown } else { 13039566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 13049566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew, cEnd, nleavesExpanded, NULL, PETSC_OWN_POINTER, remotesExpanded, PETSC_COPY_VALUES)); 13050a96aa3bSJed Brown } 13069566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesExpanded)); 13079566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 13080a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 13090a96aa3bSJed Brown } 13100a96aa3bSJed Brown } 13110a96aa3bSJed Brown } 13120a96aa3bSJed Brown } 13130a96aa3bSJed Brown forest->preCoarseToFine = preCoarseToFine; 13140a96aa3bSJed Brown forest->coarseToPreFine = coarseToPreFine; 13150a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 1316d72c4dc2SStefano Zampini PetscCall(MPIU_Allreduce(&ctx.anyChange, &pforest->adaptivitySuccess, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 13179566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, NULL)); 13183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13190a96aa3bSJed Brown } 13200a96aa3bSJed Brown 13210a96aa3bSJed Brown #define DMForestGetAdaptivitySuccess_pforest _append_pforest(DMForestGetAdaptivitySuccess) 1322d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestGetAdaptivitySuccess_pforest(DM dm, PetscBool *success) 1323d71ae5a4SJacob Faibussowitsch { 13240a96aa3bSJed Brown DM_Forest *forest; 13250a96aa3bSJed Brown DM_Forest_pforest *pforest; 13260a96aa3bSJed Brown 13270a96aa3bSJed Brown PetscFunctionBegin; 13280a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 13290a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 13300a96aa3bSJed Brown *success = pforest->adaptivitySuccess; 13313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13320a96aa3bSJed Brown } 13330a96aa3bSJed Brown 13340a96aa3bSJed Brown #define DMView_ASCII_pforest _append_pforest(DMView_ASCII) 1335d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_ASCII_pforest(PetscObject odm, PetscViewer viewer) 1336d71ae5a4SJacob Faibussowitsch { 13370a96aa3bSJed Brown DM dm = (DM)odm; 13380a96aa3bSJed Brown 13390a96aa3bSJed Brown PetscFunctionBegin; 13400a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13410a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13429566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13430a96aa3bSJed Brown switch (viewer->format) { 13440a96aa3bSJed Brown case PETSC_VIEWER_DEFAULT: 13459371c9d4SSatish Balay case PETSC_VIEWER_ASCII_INFO: { 13460a96aa3bSJed Brown PetscInt dim; 13470a96aa3bSJed Brown const char *name; 13480a96aa3bSJed Brown 13499566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 13509566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 135163a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "Forest %s in %" PetscInt_FMT " dimensions:\n", name, dim)); 135263a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Forest in %" PetscInt_FMT " dimensions:\n", dim)); 1353f4d061e9SPierre Jolivet } /* fall through */ 13540a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO_DETAIL: 13559371c9d4SSatish Balay case PETSC_VIEWER_LOAD_BALANCE: { 13560a96aa3bSJed Brown DM plex; 13570a96aa3bSJed Brown 13589566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 13599566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 13609371c9d4SSatish Balay } break; 1361d71ae5a4SJacob Faibussowitsch default: 1362d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 13630a96aa3bSJed Brown } 13643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13650a96aa3bSJed Brown } 13660a96aa3bSJed Brown 13670a96aa3bSJed Brown #define DMView_VTK_pforest _append_pforest(DMView_VTK) 1368d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_VTK_pforest(PetscObject odm, PetscViewer viewer) 1369d71ae5a4SJacob Faibussowitsch { 13700a96aa3bSJed Brown DM dm = (DM)odm; 13710a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 13720a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 13730a96aa3bSJed Brown PetscBool isvtk; 13740a96aa3bSJed Brown PetscReal vtkScale = 1. - PETSC_MACHINE_EPSILON; 13750a96aa3bSJed Brown PetscViewer_VTK *vtk = (PetscViewer_VTK *)viewer->data; 13760a96aa3bSJed Brown const char *name; 13770a96aa3bSJed Brown char *filenameStrip = NULL; 13780a96aa3bSJed Brown PetscBool hasExt; 13790a96aa3bSJed Brown size_t len; 13800a96aa3bSJed Brown p4est_geometry_t *geom; 13810a96aa3bSJed Brown 13820a96aa3bSJed Brown PetscFunctionBegin; 13830a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13840a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13859566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13860a96aa3bSJed Brown geom = pforest->topo->geom; 13879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 138828b400f6SJacob Faibussowitsch PetscCheck(isvtk, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name); 13890a96aa3bSJed Brown switch (viewer->format) { 13900a96aa3bSJed Brown case PETSC_VIEWER_VTK_VTU: 139128b400f6SJacob Faibussowitsch PetscCheck(pforest->forest, PetscObjectComm(odm), PETSC_ERR_ARG_WRONG, "DM has not been setup with a valid forest"); 13920a96aa3bSJed Brown name = vtk->filename; 13939566063dSJacob Faibussowitsch PetscCall(PetscStrlen(name, &len)); 13949566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(name + len - 4, ".vtu", &hasExt)); 13950a96aa3bSJed Brown if (hasExt) { 13969566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &filenameStrip)); 13970a96aa3bSJed Brown filenameStrip[len - 4] = '\0'; 13980a96aa3bSJed Brown name = filenameStrip; 13990a96aa3bSJed Brown } 1400792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4estReturn(geom, p4est_geometry_new_connectivity, (pforest->topo->conn)); 14010a96aa3bSJed Brown { 14020a96aa3bSJed Brown p4est_vtk_context_t *pvtk; 14030a96aa3bSJed Brown int footerr; 14040a96aa3bSJed Brown 1405792fecdfSBarry Smith PetscCallP4estReturn(pvtk, p4est_vtk_context_new, (pforest->forest, name)); 1406792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_geom, (pvtk, geom)); 1407792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_scale, (pvtk, (double)vtkScale)); 1408792fecdfSBarry Smith PetscCallP4estReturn(pvtk, p4est_vtk_write_header, (pvtk)); 140928b400f6SJacob Faibussowitsch PetscCheck(pvtk, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_header() failed"); 14109371c9d4SSatish Balay PetscCallP4estReturn(pvtk, p4est_vtk_write_cell_dataf, 14119371c9d4SSatish Balay (pvtk, 1, /* write tree */ 14120a96aa3bSJed Brown 1, /* write level */ 14130a96aa3bSJed Brown 1, /* write rank */ 14140a96aa3bSJed Brown 0, /* do not wrap rank */ 14150a96aa3bSJed Brown 0, /* no scalar fields */ 14160a96aa3bSJed Brown 0, /* no vector fields */ 14170a96aa3bSJed Brown pvtk)); 141828b400f6SJacob Faibussowitsch PetscCheck(pvtk, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_cell_dataf() failed"); 1419792fecdfSBarry Smith PetscCallP4estReturn(footerr, p4est_vtk_write_footer, (pvtk)); 142028b400f6SJacob Faibussowitsch PetscCheck(!footerr, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_footer() failed"); 14210a96aa3bSJed Brown } 1422792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4est(p4est_geometry_destroy, (geom)); 14239566063dSJacob Faibussowitsch PetscCall(PetscFree(filenameStrip)); 14240a96aa3bSJed Brown break; 1425d71ae5a4SJacob Faibussowitsch default: 1426d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 14270a96aa3bSJed Brown } 14283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14290a96aa3bSJed Brown } 14300a96aa3bSJed Brown 14310a96aa3bSJed Brown #define DMView_HDF5_pforest _append_pforest(DMView_HDF5) 1432d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_HDF5_pforest(DM dm, PetscViewer viewer) 1433d71ae5a4SJacob Faibussowitsch { 14340a96aa3bSJed Brown DM plex; 14350a96aa3bSJed Brown 14360a96aa3bSJed Brown PetscFunctionBegin; 14379566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 14389566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 14399566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 14403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14410a96aa3bSJed Brown } 14420a96aa3bSJed Brown 14430a96aa3bSJed Brown #define DMView_GLVis_pforest _append_pforest(DMView_GLVis) 1444d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_GLVis_pforest(DM dm, PetscViewer viewer) 1445d71ae5a4SJacob Faibussowitsch { 14460a96aa3bSJed Brown DM plex; 14470a96aa3bSJed Brown 14480a96aa3bSJed Brown PetscFunctionBegin; 14499566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 14509566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 14519566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 14523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14530a96aa3bSJed Brown } 14540a96aa3bSJed Brown 14550a96aa3bSJed Brown #define DMView_pforest _append_pforest(DMView) 1456d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_pforest(DM dm, PetscViewer viewer) 1457d71ae5a4SJacob Faibussowitsch { 14580a96aa3bSJed Brown PetscBool isascii, isvtk, ishdf5, isglvis; 14590a96aa3bSJed Brown 14600a96aa3bSJed Brown PetscFunctionBegin; 14610a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14620a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 14639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 14649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 14659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 14669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 14670a96aa3bSJed Brown if (isascii) { 14689566063dSJacob Faibussowitsch PetscCall(DMView_ASCII_pforest((PetscObject)dm, viewer)); 14690a96aa3bSJed Brown } else if (isvtk) { 14709566063dSJacob Faibussowitsch PetscCall(DMView_VTK_pforest((PetscObject)dm, viewer)); 14710a96aa3bSJed Brown } else if (ishdf5) { 14729566063dSJacob Faibussowitsch PetscCall(DMView_HDF5_pforest(dm, viewer)); 14730a96aa3bSJed Brown } else if (isglvis) { 14749566063dSJacob Faibussowitsch PetscCall(DMView_GLVis_pforest(dm, viewer)); 14750a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer not supported (not VTK, HDF5, or GLVis)"); 14763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14770a96aa3bSJed Brown } 14780a96aa3bSJed Brown 1479d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *conn, PetscInt **tree_face_to_uniq) 1480d71ae5a4SJacob Faibussowitsch { 14810a96aa3bSJed Brown PetscInt *ttf, f, t, g, count; 14820a96aa3bSJed Brown PetscInt numFacets; 14830a96aa3bSJed Brown 14840a96aa3bSJed Brown PetscFunctionBegin; 14850a96aa3bSJed Brown numFacets = conn->num_trees * P4EST_FACES; 14869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFacets, &ttf)); 14870a96aa3bSJed Brown for (f = 0; f < numFacets; f++) ttf[f] = -1; 14880a96aa3bSJed Brown for (g = 0, count = 0, t = 0; t < conn->num_trees; t++) { 14890a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++, g++) { 14900a96aa3bSJed Brown if (ttf[g] == -1) { 14910a96aa3bSJed Brown PetscInt ng; 14920a96aa3bSJed Brown 14930a96aa3bSJed Brown ttf[g] = count++; 14940a96aa3bSJed Brown ng = conn->tree_to_tree[g] * P4EST_FACES + (conn->tree_to_face[g] % P4EST_FACES); 14950a96aa3bSJed Brown ttf[ng] = ttf[g]; 14960a96aa3bSJed Brown } 14970a96aa3bSJed Brown } 14980a96aa3bSJed Brown } 14990a96aa3bSJed Brown *tree_face_to_uniq = ttf; 15003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15010a96aa3bSJed Brown } 15020a96aa3bSJed Brown 1503d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConnectivity_pforest(DM dm, p4est_connectivity_t **connOut, PetscInt **tree_face_to_uniq) 1504d71ae5a4SJacob Faibussowitsch { 15050a96aa3bSJed Brown p4est_topidx_t numTrees, numVerts, numCorns, numCtt; 15060a96aa3bSJed Brown PetscSection ctt; 15070a96aa3bSJed Brown #if defined(P4_TO_P8) 15080a96aa3bSJed Brown p4est_topidx_t numEdges, numEtt; 15090a96aa3bSJed Brown PetscSection ett; 15100a96aa3bSJed Brown PetscInt eStart, eEnd, e, ettSize; 15110a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES + P8EST_EDGES; 15120a96aa3bSJed Brown PetscInt edgeOff = 1 + P4EST_FACES; 15130a96aa3bSJed Brown #else 15140a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES; 15150a96aa3bSJed Brown #endif 15160a96aa3bSJed Brown p4est_connectivity_t *conn; 15170a96aa3bSJed Brown PetscInt cStart, cEnd, c, vStart, vEnd, v, fStart, fEnd, f; 15180a96aa3bSJed Brown PetscInt *star = NULL, *closure = NULL, closureSize, starSize, cttSize; 15190a96aa3bSJed Brown PetscInt *ttf; 15200a96aa3bSJed Brown 15210a96aa3bSJed Brown PetscFunctionBegin; 15220a96aa3bSJed Brown /* 1: count objects, allocate */ 15239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 15249566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cEnd - cStart, &numTrees)); 15250a96aa3bSJed Brown numVerts = P4EST_CHILDREN * numTrees; 15269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 15279566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(vEnd - vStart, &numCorns)); 15289566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &ctt)); 15299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ctt, vStart, vEnd)); 15300a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 15310a96aa3bSJed Brown PetscInt s; 15320a96aa3bSJed Brown 15339566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 15340a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 15350a96aa3bSJed Brown PetscInt p = star[2 * s]; 15360a96aa3bSJed Brown 15370a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 15380a96aa3bSJed Brown /* we want to count every time cell p references v, so we see how many times it comes up in the closure. This 15390a96aa3bSJed Brown * only protects against periodicity problems */ 15409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 154163a3b9bcSJacob 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); 15420a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 15430a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 15440a96aa3bSJed Brown 15451dca8a05SBarry Smith PetscCheck(cellVert >= vStart && cellVert < vEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure: vertices"); 154648a46eb9SPierre Jolivet if (cellVert == v) PetscCall(PetscSectionAddDof(ctt, v, 1)); 15470a96aa3bSJed Brown } 15489566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 15490a96aa3bSJed Brown } 15500a96aa3bSJed Brown } 15519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 15520a96aa3bSJed Brown } 15539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ctt)); 15549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ctt, &cttSize)); 15559566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cttSize, &numCtt)); 15560a96aa3bSJed Brown #if defined(P4_TO_P8) 15579566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, P4EST_DIM - 1, &eStart, &eEnd)); 15589566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(eEnd - eStart, &numEdges)); 15599566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &ett)); 15609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ett, eStart, eEnd)); 15610a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 15620a96aa3bSJed Brown PetscInt s; 15630a96aa3bSJed Brown 15649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 15650a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 15660a96aa3bSJed Brown PetscInt p = star[2 * s]; 15670a96aa3bSJed Brown 15680a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 15690a96aa3bSJed Brown /* we want to count every time cell p references e, so we see how many times it comes up in the closure. This 15700a96aa3bSJed Brown * only protects against periodicity problems */ 15719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 157208401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell with wrong closure size"); 15730a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 15740a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 15750a96aa3bSJed Brown 15761dca8a05SBarry Smith PetscCheck(cellEdge >= eStart && cellEdge < eEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure: edges"); 157748a46eb9SPierre Jolivet if (cellEdge == e) PetscCall(PetscSectionAddDof(ett, e, 1)); 15780a96aa3bSJed Brown } 15799566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 15800a96aa3bSJed Brown } 15810a96aa3bSJed Brown } 15829566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 15830a96aa3bSJed Brown } 15849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ett)); 15859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ett, &ettSize)); 15869566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(ettSize, &numEtt)); 15870a96aa3bSJed Brown 15880a96aa3bSJed Brown /* This routine allocates space for the arrays, which we fill below */ 1589792fecdfSBarry Smith PetscCallP4estReturn(conn, p8est_connectivity_new, (numVerts, numTrees, numEdges, numEtt, numCorns, numCtt)); 15900a96aa3bSJed Brown #else 1591792fecdfSBarry Smith PetscCallP4estReturn(conn, p4est_connectivity_new, (numVerts, numTrees, numCorns, numCtt)); 15920a96aa3bSJed Brown #endif 15930a96aa3bSJed Brown 15940a96aa3bSJed Brown /* 2: visit every face, determine neighboring cells(trees) */ 15959566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 1, &fStart, &fEnd)); 15969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * P4EST_FACES, &ttf)); 15970a96aa3bSJed Brown for (f = fStart; f < fEnd; f++) { 15980a96aa3bSJed Brown PetscInt numSupp, s; 15990a96aa3bSJed Brown PetscInt myFace[2] = {-1, -1}; 16000a96aa3bSJed Brown PetscInt myOrnt[2] = {PETSC_MIN_INT, PETSC_MIN_INT}; 16010a96aa3bSJed Brown const PetscInt *supp; 16020a96aa3bSJed Brown 16039566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &numSupp)); 16041dca8a05SBarry 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); 16059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &supp)); 16060a96aa3bSJed Brown 16070a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16080a96aa3bSJed Brown PetscInt p = supp[s]; 16090a96aa3bSJed Brown 16100a96aa3bSJed Brown if (p >= cEnd) { 16110a96aa3bSJed Brown numSupp--; 16120a96aa3bSJed Brown if (s) supp = &supp[1 - s]; 16130a96aa3bSJed Brown break; 16140a96aa3bSJed Brown } 16150a96aa3bSJed Brown } 16160a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16170a96aa3bSJed Brown PetscInt p = supp[s], i; 16180a96aa3bSJed Brown PetscInt numCone; 16190a96aa3bSJed Brown DMPolytopeType ct; 16200a96aa3bSJed Brown const PetscInt *cone; 16210a96aa3bSJed Brown const PetscInt *ornt; 16220a96aa3bSJed Brown PetscInt orient = PETSC_MIN_INT; 16230a96aa3bSJed Brown 16249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &numCone)); 162563a3b9bcSJacob 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); 16269566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 16279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[0], &ct)); 16289566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 16290a96aa3bSJed Brown for (i = 0; i < P4EST_FACES; i++) { 16300a96aa3bSJed Brown if (cone[i] == f) { 16310a96aa3bSJed Brown orient = DMPolytopeConvertNewOrientation_Internal(ct, ornt[i]); 16320a96aa3bSJed Brown break; 16330a96aa3bSJed Brown } 16340a96aa3bSJed Brown } 163563a3b9bcSJacob Faibussowitsch PetscCheck(i < P4EST_FACES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "cell %" PetscInt_FMT " faced %" PetscInt_FMT " mismatch", p, f); 16360a96aa3bSJed Brown if (p < cStart || p >= cEnd) { 16370a96aa3bSJed Brown DMPolytopeType ct; 16389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 163963a3b9bcSJacob 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); 16400a96aa3bSJed Brown } 16410a96aa3bSJed Brown ttf[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = f - fStart; 16420a96aa3bSJed Brown if (numSupp == 1) { 16430a96aa3bSJed Brown /* boundary faces indicated by self reference */ 16440a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = p - cStart; 16450a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = (int8_t)PetscFaceToP4estFace[i]; 16460a96aa3bSJed Brown } else { 16470a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16480a96aa3bSJed Brown 16490a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = supp[1 - s] - cStart; 16500a96aa3bSJed Brown myFace[s] = PetscFaceToP4estFace[i]; 16510a96aa3bSJed Brown /* get the orientation of cell p in p4est-type closure to facet f, by composing the p4est-closure to 16520a96aa3bSJed Brown * petsc-closure permutation and the petsc-closure to facet orientation */ 16530a96aa3bSJed Brown myOrnt[s] = DihedralCompose(N, orient, DMPolytopeConvertNewOrientation_Internal(ct, P4estFaceToPetscOrnt[myFace[s]])); 16540a96aa3bSJed Brown } 16550a96aa3bSJed Brown } 16560a96aa3bSJed Brown if (numSupp == 2) { 16570a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16580a96aa3bSJed Brown PetscInt p = supp[s]; 16590a96aa3bSJed Brown PetscInt orntAtoB; 16600a96aa3bSJed Brown PetscInt p4estOrient; 16610a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16620a96aa3bSJed Brown 16630a96aa3bSJed Brown /* composing the forward permutation with the other cell's inverse permutation gives the self-to-neighbor 16640a96aa3bSJed Brown * permutation of this cell-facet's cone */ 16650a96aa3bSJed Brown orntAtoB = DihedralCompose(N, DihedralInvert(N, myOrnt[1 - s]), myOrnt[s]); 16660a96aa3bSJed Brown 16670a96aa3bSJed Brown /* convert cone-description permutation (i.e., edges around facet) to cap-description permutation (i.e., 16680a96aa3bSJed Brown * vertices around facet) */ 16690a96aa3bSJed Brown #if !defined(P4_TO_P8) 16700a96aa3bSJed Brown p4estOrient = orntAtoB < 0 ? -(orntAtoB + 1) : orntAtoB; 16710a96aa3bSJed Brown #else 16720a96aa3bSJed Brown { 16730a96aa3bSJed Brown PetscInt firstVert = orntAtoB < 0 ? ((-orntAtoB) % N) : orntAtoB; 16740a96aa3bSJed Brown PetscInt p4estFirstVert = firstVert < 2 ? firstVert : (firstVert ^ 1); 16750a96aa3bSJed Brown 16760a96aa3bSJed Brown /* swap bits */ 16770a96aa3bSJed Brown p4estOrient = ((myFace[s] <= myFace[1 - s]) || (orntAtoB < 0)) ? p4estFirstVert : ((p4estFirstVert >> 1) | ((p4estFirstVert & 1) << 1)); 16780a96aa3bSJed Brown } 16790a96aa3bSJed Brown #endif 16800a96aa3bSJed Brown /* encode neighbor face and orientation in tree_to_face per p4est_connectivity standard (see 16810a96aa3bSJed Brown * p4est_connectivity.h, p8est_connectivity.h) */ 16820a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + myFace[s]] = (int8_t)myFace[1 - s] + p4estOrient * P4EST_FACES; 16830a96aa3bSJed Brown } 16840a96aa3bSJed Brown } 16850a96aa3bSJed Brown } 16860a96aa3bSJed Brown 16870a96aa3bSJed Brown #if defined(P4_TO_P8) 16880a96aa3bSJed Brown /* 3: visit every edge */ 16890a96aa3bSJed Brown conn->ett_offset[0] = 0; 16900a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 16910a96aa3bSJed Brown PetscInt off, s; 16920a96aa3bSJed Brown 16939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ett, e, &off)); 16940a96aa3bSJed Brown conn->ett_offset[e - eStart] = (p4est_topidx_t)off; 16959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 16960a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 16970a96aa3bSJed Brown PetscInt p = star[2 * s]; 16980a96aa3bSJed Brown 16990a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 17009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 170108401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure"); 17020a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 17030a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 17040a96aa3bSJed Brown PetscInt cellOrnt = closure[2 * (c + edgeOff) + 1]; 17050a96aa3bSJed Brown DMPolytopeType ct; 17060a96aa3bSJed Brown 17079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cellEdge, &ct)); 17080a96aa3bSJed Brown cellOrnt = DMPolytopeConvertNewOrientation_Internal(ct, cellOrnt); 17090a96aa3bSJed Brown if (cellEdge == e) { 17100a96aa3bSJed Brown PetscInt p4estEdge = PetscEdgeToP4estEdge[c]; 17110a96aa3bSJed Brown PetscInt totalOrient; 17120a96aa3bSJed Brown 17130a96aa3bSJed Brown /* compose p4est-closure to petsc-closure permutation and petsc-closure to edge orientation */ 17140a96aa3bSJed Brown totalOrient = DihedralCompose(2, cellOrnt, DMPolytopeConvertNewOrientation_Internal(DM_POLYTOPE_SEGMENT, P4estEdgeToPetscOrnt[p4estEdge])); 17150a96aa3bSJed Brown /* p4est orientations are positive: -2 => 1, -1 => 0 */ 17160a96aa3bSJed Brown totalOrient = (totalOrient < 0) ? -(totalOrient + 1) : totalOrient; 17170a96aa3bSJed Brown conn->edge_to_tree[off] = (p4est_locidx_t)(p - cStart); 1718d5b43468SJose E. Roman /* encode cell-edge and orientation in edge_to_edge per p8est_connectivity standard (see 17190a96aa3bSJed Brown * p8est_connectivity.h) */ 17200a96aa3bSJed Brown conn->edge_to_edge[off++] = (int8_t)p4estEdge + P8EST_EDGES * totalOrient; 17210a96aa3bSJed Brown conn->tree_to_edge[P8EST_EDGES * (p - cStart) + p4estEdge] = e - eStart; 17220a96aa3bSJed Brown } 17230a96aa3bSJed Brown } 17249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 17250a96aa3bSJed Brown } 17260a96aa3bSJed Brown } 17279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star)); 17280a96aa3bSJed Brown } 17299566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ett)); 17300a96aa3bSJed Brown #endif 17310a96aa3bSJed Brown 17320a96aa3bSJed Brown /* 4: visit every vertex */ 17330a96aa3bSJed Brown conn->ctt_offset[0] = 0; 17340a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 17350a96aa3bSJed Brown PetscInt off, s; 17360a96aa3bSJed Brown 17379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ctt, v, &off)); 17380a96aa3bSJed Brown conn->ctt_offset[v - vStart] = (p4est_topidx_t)off; 17399566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 17400a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 17410a96aa3bSJed Brown PetscInt p = star[2 * s]; 17420a96aa3bSJed Brown 17430a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 17449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 174508401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure"); 17460a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 17470a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 17480a96aa3bSJed Brown 17490a96aa3bSJed Brown if (cellVert == v) { 17500a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[c]; 17510a96aa3bSJed Brown 17520a96aa3bSJed Brown conn->corner_to_tree[off] = (p4est_locidx_t)(p - cStart); 17530a96aa3bSJed Brown conn->corner_to_corner[off++] = (int8_t)p4estVert; 17540a96aa3bSJed Brown conn->tree_to_corner[P4EST_CHILDREN * (p - cStart) + p4estVert] = v - vStart; 17550a96aa3bSJed Brown } 17560a96aa3bSJed Brown } 17579566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure)); 17580a96aa3bSJed Brown } 17590a96aa3bSJed Brown } 17609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star)); 17610a96aa3bSJed Brown } 17629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ctt)); 17630a96aa3bSJed Brown 17640a96aa3bSJed Brown /* 5: Compute the coordinates */ 17650a96aa3bSJed Brown { 17660a96aa3bSJed Brown PetscInt coordDim; 17670a96aa3bSJed Brown 17689566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim)); 17696858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 17700a96aa3bSJed Brown for (c = cStart; c < cEnd; c++) { 17710a96aa3bSJed Brown PetscInt dof; 17726858538eSMatthew G. Knepley PetscBool isDG; 17730a96aa3bSJed Brown PetscScalar *cellCoords = NULL; 17746858538eSMatthew G. Knepley const PetscScalar *array; 17750a96aa3bSJed Brown 17766858538eSMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 17776858538eSMatthew 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); 17780a96aa3bSJed Brown for (v = 0; v < P4EST_CHILDREN; v++) { 17790a96aa3bSJed Brown PetscInt i, lim = PetscMin(3, coordDim); 17800a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[v]; 17810a96aa3bSJed Brown 17820a96aa3bSJed Brown conn->tree_to_vertex[P4EST_CHILDREN * (c - cStart) + v] = P4EST_CHILDREN * (c - cStart) + v; 17830a96aa3bSJed Brown /* p4est vertices are always embedded in R^3 */ 17840a96aa3bSJed Brown for (i = 0; i < 3; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = 0.; 17850a96aa3bSJed Brown for (i = 0; i < lim; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = PetscRealPart(cellCoords[v * coordDim + i]); 17860a96aa3bSJed Brown } 17876858538eSMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 17880a96aa3bSJed Brown } 17890a96aa3bSJed Brown } 17900a96aa3bSJed Brown 17910a96aa3bSJed Brown #if defined(P4EST_ENABLE_DEBUG) 179208401ef6SPierre Jolivet PetscCheck(p4est_connectivity_is_valid(conn), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Plex to p4est conversion failed"); 17930a96aa3bSJed Brown #endif 17940a96aa3bSJed Brown 17950a96aa3bSJed Brown *connOut = conn; 17960a96aa3bSJed Brown 17970a96aa3bSJed Brown *tree_face_to_uniq = ttf; 17983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17990a96aa3bSJed Brown } 18000a96aa3bSJed Brown 1801d71ae5a4SJacob Faibussowitsch static PetscErrorCode locidx_to_PetscInt(sc_array_t *array) 1802d71ae5a4SJacob Faibussowitsch { 18030a96aa3bSJed Brown sc_array_t *newarray; 18040a96aa3bSJed Brown size_t zz, count = array->elem_count; 18050a96aa3bSJed Brown 18060a96aa3bSJed Brown PetscFunctionBegin; 180708401ef6SPierre Jolivet PetscCheck(array->elem_size == sizeof(p4est_locidx_t), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong locidx size"); 18080a96aa3bSJed Brown 18093ba16761SJacob Faibussowitsch if (sizeof(p4est_locidx_t) == sizeof(PetscInt)) PetscFunctionReturn(PETSC_SUCCESS); 18100a96aa3bSJed Brown 18110a96aa3bSJed Brown newarray = sc_array_new_size(sizeof(PetscInt), array->elem_count); 18120a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18130a96aa3bSJed Brown p4est_locidx_t il = *((p4est_locidx_t *)sc_array_index(array, zz)); 18140a96aa3bSJed Brown PetscInt *ip = (PetscInt *)sc_array_index(newarray, zz); 18150a96aa3bSJed Brown 18160a96aa3bSJed Brown *ip = (PetscInt)il; 18170a96aa3bSJed Brown } 18180a96aa3bSJed Brown 18190a96aa3bSJed Brown sc_array_reset(array); 18200a96aa3bSJed Brown sc_array_init_size(array, sizeof(PetscInt), count); 18210a96aa3bSJed Brown sc_array_copy(array, newarray); 18220a96aa3bSJed Brown sc_array_destroy(newarray); 18233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18240a96aa3bSJed Brown } 18250a96aa3bSJed Brown 1826d71ae5a4SJacob Faibussowitsch static PetscErrorCode coords_double_to_PetscScalar(sc_array_t *array, PetscInt dim) 1827d71ae5a4SJacob Faibussowitsch { 18280a96aa3bSJed Brown sc_array_t *newarray; 18290a96aa3bSJed Brown size_t zz, count = array->elem_count; 18300a96aa3bSJed Brown 18310a96aa3bSJed Brown PetscFunctionBegin; 18321dca8a05SBarry Smith PetscCheck(array->elem_size == 3 * sizeof(double), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong coordinate size"); 18330a96aa3bSJed Brown #if !defined(PETSC_USE_COMPLEX) 18343ba16761SJacob Faibussowitsch if (sizeof(double) == sizeof(PetscScalar) && dim == 3) PetscFunctionReturn(PETSC_SUCCESS); 18350a96aa3bSJed Brown #endif 18360a96aa3bSJed Brown 18370a96aa3bSJed Brown newarray = sc_array_new_size(dim * sizeof(PetscScalar), array->elem_count); 18380a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18390a96aa3bSJed Brown int i; 18400a96aa3bSJed Brown double *id = (double *)sc_array_index(array, zz); 18410a96aa3bSJed Brown PetscScalar *ip = (PetscScalar *)sc_array_index(newarray, zz); 18420a96aa3bSJed Brown 18430a96aa3bSJed Brown for (i = 0; i < dim; i++) ip[i] = 0.; 18440a96aa3bSJed Brown for (i = 0; i < PetscMin(dim, 3); i++) ip[i] = (PetscScalar)id[i]; 18450a96aa3bSJed Brown } 18460a96aa3bSJed Brown 18470a96aa3bSJed Brown sc_array_reset(array); 18480a96aa3bSJed Brown sc_array_init_size(array, dim * sizeof(PetscScalar), count); 18490a96aa3bSJed Brown sc_array_copy(array, newarray); 18500a96aa3bSJed Brown sc_array_destroy(newarray); 18513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18520a96aa3bSJed Brown } 18530a96aa3bSJed Brown 1854d71ae5a4SJacob Faibussowitsch static PetscErrorCode locidx_pair_to_PetscSFNode(sc_array_t *array) 1855d71ae5a4SJacob Faibussowitsch { 18560a96aa3bSJed Brown sc_array_t *newarray; 18570a96aa3bSJed Brown size_t zz, count = array->elem_count; 18580a96aa3bSJed Brown 18590a96aa3bSJed Brown PetscFunctionBegin; 18601dca8a05SBarry Smith PetscCheck(array->elem_size == 2 * sizeof(p4est_locidx_t), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong locidx size"); 18610a96aa3bSJed Brown 18620a96aa3bSJed Brown newarray = sc_array_new_size(sizeof(PetscSFNode), array->elem_count); 18630a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18640a96aa3bSJed Brown p4est_locidx_t *il = (p4est_locidx_t *)sc_array_index(array, zz); 18650a96aa3bSJed Brown PetscSFNode *ip = (PetscSFNode *)sc_array_index(newarray, zz); 18660a96aa3bSJed Brown 18670a96aa3bSJed Brown ip->rank = (PetscInt)il[0]; 18680a96aa3bSJed Brown ip->index = (PetscInt)il[1]; 18690a96aa3bSJed Brown } 18700a96aa3bSJed Brown 18710a96aa3bSJed Brown sc_array_reset(array); 18720a96aa3bSJed Brown sc_array_init_size(array, sizeof(PetscSFNode), count); 18730a96aa3bSJed Brown sc_array_copy(array, newarray); 18740a96aa3bSJed Brown sc_array_destroy(newarray); 18753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18760a96aa3bSJed Brown } 18770a96aa3bSJed Brown 1878d71ae5a4SJacob Faibussowitsch static PetscErrorCode P4estToPlex_Local(p4est_t *p4est, DM *plex) 1879d71ae5a4SJacob Faibussowitsch { 18800a96aa3bSJed Brown PetscFunctionBegin; 18810a96aa3bSJed Brown { 18820a96aa3bSJed Brown sc_array_t *points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 18830a96aa3bSJed Brown sc_array_t *cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 18840a96aa3bSJed Brown sc_array_t *cones = sc_array_new(sizeof(p4est_locidx_t)); 18850a96aa3bSJed Brown sc_array_t *cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 18860a96aa3bSJed Brown sc_array_t *coords = sc_array_new(3 * sizeof(double)); 18870a96aa3bSJed Brown sc_array_t *children = sc_array_new(sizeof(p4est_locidx_t)); 18880a96aa3bSJed Brown sc_array_t *parents = sc_array_new(sizeof(p4est_locidx_t)); 18890a96aa3bSJed Brown sc_array_t *childids = sc_array_new(sizeof(p4est_locidx_t)); 18900a96aa3bSJed Brown sc_array_t *leaves = sc_array_new(sizeof(p4est_locidx_t)); 18910a96aa3bSJed Brown sc_array_t *remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 18920a96aa3bSJed Brown p4est_locidx_t first_local_quad; 18930a96aa3bSJed Brown 1894792fecdfSBarry 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)); 18950a96aa3bSJed Brown 18969566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 18979566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 18989566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 18999566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 19009566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, P4EST_DIM)); 19010a96aa3bSJed Brown 19029566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PETSC_COMM_SELF, plex)); 19039566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*plex, P4EST_DIM)); 19049566063dSJacob 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)); 19059566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(*plex)); 19060a96aa3bSJed Brown sc_array_destroy(points_per_dim); 19070a96aa3bSJed Brown sc_array_destroy(cone_sizes); 19080a96aa3bSJed Brown sc_array_destroy(cones); 19090a96aa3bSJed Brown sc_array_destroy(cone_orientations); 19100a96aa3bSJed Brown sc_array_destroy(coords); 19110a96aa3bSJed Brown sc_array_destroy(children); 19120a96aa3bSJed Brown sc_array_destroy(parents); 19130a96aa3bSJed Brown sc_array_destroy(childids); 19140a96aa3bSJed Brown sc_array_destroy(leaves); 19150a96aa3bSJed Brown sc_array_destroy(remotes); 19160a96aa3bSJed Brown } 19173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19180a96aa3bSJed Brown } 19190a96aa3bSJed Brown 19200a96aa3bSJed Brown #define DMReferenceTreeGetChildSymmetry_pforest _append_pforest(DMReferenceTreeGetChildSymmetry) 1921d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMReferenceTreeGetChildSymmetry_pforest(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB) 1922d71ae5a4SJacob Faibussowitsch { 19230a96aa3bSJed Brown PetscInt coneSize, dStart, dEnd, vStart, vEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 19240a96aa3bSJed Brown 19250a96aa3bSJed Brown PetscFunctionBegin; 19260a96aa3bSJed Brown if (parentOrientA == parentOrientB) { 19270a96aa3bSJed Brown if (childOrientB) *childOrientB = childOrientA; 19280a96aa3bSJed Brown if (childB) *childB = childA; 19293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19300a96aa3bSJed Brown } 19319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 19326aad120cSJose E. Roman if (childA >= vStart && childA < vEnd) { /* vertices (always in the middle) are invariant under rotation */ 19330a96aa3bSJed Brown if (childOrientB) *childOrientB = 0; 19340a96aa3bSJed Brown if (childB) *childB = childA; 19353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19360a96aa3bSJed Brown } 19370a96aa3bSJed Brown for (dim = 0; dim < 3; dim++) { 19389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, &dStart, &dEnd)); 19390a96aa3bSJed Brown if (parent >= dStart && parent <= dEnd) break; 19400a96aa3bSJed Brown } 194163a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot perform child symmetry for %" PetscInt_FMT "-cells", dim); 194228b400f6SJacob Faibussowitsch PetscCheck(dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "A vertex has no children"); 19430a96aa3bSJed Brown if (childA < dStart || childA >= dEnd) { /* a 1-cell in a 2-cell */ 19440a96aa3bSJed Brown /* this is a lower-dimensional child: bootstrap */ 19450a96aa3bSJed Brown PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 19460a96aa3bSJed Brown const PetscInt *supp, *coneA, *coneB, *oA, *oB; 19470a96aa3bSJed Brown 19489566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, childA, &size)); 19499566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, childA, &supp)); 19500a96aa3bSJed Brown 19510a96aa3bSJed Brown /* find a point sA in supp(childA) that has the same parent */ 19520a96aa3bSJed Brown for (i = 0; i < size; i++) { 19530a96aa3bSJed Brown PetscInt sParent; 19540a96aa3bSJed Brown 19550a96aa3bSJed Brown sA = supp[i]; 19560a96aa3bSJed Brown if (sA == parent) continue; 19579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, sA, &sParent, NULL)); 19580a96aa3bSJed Brown if (sParent == parent) break; 19590a96aa3bSJed Brown } 196008401ef6SPierre Jolivet PetscCheck(i != size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "could not find support in children"); 19610a96aa3bSJed Brown /* find out which point sB is in an equivalent position to sA under 19620a96aa3bSJed Brown * parentOrientB */ 19639566063dSJacob Faibussowitsch PetscCall(DMReferenceTreeGetChildSymmetry_pforest(dm, parent, parentOrientA, 0, sA, parentOrientB, &sOrientB, &sB)); 19649566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, sA, &sConeSize)); 19659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sA, &coneA)); 19669566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sB, &coneB)); 19679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sA, &oA)); 19689566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sB, &oB)); 19690a96aa3bSJed Brown /* step through the cone of sA in natural order */ 19700a96aa3bSJed Brown for (i = 0; i < sConeSize; i++) { 19710a96aa3bSJed Brown if (coneA[i] == childA) { 19720a96aa3bSJed Brown /* if childA is at position i in coneA, 19730a96aa3bSJed Brown * then we want the point that is at sOrientB*i in coneB */ 19740a96aa3bSJed Brown PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize - (sOrientB + 1) - i) % sConeSize); 19750a96aa3bSJed Brown if (childB) *childB = coneB[j]; 19760a96aa3bSJed Brown if (childOrientB) { 19770a96aa3bSJed Brown DMPolytopeType ct; 19780a96aa3bSJed Brown PetscInt oBtrue; 19790a96aa3bSJed Brown 19809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, childA, &coneSize)); 19810a96aa3bSJed Brown /* compose sOrientB and oB[j] */ 19821dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected a vertex or an edge"); 19830a96aa3bSJed Brown ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 19840a96aa3bSJed Brown /* we may have to flip an edge */ 19850a96aa3bSJed Brown oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientationInv(ct, -1, oB[j]); 19860a96aa3bSJed Brown oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 19870a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, DMPolytopeConvertNewOrientation_Internal(ct, oA[i]), oBtrue); 19880a96aa3bSJed Brown *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 19890a96aa3bSJed Brown } 19900a96aa3bSJed Brown break; 19910a96aa3bSJed Brown } 19920a96aa3bSJed Brown } 199308401ef6SPierre Jolivet PetscCheck(i != sConeSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "support cone mismatch"); 19943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19950a96aa3bSJed Brown } 19960a96aa3bSJed Brown /* get the cone size and symmetry swap */ 19979566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize)); 19980a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 19990a96aa3bSJed Brown if (dim == 2) { 20000a96aa3bSJed Brown /* orientations refer to cones: we want them to refer to vertices: 20010a96aa3bSJed Brown * if it's a rotation, they are the same, but if the order is reversed, a 20020a96aa3bSJed Brown * permutation that puts side i first does *not* put vertex i first */ 20030a96aa3bSJed Brown oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 20040a96aa3bSJed Brown oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 20050a96aa3bSJed Brown ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 20060a96aa3bSJed Brown } else { 20070a96aa3bSJed Brown oAvert = parentOrientA; 20080a96aa3bSJed Brown oBvert = parentOrientB; 20090a96aa3bSJed Brown ABswapVert = ABswap; 20100a96aa3bSJed Brown } 20110a96aa3bSJed Brown if (childB) { 20120a96aa3bSJed Brown /* assume that each child corresponds to a vertex, in the same order */ 20130a96aa3bSJed Brown PetscInt p, posA = -1, numChildren, i; 20140a96aa3bSJed Brown const PetscInt *children; 20150a96aa3bSJed Brown 20160a96aa3bSJed Brown /* count which position the child is in */ 20179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, parent, &numChildren, &children)); 20180a96aa3bSJed Brown for (i = 0; i < numChildren; i++) { 20190a96aa3bSJed Brown p = children[i]; 20200a96aa3bSJed Brown if (p == childA) { 20210a96aa3bSJed Brown if (dim == 1) { 20220a96aa3bSJed Brown posA = i; 20230a96aa3bSJed Brown } else { /* 2D Morton to rotation */ 20240a96aa3bSJed Brown posA = (i & 2) ? (i ^ 1) : i; 20250a96aa3bSJed Brown } 20260a96aa3bSJed Brown break; 20270a96aa3bSJed Brown } 20280a96aa3bSJed Brown } 20290a96aa3bSJed Brown if (posA >= coneSize) { 20300a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find childA in children of parent"); 20310a96aa3bSJed Brown } else { 20320a96aa3bSJed Brown /* figure out position B by applying ABswapVert */ 20330a96aa3bSJed Brown PetscInt posB, childIdB; 20340a96aa3bSJed Brown 20350a96aa3bSJed Brown posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize - (ABswapVert + 1) - posA) % coneSize); 20360a96aa3bSJed Brown if (dim == 1) { 20370a96aa3bSJed Brown childIdB = posB; 20380a96aa3bSJed Brown } else { /* 2D rotation to Morton */ 20390a96aa3bSJed Brown childIdB = (posB & 2) ? (posB ^ 1) : posB; 20400a96aa3bSJed Brown } 20410a96aa3bSJed Brown if (childB) *childB = children[childIdB]; 20420a96aa3bSJed Brown } 20430a96aa3bSJed Brown } 20440a96aa3bSJed Brown if (childOrientB) *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap); 20453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20460a96aa3bSJed Brown } 20470a96aa3bSJed Brown 20480a96aa3bSJed Brown #define DMCreateReferenceTree_pforest _append_pforest(DMCreateReferenceTree) 2049d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateReferenceTree_pforest(MPI_Comm comm, DM *dm) 2050d71ae5a4SJacob Faibussowitsch { 20510a96aa3bSJed Brown p4est_connectivity_t *refcube; 20520a96aa3bSJed Brown p4est_t *root, *refined; 20530a96aa3bSJed Brown DM dmRoot, dmRefined; 20540a96aa3bSJed Brown DM_Plex *mesh; 20550a96aa3bSJed Brown PetscMPIInt rank; 205666c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI) 205766c0a4b5SToby Isaac sc_MPI_Comm comm_self = sc_MPI_COMM_SELF; 205866c0a4b5SToby Isaac #else 205966c0a4b5SToby Isaac MPI_Comm comm_self = PETSC_COMM_SELF; 206066c0a4b5SToby Isaac #endif 20610a96aa3bSJed Brown 20620a96aa3bSJed Brown PetscFunctionBegin; 2063792fecdfSBarry Smith PetscCallP4estReturn(refcube, p4est_connectivity_new_byname, ("unit")); 20640a96aa3bSJed Brown { /* [-1,1]^d geometry */ 20650a96aa3bSJed Brown PetscInt i, j; 20660a96aa3bSJed Brown 20670a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 20680a96aa3bSJed Brown for (j = 0; j < 3; j++) { 20690a96aa3bSJed Brown refcube->vertices[3 * i + j] *= 2.; 20700a96aa3bSJed Brown refcube->vertices[3 * i + j] -= 1.; 20710a96aa3bSJed Brown } 20720a96aa3bSJed Brown } 20730a96aa3bSJed Brown } 2074792fecdfSBarry Smith PetscCallP4estReturn(root, p4est_new, (comm_self, refcube, 0, NULL, NULL)); 2075792fecdfSBarry Smith PetscCallP4estReturn(refined, p4est_new_ext, (comm_self, refcube, 0, 1, 1, 0, NULL, NULL)); 20769566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(root, &dmRoot)); 20779566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(refined, &dmRefined)); 20780a96aa3bSJed Brown { 20790a96aa3bSJed Brown #if !defined(P4_TO_P8) 20800a96aa3bSJed Brown PetscInt nPoints = 25; 20819371c9d4SSatish 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}; 20829371c9d4SSatish 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}; 20830a96aa3bSJed Brown #else 20840a96aa3bSJed Brown PetscInt nPoints = 125; 20859371c9d4SSatish 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, 20869371c9d4SSatish 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, 20879371c9d4SSatish 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}; 20889371c9d4SSatish 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, 20899371c9d4SSatish 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}; 20900a96aa3bSJed Brown 20910a96aa3bSJed Brown #endif 20920a96aa3bSJed Brown IS permIS; 20930a96aa3bSJed Brown DM dmPerm; 20940a96aa3bSJed Brown 20959566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nPoints, perm, PETSC_USE_POINTER, &permIS)); 20969566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dmRefined, permIS, &dmPerm)); 20970a96aa3bSJed Brown if (dmPerm) { 20989566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 20990a96aa3bSJed Brown dmRefined = dmPerm; 21000a96aa3bSJed Brown } 21019566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 21020a96aa3bSJed Brown { 21030a96aa3bSJed Brown PetscInt p; 21049566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRoot, "identity")); 21059566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRefined, "identity")); 210648a46eb9SPierre Jolivet for (p = 0; p < P4EST_INSUL; p++) PetscCall(DMSetLabelValue(dmRoot, "identity", p, p)); 210748a46eb9SPierre Jolivet for (p = 0; p < nPoints; p++) PetscCall(DMSetLabelValue(dmRefined, "identity", p, ident[p])); 21080a96aa3bSJed Brown } 21090a96aa3bSJed Brown } 21109566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(dmRoot, dmRefined, "identity", dm)); 21110a96aa3bSJed Brown mesh = (DM_Plex *)(*dm)->data; 21120a96aa3bSJed Brown mesh->getchildsymmetry = DMReferenceTreeGetChildSymmetry_pforest; 21139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 21140a96aa3bSJed Brown if (rank == 0) { 21159566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRoot, NULL, "-dm_p4est_ref_root_view")); 21169566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined, NULL, "-dm_p4est_ref_refined_view")); 21179566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined, NULL, "-dm_p4est_ref_tree_view")); 21180a96aa3bSJed Brown } 21199566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 21209566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRoot)); 2121792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (refined)); 2122792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (root)); 2123792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy, (refcube)); 21243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21250a96aa3bSJed Brown } 21260a96aa3bSJed Brown 2127d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMShareDiscretization(DM dmA, DM dmB) 2128d71ae5a4SJacob Faibussowitsch { 21290a96aa3bSJed Brown void *ctx; 21300a96aa3bSJed Brown PetscInt num; 21310a96aa3bSJed Brown PetscReal val; 21320a96aa3bSJed Brown 21330a96aa3bSJed Brown PetscFunctionBegin; 21349566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmA, &ctx)); 21359566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(dmB, ctx)); 21369566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmA, dmB)); 21379566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dmA, &num, &val)); 21389566063dSJacob Faibussowitsch PetscCall(DMSetOutputSequenceNumber(dmB, num, val)); 21390a96aa3bSJed Brown if (dmB->localSection != dmA->localSection || dmB->globalSection != dmA->globalSection) { 21409566063dSJacob Faibussowitsch PetscCall(DMClearLocalVectors(dmB)); 21419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->localSection)); 2142f4f49eeaSPierre Jolivet PetscCall(PetscSectionDestroy(&dmB->localSection)); 21430a96aa3bSJed Brown dmB->localSection = dmA->localSection; 21449566063dSJacob Faibussowitsch PetscCall(DMClearGlobalVectors(dmB)); 21459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->globalSection)); 2146f4f49eeaSPierre Jolivet PetscCall(PetscSectionDestroy(&dmB->globalSection)); 21470a96aa3bSJed Brown dmB->globalSection = dmA->globalSection; 21489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.section)); 2149f4f49eeaSPierre Jolivet PetscCall(PetscSectionDestroy(&dmB->defaultConstraint.section)); 21503b8ba7d1SJed Brown dmB->defaultConstraint.section = dmA->defaultConstraint.section; 21519566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.mat)); 2152f4f49eeaSPierre Jolivet PetscCall(MatDestroy(&dmB->defaultConstraint.mat)); 21533b8ba7d1SJed Brown dmB->defaultConstraint.mat = dmA->defaultConstraint.mat; 21549566063dSJacob Faibussowitsch if (dmA->map) PetscCall(PetscLayoutReference(dmA->map, &dmB->map)); 21550a96aa3bSJed Brown } 21560a96aa3bSJed Brown if (dmB->sectionSF != dmA->sectionSF) { 21579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->sectionSF)); 21589566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&dmB->sectionSF)); 21590a96aa3bSJed Brown dmB->sectionSF = dmA->sectionSF; 21600a96aa3bSJed Brown } 21613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21620a96aa3bSJed Brown } 21630a96aa3bSJed Brown 21640a96aa3bSJed Brown /* Get an SF that broadcasts a coarse-cell covering of the local fine cells */ 2165d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetCellCoveringSF(MPI_Comm comm, p4est_t *p4estC, p4est_t *p4estF, PetscInt cStart, PetscInt cEnd, PetscSF *coveringSF) 2166d71ae5a4SJacob Faibussowitsch { 21670a96aa3bSJed Brown PetscInt startF, endF, startC, endC, p, nLeaves; 21680a96aa3bSJed Brown PetscSFNode *leaves; 21690a96aa3bSJed Brown PetscSF sf; 21700a96aa3bSJed Brown PetscInt *recv, *send; 21710a96aa3bSJed Brown PetscMPIInt tag; 21720a96aa3bSJed Brown MPI_Request *recvReqs, *sendReqs; 21730a96aa3bSJed Brown PetscSection section; 21740a96aa3bSJed Brown 21750a96aa3bSJed Brown PetscFunctionBegin; 21769566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize, p4estC->mpirank, p4estF, p4estC, &startC, &endC)); 21779566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2 * (endC - startC), &recv, endC - startC, &recvReqs)); 21789566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(comm, &tag)); 21790a96aa3bSJed Brown for (p = startC; p < endC; p++) { 21800a96aa3bSJed Brown recvReqs[p - startC] = MPI_REQUEST_NULL; /* just in case we don't initiate a receive */ 21810a96aa3bSJed Brown if (p4estC->global_first_quadrant[p] == p4estC->global_first_quadrant[p + 1]) { /* empty coarse partition */ 21820a96aa3bSJed Brown recv[2 * (p - startC)] = 0; 21830a96aa3bSJed Brown recv[2 * (p - startC) + 1] = 0; 21840a96aa3bSJed Brown continue; 21850a96aa3bSJed Brown } 21860a96aa3bSJed Brown 21879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(&recv[2 * (p - startC)], 2, MPIU_INT, p, tag, comm, &recvReqs[p - startC])); 21880a96aa3bSJed Brown } 21899566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize, p4estC->mpirank, p4estC, p4estF, &startF, &endF)); 21909566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2 * (endF - startF), &send, endF - startF, &sendReqs)); 21910a96aa3bSJed Brown /* count the quadrants rank will send to each of [startF,endF) */ 21920a96aa3bSJed Brown for (p = startF; p < endF; p++) { 21930a96aa3bSJed Brown p4est_quadrant_t *myFineStart = &p4estF->global_first_position[p]; 21940a96aa3bSJed Brown p4est_quadrant_t *myFineEnd = &p4estF->global_first_position[p + 1]; 21950a96aa3bSJed Brown PetscInt tStart = (PetscInt)myFineStart->p.which_tree; 21960a96aa3bSJed Brown PetscInt tEnd = (PetscInt)myFineEnd->p.which_tree; 21970a96aa3bSJed Brown PetscInt firstCell = -1, lastCell = -1; 21980a96aa3bSJed Brown p4est_tree_t *treeStart = &(((p4est_tree_t *)p4estC->trees->array)[tStart]); 21990a96aa3bSJed Brown p4est_tree_t *treeEnd = (size_t)tEnd < p4estC->trees->elem_count ? &(((p4est_tree_t *)p4estC->trees->array)[tEnd]) : NULL; 22000a96aa3bSJed Brown ssize_t overlapIndex; 22010a96aa3bSJed Brown 22020a96aa3bSJed Brown sendReqs[p - startF] = MPI_REQUEST_NULL; /* just in case we don't initiate a send */ 22030a96aa3bSJed Brown if (p4estF->global_first_quadrant[p] == p4estF->global_first_quadrant[p + 1]) continue; 22040a96aa3bSJed Brown 22050a96aa3bSJed Brown /* locate myFineStart in (or before) a cell */ 22060a96aa3bSJed Brown if (treeStart->quadrants.elem_count) { 2207f4f49eeaSPierre Jolivet PetscCallP4estReturn(overlapIndex, sc_array_bsearch, (&treeStart->quadrants, myFineStart, p4est_quadrant_disjoint)); 22080a96aa3bSJed Brown if (overlapIndex < 0) { 22090a96aa3bSJed Brown firstCell = 0; 22100a96aa3bSJed Brown } else { 22110a96aa3bSJed Brown firstCell = treeStart->quadrants_offset + overlapIndex; 22120a96aa3bSJed Brown } 22130a96aa3bSJed Brown } else { 22140a96aa3bSJed Brown firstCell = 0; 22150a96aa3bSJed Brown } 22160a96aa3bSJed Brown if (treeEnd && treeEnd->quadrants.elem_count) { 2217f4f49eeaSPierre Jolivet PetscCallP4estReturn(overlapIndex, sc_array_bsearch, (&treeEnd->quadrants, myFineEnd, p4est_quadrant_disjoint)); 22180a96aa3bSJed Brown if (overlapIndex < 0) { /* all of this local section is overlapped */ 22190a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 22200a96aa3bSJed Brown } else { 22210a96aa3bSJed Brown p4est_quadrant_t *container = &(((p4est_quadrant_t *)treeEnd->quadrants.array)[overlapIndex]); 22220a96aa3bSJed Brown p4est_quadrant_t first_desc; 22230a96aa3bSJed Brown int equal; 22240a96aa3bSJed Brown 2225792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_first_descendant, (container, &first_desc, P4EST_QMAXLEVEL)); 2226792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal, (myFineEnd, &first_desc)); 22270a96aa3bSJed Brown if (equal) { 22280a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex; 22290a96aa3bSJed Brown } else { 22300a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex + 1; 22310a96aa3bSJed Brown } 22320a96aa3bSJed Brown } 22330a96aa3bSJed Brown } else { 22340a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 22350a96aa3bSJed Brown } 22360a96aa3bSJed Brown send[2 * (p - startF)] = firstCell; 22370a96aa3bSJed Brown send[2 * (p - startF) + 1] = lastCell - firstCell; 22389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(&send[2 * (p - startF)], 2, MPIU_INT, p, tag, comm, &sendReqs[p - startF])); 22390a96aa3bSJed Brown } 22409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endC - startC), recvReqs, MPI_STATUSES_IGNORE)); 22419566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion)); 22429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, startC, endC)); 22430a96aa3bSJed Brown for (p = startC; p < endC; p++) { 22440a96aa3bSJed Brown PetscInt numCells = recv[2 * (p - startC) + 1]; 22459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, numCells)); 22460a96aa3bSJed Brown } 22479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 22489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &nLeaves)); 22499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &leaves)); 22500a96aa3bSJed Brown for (p = startC; p < endC; p++) { 22510a96aa3bSJed Brown PetscInt firstCell = recv[2 * (p - startC)]; 22520a96aa3bSJed Brown PetscInt numCells = recv[2 * (p - startC) + 1]; 22530a96aa3bSJed Brown PetscInt off, i; 22540a96aa3bSJed Brown 22559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off)); 22560a96aa3bSJed Brown for (i = 0; i < numCells; i++) { 22570a96aa3bSJed Brown leaves[off + i].rank = p; 22580a96aa3bSJed Brown leaves[off + i].index = firstCell + i; 22590a96aa3bSJed Brown } 22600a96aa3bSJed Brown } 22619566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sf)); 22629566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, cEnd - cStart, nLeaves, NULL, PETSC_OWN_POINTER, leaves, PETSC_OWN_POINTER)); 22639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 22649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endF - startF), sendReqs, MPI_STATUSES_IGNORE)); 22659566063dSJacob Faibussowitsch PetscCall(PetscFree2(send, sendReqs)); 22669566063dSJacob Faibussowitsch PetscCall(PetscFree2(recv, recvReqs)); 22670a96aa3bSJed Brown *coveringSF = sf; 22683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22690a96aa3bSJed Brown } 22700a96aa3bSJed Brown 22710a96aa3bSJed Brown /* closure points for locally-owned cells */ 2272d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetCellSFNodes(DM dm, PetscInt numClosureIndices, PetscInt *numClosurePoints, PetscSFNode **closurePoints, PetscBool redirect) 2273d71ae5a4SJacob Faibussowitsch { 22740a96aa3bSJed Brown PetscInt cStart, cEnd; 22750a96aa3bSJed Brown PetscInt count, c; 22760a96aa3bSJed Brown PetscMPIInt rank; 22770a96aa3bSJed Brown PetscInt closureSize = -1; 22780a96aa3bSJed Brown PetscInt *closure = NULL; 22790a96aa3bSJed Brown PetscSF pointSF; 22800a96aa3bSJed Brown PetscInt nleaves, nroots; 22810a96aa3bSJed Brown const PetscInt *ilocal; 22820a96aa3bSJed Brown const PetscSFNode *iremote; 22830a96aa3bSJed Brown DM plex; 22840a96aa3bSJed Brown DM_Forest *forest; 22850a96aa3bSJed Brown DM_Forest_pforest *pforest; 22860a96aa3bSJed Brown 22870a96aa3bSJed Brown PetscFunctionBegin; 22880a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 22890a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 22900a96aa3bSJed Brown cStart = pforest->cLocalStart; 22910a96aa3bSJed Brown cEnd = pforest->cLocalEnd; 22929566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 22939566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &pointSF)); 22949566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &ilocal, &iremote)); 22950a96aa3bSJed Brown nleaves = PetscMax(0, nleaves); 22960a96aa3bSJed Brown nroots = PetscMax(0, nroots); 22970a96aa3bSJed Brown *numClosurePoints = numClosureIndices * (cEnd - cStart); 22989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numClosurePoints, closurePoints)); 22999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 23000a96aa3bSJed Brown for (c = cStart, count = 0; c < cEnd; c++) { 23010a96aa3bSJed Brown PetscInt i; 23029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, c, PETSC_TRUE, &closureSize, &closure)); 23030a96aa3bSJed Brown 23040a96aa3bSJed Brown for (i = 0; i < numClosureIndices; i++, count++) { 23050a96aa3bSJed Brown PetscInt p = closure[2 * i]; 23060a96aa3bSJed Brown PetscInt loc = -1; 23070a96aa3bSJed Brown 23089566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p, nleaves, ilocal, &loc)); 23090a96aa3bSJed Brown if (redirect && loc >= 0) { 23100a96aa3bSJed Brown (*closurePoints)[count].rank = iremote[loc].rank; 23110a96aa3bSJed Brown (*closurePoints)[count].index = iremote[loc].index; 23120a96aa3bSJed Brown } else { 23130a96aa3bSJed Brown (*closurePoints)[count].rank = rank; 23140a96aa3bSJed Brown (*closurePoints)[count].index = p; 23150a96aa3bSJed Brown } 23160a96aa3bSJed Brown } 23179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, c, PETSC_TRUE, &closureSize, &closure)); 23180a96aa3bSJed Brown } 23193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23200a96aa3bSJed Brown } 23210a96aa3bSJed Brown 2322d71ae5a4SJacob Faibussowitsch static void MPIAPI DMPforestMaxSFNode(void *a, void *b, PetscMPIInt *len, MPI_Datatype *type) 2323d71ae5a4SJacob Faibussowitsch { 23240a96aa3bSJed Brown PetscMPIInt i; 23250a96aa3bSJed Brown 23260a96aa3bSJed Brown for (i = 0; i < *len; i++) { 23270a96aa3bSJed Brown PetscSFNode *A = (PetscSFNode *)a; 23280a96aa3bSJed Brown PetscSFNode *B = (PetscSFNode *)b; 23290a96aa3bSJed Brown 23300a96aa3bSJed Brown if (B->rank < 0) *B = *A; 23310a96aa3bSJed Brown } 23320a96aa3bSJed Brown } 23330a96aa3bSJed Brown 2334d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetTransferSF_Point(DM coarse, DM fine, PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 2335d71ae5a4SJacob Faibussowitsch { 23360a96aa3bSJed Brown MPI_Comm comm; 23370a96aa3bSJed Brown PetscMPIInt rank, size; 23380a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 23390a96aa3bSJed Brown p4est_t *p4estC, *p4estF; 23400a96aa3bSJed Brown PetscInt numClosureIndices; 23410a96aa3bSJed Brown PetscInt numClosurePointsC, numClosurePointsF; 23420a96aa3bSJed Brown PetscSFNode *closurePointsC, *closurePointsF; 23430a96aa3bSJed Brown p4est_quadrant_t *coverQuads = NULL; 23440a96aa3bSJed Brown p4est_quadrant_t **treeQuads; 23450a96aa3bSJed Brown PetscInt *treeQuadCounts; 23460a96aa3bSJed Brown MPI_Datatype nodeType; 23470a96aa3bSJed Brown MPI_Datatype nodeClosureType; 23480a96aa3bSJed Brown MPI_Op sfNodeReduce; 23490a96aa3bSJed Brown p4est_topidx_t fltF, lltF, t; 23500a96aa3bSJed Brown DM plexC, plexF; 23510a96aa3bSJed Brown PetscInt pStartF, pEndF, pStartC, pEndC; 23520a96aa3bSJed Brown PetscBool saveInCoarse = PETSC_FALSE; 23530a96aa3bSJed Brown PetscBool saveInFine = PETSC_FALSE; 23540a96aa3bSJed Brown PetscBool formCids = (childIds != NULL) ? PETSC_TRUE : PETSC_FALSE; 23550a96aa3bSJed Brown PetscInt *cids = NULL; 23560a96aa3bSJed Brown 23570a96aa3bSJed Brown PetscFunctionBegin; 23580a96aa3bSJed Brown pforestC = (DM_Forest_pforest *)((DM_Forest *)coarse->data)->data; 23590a96aa3bSJed Brown pforestF = (DM_Forest_pforest *)((DM_Forest *)fine->data)->data; 23600a96aa3bSJed Brown p4estC = pforestC->forest; 23610a96aa3bSJed Brown p4estF = pforestF->forest; 236208401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo, PetscObjectComm((PetscObject)coarse), PETSC_ERR_ARG_INCOMP, "DM's must have the same base DM"); 23630a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 23649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 23659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 23669566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine, &plexF)); 23679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF, &pStartF, &pEndF)); 23689566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse, &plexC)); 23699566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC, &pStartC, &pEndC)); 23700a96aa3bSJed Brown { /* check if the results have been cached */ 23710a96aa3bSJed Brown DM adaptCoarse, adaptFine; 23720a96aa3bSJed Brown 23739566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(coarse, &adaptCoarse)); 23749566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(fine, &adaptFine)); 23750a96aa3bSJed Brown if (adaptCoarse && adaptCoarse->data == fine->data) { /* coarse is adapted from fine */ 23760a96aa3bSJed Brown if (pforestC->pointSelfToAdaptSF) { 2377f4f49eeaSPierre Jolivet PetscCall(PetscObjectReference((PetscObject)pforestC->pointSelfToAdaptSF)); 23780a96aa3bSJed Brown *sf = pforestC->pointSelfToAdaptSF; 23790a96aa3bSJed Brown if (childIds) { 23809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids)); 23819566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids, pforestC->pointSelfToAdaptCids, pEndF - pStartF)); 23820a96aa3bSJed Brown *childIds = cids; 23830a96aa3bSJed Brown } 23843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23850a96aa3bSJed Brown } else { 23860a96aa3bSJed Brown saveInCoarse = PETSC_TRUE; 23870a96aa3bSJed Brown formCids = PETSC_TRUE; 23880a96aa3bSJed Brown } 23890a96aa3bSJed Brown } else if (adaptFine && adaptFine->data == coarse->data) { /* fine is adapted from coarse */ 23900a96aa3bSJed Brown if (pforestF->pointAdaptToSelfSF) { 2391f4f49eeaSPierre Jolivet PetscCall(PetscObjectReference((PetscObject)pforestF->pointAdaptToSelfSF)); 23920a96aa3bSJed Brown *sf = pforestF->pointAdaptToSelfSF; 23930a96aa3bSJed Brown if (childIds) { 23949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids)); 23959566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids, pforestF->pointAdaptToSelfCids, pEndF - pStartF)); 23960a96aa3bSJed Brown *childIds = cids; 23970a96aa3bSJed Brown } 23983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23990a96aa3bSJed Brown } else { 24000a96aa3bSJed Brown saveInFine = PETSC_TRUE; 24010a96aa3bSJed Brown formCids = PETSC_TRUE; 24020a96aa3bSJed Brown } 24030a96aa3bSJed Brown } 24040a96aa3bSJed Brown } 24050a96aa3bSJed Brown 24060a96aa3bSJed Brown /* count the number of closure points that have dofs and create a list */ 24070a96aa3bSJed Brown numClosureIndices = P4EST_INSUL; 24080a96aa3bSJed Brown /* create the datatype */ 24099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(2, MPIU_INT, &nodeType)); 24109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 24119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(DMPforestMaxSFNode, PETSC_FALSE, &sfNodeReduce)); 24129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(numClosureIndices * 2, MPIU_INT, &nodeClosureType)); 24139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeClosureType)); 24140a96aa3bSJed Brown /* everything has to go through cells: for each cell, create a list of the sfnodes in its closure */ 24150a96aa3bSJed Brown /* get lists of closure point SF nodes for every cell */ 24169566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(coarse, numClosureIndices, &numClosurePointsC, &closurePointsC, PETSC_TRUE)); 24179566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(fine, numClosureIndices, &numClosurePointsF, &closurePointsF, PETSC_FALSE)); 24180a96aa3bSJed Brown /* create pointers for tree lists */ 24190a96aa3bSJed Brown fltF = p4estF->first_local_tree; 24200a96aa3bSJed Brown lltF = p4estF->last_local_tree; 24219566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(lltF + 1 - fltF, &treeQuads, lltF + 1 - fltF, &treeQuadCounts)); 24220a96aa3bSJed Brown /* if the partitions don't match, ship the coarse to cover the fine */ 24230a96aa3bSJed Brown if (size > 1) { 24240a96aa3bSJed Brown PetscInt p; 24250a96aa3bSJed Brown 24260a96aa3bSJed Brown for (p = 0; p < size; p++) { 24270a96aa3bSJed Brown int equal; 24280a96aa3bSJed Brown 2429792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal_piggy, (&p4estC->global_first_position[p], &p4estF->global_first_position[p])); 24300a96aa3bSJed Brown if (!equal) break; 24310a96aa3bSJed Brown } 24320a96aa3bSJed Brown if (p < size) { /* non-matching distribution: send the coarse to cover the fine */ 24330a96aa3bSJed Brown PetscInt cStartC, cEndC; 24340a96aa3bSJed Brown PetscSF coveringSF; 24350a96aa3bSJed Brown PetscInt nleaves; 24360a96aa3bSJed Brown PetscInt count; 24370a96aa3bSJed Brown PetscSFNode *newClosurePointsC; 24380a96aa3bSJed Brown p4est_quadrant_t *coverQuadsSend; 24390a96aa3bSJed Brown p4est_topidx_t fltC = p4estC->first_local_tree; 24400a96aa3bSJed Brown p4est_topidx_t lltC = p4estC->last_local_tree; 24410a96aa3bSJed Brown p4est_topidx_t t; 24420a96aa3bSJed Brown PetscMPIInt blockSizes[4] = {P4EST_DIM, 2, 1, 1}; 24439371c9d4SSatish 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)}; 24440a96aa3bSJed Brown MPI_Datatype blockTypes[4] = {MPI_INT32_T, MPI_INT8_T, MPI_INT16_T, MPI_INT32_T /* p.which_tree */}; 24450a96aa3bSJed Brown MPI_Datatype quadStruct, quadType; 24460a96aa3bSJed Brown 24479566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC, 0, &cStartC, &cEndC)); 24489566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellCoveringSF(comm, p4estC, p4estF, pforestC->cLocalStart, pforestC->cLocalEnd, &coveringSF)); 24499566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coveringSF, NULL, &nleaves, NULL, NULL)); 24509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numClosureIndices * nleaves, &newClosurePointsC)); 24519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &coverQuads)); 24529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEndC - cStartC, &coverQuadsSend)); 24530a96aa3bSJed Brown count = 0; 24540a96aa3bSJed Brown for (t = fltC; t <= lltC; t++) { /* unfortunately, we need to pack a send array, since quads are not stored packed in p4est */ 24550a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estC->trees->array)[t]); 24560a96aa3bSJed Brown PetscInt q; 24570a96aa3bSJed Brown 24589566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&coverQuadsSend[count], tree->quadrants.array, tree->quadrants.elem_count * sizeof(p4est_quadrant_t))); 24590a96aa3bSJed Brown for (q = 0; (size_t)q < tree->quadrants.elem_count; q++) coverQuadsSend[count + q].p.which_tree = t; 24600a96aa3bSJed Brown count += tree->quadrants.elem_count; 24610a96aa3bSJed Brown } 24620a96aa3bSJed Brown /* p is of a union type p4est_quadrant_data, but only the p.which_tree field is active at this time. So, we 24630a96aa3bSJed Brown have a simple blockTypes[] to use. Note that quadStruct does not count potential padding in array of 24640a96aa3bSJed Brown p4est_quadrant_t. We have to call MPI_Type_create_resized() to change upper-bound of quadStruct. 24650a96aa3bSJed Brown */ 24669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(4, blockSizes, blockOffsets, blockTypes, &quadStruct)); 24679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_resized(quadStruct, 0, sizeof(p4est_quadrant_t), &quadType)); 24689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&quadType)); 24699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF, nodeClosureType, closurePointsC, newClosurePointsC, MPI_REPLACE)); 24709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF, quadType, coverQuadsSend, coverQuads, MPI_REPLACE)); 24719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF, nodeClosureType, closurePointsC, newClosurePointsC, MPI_REPLACE)); 24729566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF, quadType, coverQuadsSend, coverQuads, MPI_REPLACE)); 24739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadStruct)); 24749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadType)); 24759566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuadsSend)); 24769566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 24779566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coveringSF)); 24780a96aa3bSJed Brown closurePointsC = newClosurePointsC; 24790a96aa3bSJed Brown 24800a96aa3bSJed Brown /* assign tree quads based on locations in coverQuads */ 24810a96aa3bSJed Brown { 24820a96aa3bSJed Brown PetscInt q; 24830a96aa3bSJed Brown for (q = 0; q < nleaves; q++) { 24840a96aa3bSJed Brown p4est_locidx_t t = coverQuads[q].p.which_tree; 24850a96aa3bSJed Brown if (!treeQuadCounts[t - fltF]++) treeQuads[t - fltF] = &coverQuads[q]; 24860a96aa3bSJed Brown } 24870a96aa3bSJed Brown } 24880a96aa3bSJed Brown } 24890a96aa3bSJed Brown } 24900a96aa3bSJed Brown if (!coverQuads) { /* matching partitions: assign tree quads based on locations in p4est native arrays */ 24910a96aa3bSJed Brown for (t = fltF; t <= lltF; t++) { 24920a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estC->trees->array)[t]); 24930a96aa3bSJed Brown 24940a96aa3bSJed Brown treeQuadCounts[t - fltF] = tree->quadrants.elem_count; 24950a96aa3bSJed Brown treeQuads[t - fltF] = (p4est_quadrant_t *)tree->quadrants.array; 24960a96aa3bSJed Brown } 24970a96aa3bSJed Brown } 24980a96aa3bSJed Brown 24990a96aa3bSJed Brown { 25000a96aa3bSJed Brown PetscInt p; 25010a96aa3bSJed Brown PetscInt cLocalStartF; 25020a96aa3bSJed Brown PetscSF pointSF; 25030a96aa3bSJed Brown PetscSFNode *roots; 25040a96aa3bSJed Brown PetscInt *rootType; 25050a96aa3bSJed Brown DM refTree = NULL; 25060a96aa3bSJed Brown DMLabel canonical; 25070a96aa3bSJed Brown PetscInt *childClosures[P4EST_CHILDREN] = {NULL}; 25080a96aa3bSJed Brown PetscInt *rootClosure = NULL; 25090a96aa3bSJed Brown PetscInt coarseOffset; 25100a96aa3bSJed Brown PetscInt numCoarseQuads; 25110a96aa3bSJed Brown 25129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &roots)); 25139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &rootType)); 25149566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(fine, &pointSF)); 25150a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 25160a96aa3bSJed Brown roots[p - pStartF].rank = -1; 25170a96aa3bSJed Brown roots[p - pStartF].index = -1; 25180a96aa3bSJed Brown rootType[p - pStartF] = -1; 25190a96aa3bSJed Brown } 25200a96aa3bSJed Brown if (formCids) { 25210a96aa3bSJed Brown PetscInt child; 25220a96aa3bSJed Brown 25239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids)); 25240a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) cids[p - pStartF] = -2; 25259566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF, &refTree)); 25269566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, 0, PETSC_TRUE, NULL, &rootClosure)); 25270a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { /* get the closures of the child cells in the reference tree */ 25289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child + 1, PETSC_TRUE, NULL, &childClosures[child])); 25290a96aa3bSJed Brown } 25309566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical)); 25310a96aa3bSJed Brown } 25320a96aa3bSJed Brown cLocalStartF = pforestF->cLocalStart; 25330a96aa3bSJed Brown for (t = fltF, coarseOffset = 0, numCoarseQuads = 0; t <= lltF; t++, coarseOffset += numCoarseQuads) { 25340a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estF->trees->array)[t]); 25350a96aa3bSJed Brown PetscInt numFineQuads = tree->quadrants.elem_count; 25360a96aa3bSJed Brown p4est_quadrant_t *coarseQuads = treeQuads[t - fltF]; 25370a96aa3bSJed Brown p4est_quadrant_t *fineQuads = (p4est_quadrant_t *)tree->quadrants.array; 25380a96aa3bSJed Brown PetscInt i, coarseCount = 0; 25390a96aa3bSJed Brown PetscInt offset = tree->quadrants_offset; 25400a96aa3bSJed Brown sc_array_t coarseQuadsArray; 25410a96aa3bSJed Brown 25420a96aa3bSJed Brown numCoarseQuads = treeQuadCounts[t - fltF]; 2543792fecdfSBarry Smith PetscCallP4est(sc_array_init_data, (&coarseQuadsArray, coarseQuads, sizeof(p4est_quadrant_t), (size_t)numCoarseQuads)); 25440a96aa3bSJed Brown for (i = 0; i < numFineQuads; i++) { 25450a96aa3bSJed Brown PetscInt c = i + offset; 25460a96aa3bSJed Brown p4est_quadrant_t *quad = &fineQuads[i]; 25470a96aa3bSJed Brown p4est_quadrant_t *quadCoarse = NULL; 25480a96aa3bSJed Brown ssize_t disjoint = -1; 25490a96aa3bSJed Brown 25500a96aa3bSJed Brown while (disjoint < 0 && coarseCount < numCoarseQuads) { 25510a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2552792fecdfSBarry Smith PetscCallP4estReturn(disjoint, p4est_quadrant_disjoint, (quadCoarse, quad)); 25530a96aa3bSJed Brown if (disjoint < 0) coarseCount++; 25540a96aa3bSJed Brown } 255508401ef6SPierre Jolivet PetscCheck(disjoint == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "did not find overlapping coarse quad"); 25560a96aa3bSJed Brown if (quadCoarse->level > quad->level || (quadCoarse->level == quad->level && !transferIdent)) { /* the "coarse" mesh is finer than the fine mesh at the point: continue */ 25570a96aa3bSJed Brown if (transferIdent) { /* find corners */ 25580a96aa3bSJed Brown PetscInt j = 0; 25590a96aa3bSJed Brown 25600a96aa3bSJed Brown do { 25610a96aa3bSJed Brown if (j < P4EST_CHILDREN) { 25620a96aa3bSJed Brown p4est_quadrant_t cornerQuad; 25630a96aa3bSJed Brown int equal; 25640a96aa3bSJed Brown 2565792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_descendant, (quad, &cornerQuad, j, quadCoarse->level)); 2566792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal, (&cornerQuad, quadCoarse)); 25670a96aa3bSJed Brown if (equal) { 25680a96aa3bSJed Brown PetscInt petscJ = P4estVertToPetscVert[j]; 25690a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + (P4EST_INSUL - P4EST_CHILDREN) + petscJ].index; 25700a96aa3bSJed Brown PetscSFNode q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + (P4EST_INSUL - P4EST_CHILDREN) + petscJ]; 25710a96aa3bSJed Brown 25720a96aa3bSJed Brown roots[p - pStartF] = q; 25730a96aa3bSJed Brown rootType[p - pStartF] = PETSC_MAX_INT; 25740a96aa3bSJed Brown cids[p - pStartF] = -1; 25750a96aa3bSJed Brown j++; 25760a96aa3bSJed Brown } 25770a96aa3bSJed Brown } 25780a96aa3bSJed Brown coarseCount++; 25790a96aa3bSJed Brown disjoint = 1; 25800a96aa3bSJed Brown if (coarseCount < numCoarseQuads) { 25810a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2582792fecdfSBarry Smith PetscCallP4estReturn(disjoint, p4est_quadrant_disjoint, (quadCoarse, quad)); 25830a96aa3bSJed Brown } 25840a96aa3bSJed Brown } while (!disjoint); 25850a96aa3bSJed Brown } 25860a96aa3bSJed Brown continue; 25870a96aa3bSJed Brown } 25880a96aa3bSJed Brown if (quadCoarse->level == quad->level) { /* same quad present in coarse and fine mesh */ 25890a96aa3bSJed Brown PetscInt j; 25900a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 25910a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + j].index; 25920a96aa3bSJed Brown 25930a96aa3bSJed Brown roots[p - pStartF] = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + j]; 25940a96aa3bSJed Brown rootType[p - pStartF] = PETSC_MAX_INT; /* unconditionally accept */ 25950a96aa3bSJed Brown cids[p - pStartF] = -1; 25960a96aa3bSJed Brown } 25970a96aa3bSJed Brown } else { 25980a96aa3bSJed Brown PetscInt levelDiff = quad->level - quadCoarse->level; 25990a96aa3bSJed Brown PetscInt proposedCids[P4EST_INSUL] = {0}; 26000a96aa3bSJed Brown 26010a96aa3bSJed Brown if (formCids) { 26020a96aa3bSJed Brown PetscInt cl; 26030a96aa3bSJed Brown PetscInt *pointClosure = NULL; 26040a96aa3bSJed Brown int cid; 26050a96aa3bSJed Brown 260608401ef6SPierre Jolivet PetscCheck(levelDiff <= 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Recursive child ids not implemented"); 2607792fecdfSBarry Smith PetscCallP4estReturn(cid, p4est_quadrant_child_id, (quad)); 26089566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plexF, c + cLocalStartF, PETSC_TRUE, NULL, &pointClosure)); 26090a96aa3bSJed Brown for (cl = 0; cl < P4EST_INSUL; cl++) { 26100a96aa3bSJed Brown PetscInt p = pointClosure[2 * cl]; 26110a96aa3bSJed Brown PetscInt point = childClosures[cid][2 * cl]; 26120a96aa3bSJed Brown PetscInt ornt = childClosures[cid][2 * cl + 1]; 26130a96aa3bSJed Brown PetscInt newcid = -1; 26140a96aa3bSJed Brown DMPolytopeType ct; 26150a96aa3bSJed Brown 26160a96aa3bSJed Brown if (rootType[p - pStartF] == PETSC_MAX_INT) continue; 26179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, point, &ct)); 26180a96aa3bSJed Brown ornt = DMPolytopeConvertNewOrientation_Internal(ct, ornt); 26190a96aa3bSJed Brown if (!cl) { 26200a96aa3bSJed Brown newcid = cid + 1; 26210a96aa3bSJed Brown } else { 26220a96aa3bSJed Brown PetscInt rcl, parent, parentOrnt = 0; 26230a96aa3bSJed Brown 26249566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, point, &parent, NULL)); 26250a96aa3bSJed Brown if (parent == point) { 26260a96aa3bSJed Brown newcid = -1; 26270a96aa3bSJed Brown } else if (!parent) { /* in the root */ 26280a96aa3bSJed Brown newcid = point; 26290a96aa3bSJed Brown } else { 26300a96aa3bSJed Brown DMPolytopeType rct = DM_POLYTOPE_UNKNOWN; 26310a96aa3bSJed Brown 26320a96aa3bSJed Brown for (rcl = 1; rcl < P4EST_INSUL; rcl++) { 26330a96aa3bSJed Brown if (rootClosure[2 * rcl] == parent) { 26349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, parent, &rct)); 26350a96aa3bSJed Brown parentOrnt = DMPolytopeConvertNewOrientation_Internal(rct, rootClosure[2 * rcl + 1]); 26360a96aa3bSJed Brown break; 26370a96aa3bSJed Brown } 26380a96aa3bSJed Brown } 263908401ef6SPierre Jolivet PetscCheck(rcl < P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Couldn't find parent in root closure"); 26409566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(refTree, parent, parentOrnt, ornt, point, DMPolytopeConvertNewOrientation_Internal(rct, pointClosure[2 * rcl + 1]), NULL, &newcid)); 26410a96aa3bSJed Brown } 26420a96aa3bSJed Brown } 26430a96aa3bSJed Brown if (newcid >= 0) { 264448a46eb9SPierre Jolivet if (canonical) PetscCall(DMLabelGetValue(canonical, newcid, &newcid)); 26450a96aa3bSJed Brown proposedCids[cl] = newcid; 26460a96aa3bSJed Brown } 26470a96aa3bSJed Brown } 26489566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plexF, c + cLocalStartF, PETSC_TRUE, NULL, &pointClosure)); 26490a96aa3bSJed Brown } 26509371c9d4SSatish Balay p4est_qcoord_t coarseBound[2][P4EST_DIM] = { 26519371c9d4SSatish Balay {quadCoarse->x, quadCoarse->y, 26520a96aa3bSJed Brown #if defined(P4_TO_P8) 26530a96aa3bSJed Brown quadCoarse->z 26540a96aa3bSJed Brown #endif 26559371c9d4SSatish Balay }, 26569371c9d4SSatish Balay {0} 26579371c9d4SSatish Balay }; 26589371c9d4SSatish Balay p4est_qcoord_t fineBound[2][P4EST_DIM] = { 26599371c9d4SSatish Balay {quad->x, quad->y, 26600a96aa3bSJed Brown #if defined(P4_TO_P8) 26610a96aa3bSJed Brown quad->z 26620a96aa3bSJed Brown #endif 26639371c9d4SSatish Balay }, 26649371c9d4SSatish Balay {0} 26659371c9d4SSatish Balay }; 26660a96aa3bSJed Brown PetscInt j; 26670a96aa3bSJed Brown for (j = 0; j < P4EST_DIM; j++) { /* get the coordinates of cell boundaries in each direction */ 26680a96aa3bSJed Brown coarseBound[1][j] = coarseBound[0][j] + P4EST_QUADRANT_LEN(quadCoarse->level); 26690a96aa3bSJed Brown fineBound[1][j] = fineBound[0][j] + P4EST_QUADRANT_LEN(quad->level); 26700a96aa3bSJed Brown } 26710a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 26720a96aa3bSJed Brown PetscInt l, p; 26730a96aa3bSJed Brown PetscSFNode q; 26740a96aa3bSJed Brown 26750a96aa3bSJed Brown p = closurePointsF[numClosureIndices * c + j].index; 26760a96aa3bSJed Brown if (rootType[p - pStartF] == PETSC_MAX_INT) continue; 26770a96aa3bSJed Brown if (j == 0) { /* volume: ancestor is volume */ 26780a96aa3bSJed Brown l = 0; 26790a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES) { /* facet */ 26800a96aa3bSJed Brown PetscInt face = PetscFaceToP4estFace[j - 1]; 26810a96aa3bSJed Brown PetscInt direction = face / 2; 26820a96aa3bSJed Brown PetscInt coarseFace = -1; 26830a96aa3bSJed Brown 26840a96aa3bSJed Brown if (coarseBound[face % 2][direction] == fineBound[face % 2][direction]) { 26850a96aa3bSJed Brown coarseFace = face; 26860a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 26870a96aa3bSJed Brown } else { 26880a96aa3bSJed Brown l = 0; 26890a96aa3bSJed Brown } 26900a96aa3bSJed Brown #if defined(P4_TO_P8) 26910a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES + P8EST_EDGES) { 26920a96aa3bSJed Brown PetscInt edge = PetscEdgeToP4estEdge[j - (1 + P4EST_FACES)]; 26930a96aa3bSJed Brown PetscInt direction = edge / 4; 26940a96aa3bSJed Brown PetscInt mod = edge % 4; 26950a96aa3bSJed Brown PetscInt coarseEdge = -1, coarseFace = -1; 26960a96aa3bSJed Brown PetscInt minDir = PetscMin((direction + 1) % 3, (direction + 2) % 3); 26970a96aa3bSJed Brown PetscInt maxDir = PetscMax((direction + 1) % 3, (direction + 2) % 3); 26980a96aa3bSJed Brown PetscBool dirTest[2]; 26990a96aa3bSJed Brown 27000a96aa3bSJed Brown dirTest[0] = (PetscBool)(coarseBound[mod % 2][minDir] == fineBound[mod % 2][minDir]); 27010a96aa3bSJed Brown dirTest[1] = (PetscBool)(coarseBound[mod / 2][maxDir] == fineBound[mod / 2][maxDir]); 27020a96aa3bSJed Brown 27030a96aa3bSJed Brown if (dirTest[0] && dirTest[1]) { /* fine edge falls on coarse edge */ 27040a96aa3bSJed Brown coarseEdge = edge; 27050a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 27060a96aa3bSJed Brown } else if (dirTest[0]) { /* fine edge falls on a coarse face in the minDir direction */ 27070a96aa3bSJed Brown coarseFace = 2 * minDir + (mod % 2); 27080a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27090a96aa3bSJed Brown } else if (dirTest[1]) { /* fine edge falls on a coarse face in the maxDir direction */ 27100a96aa3bSJed Brown coarseFace = 2 * maxDir + (mod / 2); 27110a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27120a96aa3bSJed Brown } else { 27130a96aa3bSJed Brown l = 0; 27140a96aa3bSJed Brown } 27150a96aa3bSJed Brown #endif 27160a96aa3bSJed Brown } else { 27170a96aa3bSJed Brown PetscInt vertex = PetscVertToP4estVert[P4EST_CHILDREN - (P4EST_INSUL - j)]; 27180a96aa3bSJed Brown PetscBool dirTest[P4EST_DIM]; 27190a96aa3bSJed Brown PetscInt m; 27200a96aa3bSJed Brown PetscInt numMatch = 0; 27210a96aa3bSJed Brown PetscInt coarseVertex = -1, coarseFace = -1; 27220a96aa3bSJed Brown #if defined(P4_TO_P8) 27230a96aa3bSJed Brown PetscInt coarseEdge = -1; 27240a96aa3bSJed Brown #endif 27250a96aa3bSJed Brown 27260a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27270a96aa3bSJed Brown dirTest[m] = (PetscBool)(coarseBound[(vertex >> m) & 1][m] == fineBound[(vertex >> m) & 1][m]); 27280a96aa3bSJed Brown if (dirTest[m]) numMatch++; 27290a96aa3bSJed Brown } 27300a96aa3bSJed Brown if (numMatch == P4EST_DIM) { /* vertex on vertex */ 27310a96aa3bSJed Brown coarseVertex = vertex; 27320a96aa3bSJed Brown l = P4EST_INSUL - (P4EST_CHILDREN - P4estVertToPetscVert[coarseVertex]); 27330a96aa3bSJed Brown } else if (numMatch == 1) { /* vertex on face */ 27340a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27350a96aa3bSJed Brown if (dirTest[m]) { 27360a96aa3bSJed Brown coarseFace = 2 * m + ((vertex >> m) & 1); 27370a96aa3bSJed Brown break; 27380a96aa3bSJed Brown } 27390a96aa3bSJed Brown } 27400a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27410a96aa3bSJed Brown #if defined(P4_TO_P8) 27420a96aa3bSJed Brown } else if (numMatch == 2) { /* vertex on edge */ 27430a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27440a96aa3bSJed Brown if (!dirTest[m]) { 27450a96aa3bSJed Brown PetscInt otherDir1 = (m + 1) % 3; 27460a96aa3bSJed Brown PetscInt otherDir2 = (m + 2) % 3; 27470a96aa3bSJed Brown PetscInt minDir = PetscMin(otherDir1, otherDir2); 27480a96aa3bSJed Brown PetscInt maxDir = PetscMax(otherDir1, otherDir2); 27490a96aa3bSJed Brown 27500a96aa3bSJed Brown coarseEdge = m * 4 + 2 * ((vertex >> maxDir) & 1) + ((vertex >> minDir) & 1); 27510a96aa3bSJed Brown break; 27520a96aa3bSJed Brown } 27530a96aa3bSJed Brown } 27540a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 27550a96aa3bSJed Brown #endif 27560a96aa3bSJed Brown } else { /* volume */ 27570a96aa3bSJed Brown l = 0; 27580a96aa3bSJed Brown } 27590a96aa3bSJed Brown } 27600a96aa3bSJed Brown q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + l]; 27610a96aa3bSJed Brown if (l > rootType[p - pStartF]) { 27620a96aa3bSJed Brown if (l >= P4EST_INSUL - P4EST_CHILDREN) { /* vertex on vertex: unconditional acceptance */ 27630a96aa3bSJed Brown if (transferIdent) { 27640a96aa3bSJed Brown roots[p - pStartF] = q; 27650a96aa3bSJed Brown rootType[p - pStartF] = PETSC_MAX_INT; 27660a96aa3bSJed Brown if (formCids) cids[p - pStartF] = -1; 27670a96aa3bSJed Brown } 27680a96aa3bSJed Brown } else { 27690a96aa3bSJed Brown PetscInt k, thisp = p, limit; 27700a96aa3bSJed Brown 27710a96aa3bSJed Brown roots[p - pStartF] = q; 27720a96aa3bSJed Brown rootType[p - pStartF] = l; 27730a96aa3bSJed Brown if (formCids) cids[p - pStartF] = proposedCids[j]; 27740a96aa3bSJed Brown limit = transferIdent ? levelDiff : (levelDiff - 1); 27750a96aa3bSJed Brown for (k = 0; k < limit; k++) { 27760a96aa3bSJed Brown PetscInt parent; 27770a96aa3bSJed Brown 27789566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plexF, thisp, &parent, NULL)); 27790a96aa3bSJed Brown if (parent == thisp) break; 27800a96aa3bSJed Brown 27810a96aa3bSJed Brown roots[parent - pStartF] = q; 27820a96aa3bSJed Brown rootType[parent - pStartF] = PETSC_MAX_INT; 27830a96aa3bSJed Brown if (formCids) cids[parent - pStartF] = -1; 27840a96aa3bSJed Brown thisp = parent; 27850a96aa3bSJed Brown } 27860a96aa3bSJed Brown } 27870a96aa3bSJed Brown } 27880a96aa3bSJed Brown } 27890a96aa3bSJed Brown } 27900a96aa3bSJed Brown } 27910a96aa3bSJed Brown } 27920a96aa3bSJed Brown 27930a96aa3bSJed 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 */ 27940a96aa3bSJed Brown if (size > 1) { 27950a96aa3bSJed Brown PetscInt *rootTypeCopy, p; 27960a96aa3bSJed Brown 27979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &rootTypeCopy)); 27989566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(rootTypeCopy, rootType, pEndF - pStartF)); 279957168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_MAX)); 280057168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_MAX)); 28019566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_REPLACE)); 28029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_REPLACE)); 28030a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28040a96aa3bSJed 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 */ 28050a96aa3bSJed Brown roots[p - pStartF].rank = -1; 28060a96aa3bSJed Brown roots[p - pStartF].index = -1; 28070a96aa3bSJed Brown } 28089371c9d4SSatish 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 */ } 28090a96aa3bSJed Brown } 28109566063dSJacob Faibussowitsch PetscCall(PetscFree(rootTypeCopy)); 28119566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF, nodeType, roots, roots, sfNodeReduce)); 28129566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF, nodeType, roots, roots, sfNodeReduce)); 28139566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, nodeType, roots, roots, MPI_REPLACE)); 28149566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, nodeType, roots, roots, MPI_REPLACE)); 28150a96aa3bSJed Brown } 28169566063dSJacob Faibussowitsch PetscCall(PetscFree(rootType)); 28170a96aa3bSJed Brown 28180a96aa3bSJed Brown { 28190a96aa3bSJed Brown PetscInt numRoots; 28200a96aa3bSJed Brown PetscInt numLeaves; 28210a96aa3bSJed Brown PetscInt *leaves; 28220a96aa3bSJed Brown PetscSFNode *iremote; 28230a96aa3bSJed Brown /* count leaves */ 28240a96aa3bSJed Brown 28250a96aa3bSJed Brown numRoots = pEndC - pStartC; 28260a96aa3bSJed Brown 28270a96aa3bSJed Brown numLeaves = 0; 28280a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28290a96aa3bSJed Brown if (roots[p - pStartF].index >= 0) numLeaves++; 28300a96aa3bSJed Brown } 28319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &leaves)); 28329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &iremote)); 28330a96aa3bSJed Brown numLeaves = 0; 28340a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28350a96aa3bSJed Brown if (roots[p - pStartF].index >= 0) { 28360a96aa3bSJed Brown leaves[numLeaves] = p - pStartF; 28370a96aa3bSJed Brown iremote[numLeaves] = roots[p - pStartF]; 28380a96aa3bSJed Brown numLeaves++; 28390a96aa3bSJed Brown } 28400a96aa3bSJed Brown } 28419566063dSJacob Faibussowitsch PetscCall(PetscFree(roots)); 28429566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sf)); 28430a96aa3bSJed Brown if (numLeaves == (pEndF - pStartF)) { 28449566063dSJacob Faibussowitsch PetscCall(PetscFree(leaves)); 28459566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, numRoots, numLeaves, NULL, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 28460a96aa3bSJed Brown } else { 28479566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, numRoots, numLeaves, leaves, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 28480a96aa3bSJed Brown } 28490a96aa3bSJed Brown } 28500a96aa3bSJed Brown if (formCids) { 28510a96aa3bSJed Brown PetscSF pointSF; 28520a96aa3bSJed Brown PetscInt child; 28530a96aa3bSJed Brown 28549566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF, &refTree)); 28559566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plexF, &pointSF)); 285657168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, cids, cids, MPI_MAX)); 285757168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, cids, cids, MPI_MAX)); 28580a96aa3bSJed Brown if (childIds) *childIds = cids; 285948a46eb9SPierre Jolivet for (child = 0; child < P4EST_CHILDREN; child++) PetscCall(DMPlexRestoreTransitiveClosure(refTree, child + 1, PETSC_TRUE, NULL, &childClosures[child])); 28609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, 0, PETSC_TRUE, NULL, &rootClosure)); 28610a96aa3bSJed Brown } 28620a96aa3bSJed Brown } 28630a96aa3bSJed Brown if (saveInCoarse) { /* cache results */ 28649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 28650a96aa3bSJed Brown pforestC->pointSelfToAdaptSF = *sf; 28660a96aa3bSJed Brown if (!childIds) { 28670a96aa3bSJed Brown pforestC->pointSelfToAdaptCids = cids; 28680a96aa3bSJed Brown } else { 28699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &pforestC->pointSelfToAdaptCids)); 28709566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestC->pointSelfToAdaptCids, cids, pEndF - pStartF)); 28710a96aa3bSJed Brown } 28720a96aa3bSJed Brown } else if (saveInFine) { 28739566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 28740a96aa3bSJed Brown pforestF->pointAdaptToSelfSF = *sf; 28750a96aa3bSJed Brown if (!childIds) { 28760a96aa3bSJed Brown pforestF->pointAdaptToSelfCids = cids; 28770a96aa3bSJed Brown } else { 28789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &pforestF->pointAdaptToSelfCids)); 28799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestF->pointAdaptToSelfCids, cids, pEndF - pStartF)); 28800a96aa3bSJed Brown } 28810a96aa3bSJed Brown } 28829566063dSJacob Faibussowitsch PetscCall(PetscFree2(treeQuads, treeQuadCounts)); 28839566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuads)); 28849566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 28859566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsF)); 28869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeClosureType)); 28879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&sfNodeReduce)); 28889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 28893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28900a96aa3bSJed Brown } 28910a96aa3bSJed Brown 28920a96aa3bSJed Brown /* children are sf leaves of parents */ 2893d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetTransferSF_Internal(DM coarse, DM fine, const PetscInt dofPerDim[], PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 2894d71ae5a4SJacob Faibussowitsch { 28950a96aa3bSJed Brown MPI_Comm comm; 2896d70f29a3SPierre Jolivet PetscMPIInt rank; 28970a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 28980a96aa3bSJed Brown DM plexC, plexF; 28990a96aa3bSJed Brown PetscInt pStartC, pEndC, pStartF, pEndF; 29000a96aa3bSJed Brown PetscSF pointTransferSF; 29010a96aa3bSJed Brown PetscBool allOnes = PETSC_TRUE; 29020a96aa3bSJed Brown 29030a96aa3bSJed Brown PetscFunctionBegin; 29040a96aa3bSJed Brown pforestC = (DM_Forest_pforest *)((DM_Forest *)coarse->data)->data; 29050a96aa3bSJed Brown pforestF = (DM_Forest_pforest *)((DM_Forest *)fine->data)->data; 290608401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo, PetscObjectComm((PetscObject)coarse), PETSC_ERR_ARG_INCOMP, "DM's must have the same base DM"); 29070a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 29089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 29090a96aa3bSJed Brown 29100a96aa3bSJed Brown { 29110a96aa3bSJed Brown PetscInt i; 29120a96aa3bSJed Brown for (i = 0; i <= P4EST_DIM; i++) { 29130a96aa3bSJed Brown if (dofPerDim[i] != 1) { 29140a96aa3bSJed Brown allOnes = PETSC_FALSE; 29150a96aa3bSJed Brown break; 29160a96aa3bSJed Brown } 29170a96aa3bSJed Brown } 29180a96aa3bSJed Brown } 29199566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Point(coarse, fine, &pointTransferSF, transferIdent, childIds)); 29200a96aa3bSJed Brown if (allOnes) { 29210a96aa3bSJed Brown *sf = pointTransferSF; 29223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29230a96aa3bSJed Brown } 29240a96aa3bSJed Brown 29259566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine, &plexF)); 29269566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF, &pStartF, &pEndF)); 29279566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse, &plexC)); 29289566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC, &pStartC, &pEndC)); 29290a96aa3bSJed Brown { 29300a96aa3bSJed Brown PetscInt numRoots; 29310a96aa3bSJed Brown PetscInt numLeaves; 29320a96aa3bSJed Brown const PetscInt *leaves; 29330a96aa3bSJed Brown const PetscSFNode *iremote; 29340a96aa3bSJed Brown PetscInt d; 29350a96aa3bSJed Brown PetscSection leafSection, rootSection; 29360a96aa3bSJed Brown 2937217f96c1SStefano Zampini /* count leaves */ 29389566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointTransferSF, &numRoots, &numLeaves, &leaves, &iremote)); 29399566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &rootSection)); 29409566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &leafSection)); 29419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, pStartC, pEndC)); 29429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafSection, pStartF, pEndF)); 29430a96aa3bSJed Brown 29440a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 29450a96aa3bSJed Brown PetscInt startC, endC, e; 29460a96aa3bSJed Brown 29479566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC, P4EST_DIM - d, &startC, &endC)); 294848a46eb9SPierre Jolivet for (e = startC; e < endC; e++) PetscCall(PetscSectionSetDof(rootSection, e, dofPerDim[d])); 29490a96aa3bSJed Brown } 29500a96aa3bSJed Brown 29510a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 29520a96aa3bSJed Brown PetscInt startF, endF, e; 29530a96aa3bSJed Brown 29549566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexF, P4EST_DIM - d, &startF, &endF)); 295548a46eb9SPierre Jolivet for (e = startF; e < endF; e++) PetscCall(PetscSectionSetDof(leafSection, e, dofPerDim[d])); 29560a96aa3bSJed Brown } 29570a96aa3bSJed Brown 29589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 29599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSection)); 29600a96aa3bSJed Brown { 29610a96aa3bSJed Brown PetscInt nroots, nleaves; 29620a96aa3bSJed Brown PetscInt *mine, i, p; 29630a96aa3bSJed Brown PetscInt *offsets, *offsetsRoot; 29640a96aa3bSJed Brown PetscSFNode *remote; 29650a96aa3bSJed Brown 29669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &offsets)); 29679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &offsetsRoot)); 296848a46eb9SPierre Jolivet for (p = pStartC; p < pEndC; p++) PetscCall(PetscSectionGetOffset(rootSection, p, &offsetsRoot[p - pStartC])); 29699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointTransferSF, MPIU_INT, offsetsRoot, offsets, MPI_REPLACE)); 29709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointTransferSF, MPIU_INT, offsetsRoot, offsets, MPI_REPLACE)); 29719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &nroots)); 29720a96aa3bSJed Brown nleaves = 0; 29730a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 29740a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 29750a96aa3bSJed Brown PetscInt dof; 29760a96aa3bSJed Brown 29779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, leaf, &dof)); 29780a96aa3bSJed Brown nleaves += dof; 29790a96aa3bSJed Brown } 29809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &mine)); 29819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remote)); 29820a96aa3bSJed Brown nleaves = 0; 29830a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 29840a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 29850a96aa3bSJed Brown PetscInt dof; 29860a96aa3bSJed Brown PetscInt off, j; 29870a96aa3bSJed Brown 29889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, leaf, &dof)); 29899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection, leaf, &off)); 29900a96aa3bSJed Brown for (j = 0; j < dof; j++) { 29910a96aa3bSJed Brown remote[nleaves].rank = iremote[i].rank; 29920a96aa3bSJed Brown remote[nleaves].index = offsets[leaf] + j; 29930a96aa3bSJed Brown mine[nleaves++] = off + j; 29940a96aa3bSJed Brown } 29950a96aa3bSJed Brown } 29969566063dSJacob Faibussowitsch PetscCall(PetscFree(offsetsRoot)); 29979566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 29989566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sf)); 29999566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, nroots, nleaves, mine, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER)); 30000a96aa3bSJed Brown } 30019566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 30029566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 30039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointTransferSF)); 30040a96aa3bSJed Brown } 30053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30060a96aa3bSJed Brown } 30070a96aa3bSJed Brown 3008d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetTransferSF(DM dmA, DM dmB, const PetscInt dofPerDim[], PetscSF *sfAtoB, PetscSF *sfBtoA) 3009d71ae5a4SJacob Faibussowitsch { 30100a96aa3bSJed Brown DM adaptA, adaptB; 30110a96aa3bSJed Brown DMAdaptFlag purpose; 30120a96aa3bSJed Brown 30130a96aa3bSJed Brown PetscFunctionBegin; 30149566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmA, &adaptA)); 30159566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmB, &adaptB)); 30160a96aa3bSJed Brown /* it is more efficient when the coarser mesh is the first argument: reorder if we know one is coarser than the other */ 30170a96aa3bSJed Brown if (adaptA && adaptA->data == dmB->data) { /* dmA was adapted from dmB */ 30189566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmA, &purpose)); 30190a96aa3bSJed Brown if (purpose == DM_ADAPT_REFINE) { 30209566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 30213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30220a96aa3bSJed Brown } 30230a96aa3bSJed Brown } else if (adaptB && adaptB->data == dmA->data) { /* dmB was adapted from dmA */ 30249566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmB, &purpose)); 30250a96aa3bSJed Brown if (purpose == DM_ADAPT_COARSEN) { 30269566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 30273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30280a96aa3bSJed Brown } 30290a96aa3bSJed Brown } 30301baa6e33SBarry Smith if (sfAtoB) PetscCall(DMPforestGetTransferSF_Internal(dmA, dmB, dofPerDim, sfAtoB, PETSC_TRUE, NULL)); 30311baa6e33SBarry Smith if (sfBtoA) PetscCall(DMPforestGetTransferSF_Internal(dmB, dmA, dofPerDim, sfBtoA, (PetscBool)(sfAtoB == NULL), NULL)); 30323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30330a96aa3bSJed Brown } 30340a96aa3bSJed Brown 3035d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestLabelsInitialize(DM dm, DM plex) 3036d71ae5a4SJacob Faibussowitsch { 30370a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data; 30380a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data; 30390a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, cStart, cEnd, fStart, fEnd, eStart, eEnd, vStart, vEnd; 30400a96aa3bSJed Brown PetscInt cStartBase, cEndBase, fStartBase, fEndBase, vStartBase, vEndBase, eStartBase, eEndBase; 30410a96aa3bSJed Brown PetscInt pStart, pEnd, pStartBase, pEndBase, p; 30420a96aa3bSJed Brown DM base; 30430a96aa3bSJed Brown PetscInt *star = NULL, starSize; 30440a96aa3bSJed Brown DMLabelLink next = dm->labels; 30450a96aa3bSJed Brown PetscInt guess = 0; 30460a96aa3bSJed Brown p4est_topidx_t num_trees = pforest->topo->conn->num_trees; 30470a96aa3bSJed Brown 30480a96aa3bSJed Brown PetscFunctionBegin; 30490a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 30500a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 30510a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 30529566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 30530a96aa3bSJed Brown if (!base) { 30540a96aa3bSJed Brown if (pforest->ghostName) { /* insert a label to make the boundaries, with stratum values denoting which face of the element touches the boundary */ 30550a96aa3bSJed Brown p4est_connectivity_t *conn = pforest->topo->conn; 30560a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 30570a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t *)p4est->trees->array; 30580a96aa3bSJed Brown p4est_topidx_t t, flt = p4est->first_local_tree; 30590a96aa3bSJed Brown p4est_topidx_t llt = pforest->forest->last_local_tree; 30600a96aa3bSJed Brown DMLabel ghostLabel; 30610a96aa3bSJed Brown PetscInt c; 30620a96aa3bSJed Brown 30639566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(plex, pforest->ghostName)); 30649566063dSJacob Faibussowitsch PetscCall(DMGetLabel(plex, pforest->ghostName, &ghostLabel)); 30650a96aa3bSJed Brown for (c = cLocalStart, t = flt; t <= llt; t++) { 30660a96aa3bSJed Brown p4est_tree_t *tree = &trees[t]; 30670a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 30680a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 30690a96aa3bSJed Brown PetscInt q; 30700a96aa3bSJed Brown 30710a96aa3bSJed Brown for (q = 0; q < numQuads; q++, c++) { 30720a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[q]; 30730a96aa3bSJed Brown PetscInt f; 30740a96aa3bSJed Brown 30750a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++) { 30760a96aa3bSJed Brown p4est_quadrant_t neigh; 30770a96aa3bSJed Brown int isOutside; 30780a96aa3bSJed Brown 3079792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor, (quad, f, &neigh)); 3080792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p4est_quadrant_is_outside_face, (&neigh)); 30810a96aa3bSJed Brown if (isOutside) { 30820a96aa3bSJed Brown p4est_topidx_t nt; 30830a96aa3bSJed Brown PetscInt nf; 30840a96aa3bSJed Brown 30850a96aa3bSJed Brown nt = conn->tree_to_tree[t * P4EST_FACES + f]; 30860a96aa3bSJed Brown nf = (PetscInt)conn->tree_to_face[t * P4EST_FACES + f]; 30870a96aa3bSJed Brown nf = nf % P4EST_FACES; 30880a96aa3bSJed Brown if (nt == t && nf == f) { 30890a96aa3bSJed Brown PetscInt plexF = P4estFaceToPetscFace[f]; 30900a96aa3bSJed Brown const PetscInt *cone; 30910a96aa3bSJed Brown 30929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(plex, c, &cone)); 30939566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ghostLabel, cone[plexF], plexF + 1)); 30940a96aa3bSJed Brown } 30950a96aa3bSJed Brown } 30960a96aa3bSJed Brown } 30970a96aa3bSJed Brown } 30980a96aa3bSJed Brown } 30990a96aa3bSJed Brown } 31003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31010a96aa3bSJed Brown } 31029566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, 0, &cStartBase, &cEndBase)); 31039566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, 1, &fStartBase, &fEndBase)); 31049566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, P4EST_DIM - 1, &eStartBase, &eEndBase)); 31059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(base, 0, &vStartBase, &vEndBase)); 31060a96aa3bSJed Brown 31079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, 0, &cStart, &cEnd)); 31089566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, 1, &fStart, &fEnd)); 31099566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, P4EST_DIM - 1, &eStart, &eEnd)); 31109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd)); 31110a96aa3bSJed Brown 31129566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &pStart, &pEnd)); 31139566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(base, &pStartBase, &pEndBase)); 31140a96aa3bSJed Brown /* go through the mesh: use star to find a quadrant that borders a point. Use the closure to determine the 31150a96aa3bSJed Brown * orientation of the quadrant relative to that point. Use that to relate the point to the numbering in the base 31160a96aa3bSJed Brown * mesh, and extract a label value (since the base mesh is redundantly distributed, can be found locally). */ 31170a96aa3bSJed Brown while (next) { 31180a96aa3bSJed Brown DMLabel baseLabel; 31190a96aa3bSJed Brown DMLabel label = next->label; 31200a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK, isSpmap; 31210a96aa3bSJed Brown const char *name; 31220a96aa3bSJed Brown 31239566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name)); 31249566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 31250a96aa3bSJed Brown if (isDepth) { 31260a96aa3bSJed Brown next = next->next; 31270a96aa3bSJed Brown continue; 31280a96aa3bSJed Brown } 31299566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 31300a96aa3bSJed Brown if (isCellType) { 31310a96aa3bSJed Brown next = next->next; 31320a96aa3bSJed Brown continue; 31330a96aa3bSJed Brown } 31349566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 31350a96aa3bSJed Brown if (isGhost) { 31360a96aa3bSJed Brown next = next->next; 31370a96aa3bSJed Brown continue; 31380a96aa3bSJed Brown } 31399566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 31400a96aa3bSJed Brown if (isVTK) { 31410a96aa3bSJed Brown next = next->next; 31420a96aa3bSJed Brown continue; 31430a96aa3bSJed Brown } 31449566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "_forest_base_subpoint_map", &isSpmap)); 31450a96aa3bSJed Brown if (!isSpmap) { 31469566063dSJacob Faibussowitsch PetscCall(DMGetLabel(base, name, &baseLabel)); 31470a96aa3bSJed Brown if (!baseLabel) { 31480a96aa3bSJed Brown next = next->next; 31490a96aa3bSJed Brown continue; 31500a96aa3bSJed Brown } 31519566063dSJacob Faibussowitsch PetscCall(DMLabelCreateIndex(baseLabel, pStartBase, pEndBase)); 31520a96aa3bSJed Brown } else baseLabel = NULL; 31530a96aa3bSJed Brown 31540a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 31550a96aa3bSJed Brown PetscInt s, c = -1, l; 31560a96aa3bSJed Brown PetscInt *closure = NULL, closureSize; 31570a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 31580a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t *)pforest->forest->trees->array; 31590a96aa3bSJed Brown p4est_quadrant_t *q; 31600a96aa3bSJed Brown PetscInt t, val; 31610a96aa3bSJed Brown PetscBool zerosupportpoint = PETSC_FALSE; 31620a96aa3bSJed Brown 31639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star)); 31640a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 31650a96aa3bSJed Brown PetscInt point = star[2 * s]; 31660a96aa3bSJed Brown 31670a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 31689566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, point, PETSC_TRUE, &closureSize, &closure)); 31690a96aa3bSJed Brown for (l = 0; l < closureSize; l++) { 31700a96aa3bSJed Brown PetscInt qParent = closure[2 * l], q, pp = p, pParent = p; 31710a96aa3bSJed Brown do { /* check parents of q */ 31720a96aa3bSJed Brown q = qParent; 31730a96aa3bSJed Brown if (q == p) { 31740a96aa3bSJed Brown c = point; 31750a96aa3bSJed Brown break; 31760a96aa3bSJed Brown } 31779566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &qParent, NULL)); 31780a96aa3bSJed Brown } while (qParent != q); 31790a96aa3bSJed Brown if (c != -1) break; 31809566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, pp, &pParent, NULL)); 31810a96aa3bSJed Brown q = closure[2 * l]; 31820a96aa3bSJed Brown while (pParent != pp) { /* check parents of p */ 31830a96aa3bSJed Brown pp = pParent; 31840a96aa3bSJed Brown if (pp == q) { 31850a96aa3bSJed Brown c = point; 31860a96aa3bSJed Brown break; 31870a96aa3bSJed Brown } 31889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, pp, &pParent, NULL)); 31890a96aa3bSJed Brown } 31900a96aa3bSJed Brown if (c != -1) break; 31910a96aa3bSJed Brown } 31929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, point, PETSC_TRUE, NULL, &closure)); 31930a96aa3bSJed Brown if (l < closureSize) break; 31940a96aa3bSJed Brown } else { 31950a96aa3bSJed Brown PetscInt supportSize; 31960a96aa3bSJed Brown 31979566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(plex, point, &supportSize)); 31980a96aa3bSJed Brown zerosupportpoint = (PetscBool)(zerosupportpoint || !supportSize); 31990a96aa3bSJed Brown } 32000a96aa3bSJed Brown } 32010a96aa3bSJed Brown if (c < 0) { 32020a96aa3bSJed Brown const char *prefix; 32030a96aa3bSJed Brown PetscBool print = PETSC_FALSE; 32040a96aa3bSJed Brown 32059566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 32069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, prefix, "-dm_forest_print_label_error", &print, NULL)); 32070a96aa3bSJed Brown if (print) { 32080a96aa3bSJed Brown PetscInt i; 32090a96aa3bSJed Brown 321063a3b9bcSJacob 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)); 321163a3b9bcSJacob 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])); 32120a96aa3bSJed Brown } 32139566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, NULL, &star)); 32140a96aa3bSJed Brown if (zerosupportpoint) continue; 32159371c9d4SSatish Balay else 32169371c9d4SSatish 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"); 32170a96aa3bSJed Brown } 32189566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, NULL, &star)); 32190a96aa3bSJed Brown 32200a96aa3bSJed Brown if (c < cLocalStart) { 32210a96aa3bSJed Brown /* get from the beginning of the ghost layer */ 3222f4f49eeaSPierre Jolivet q = &ghosts[c]; 32230a96aa3bSJed Brown t = (PetscInt)q->p.which_tree; 32240a96aa3bSJed Brown } else if (c < cLocalEnd) { 32250a96aa3bSJed Brown PetscInt lo = 0, hi = num_trees; 32260a96aa3bSJed Brown /* get from local quadrants: have to find the right tree */ 32270a96aa3bSJed Brown 32280a96aa3bSJed Brown c -= cLocalStart; 32290a96aa3bSJed Brown 32300a96aa3bSJed Brown do { 32310a96aa3bSJed Brown p4est_tree_t *tree; 32320a96aa3bSJed Brown 32331dca8a05SBarry Smith PetscCheck(guess >= lo && guess < num_trees && lo < hi, PETSC_COMM_SELF, PETSC_ERR_PLIB, "failed binary search"); 32340a96aa3bSJed Brown tree = &trees[guess]; 32350a96aa3bSJed Brown if (c < tree->quadrants_offset) { 32360a96aa3bSJed Brown hi = guess; 32370a96aa3bSJed Brown } else if (c < tree->quadrants_offset + (PetscInt)tree->quadrants.elem_count) { 32380a96aa3bSJed Brown q = &((p4est_quadrant_t *)tree->quadrants.array)[c - (PetscInt)tree->quadrants_offset]; 32390a96aa3bSJed Brown t = guess; 32400a96aa3bSJed Brown break; 32410a96aa3bSJed Brown } else { 32420a96aa3bSJed Brown lo = guess + 1; 32430a96aa3bSJed Brown } 32440a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 32450a96aa3bSJed Brown } while (1); 32460a96aa3bSJed Brown } else { 32470a96aa3bSJed Brown /* get from the end of the ghost layer */ 32480a96aa3bSJed Brown c -= (cLocalEnd - cLocalStart); 32490a96aa3bSJed Brown 3250f4f49eeaSPierre Jolivet q = &ghosts[c]; 32510a96aa3bSJed Brown t = (PetscInt)q->p.which_tree; 32520a96aa3bSJed Brown } 32530a96aa3bSJed Brown 32540a96aa3bSJed Brown if (l == 0) { /* cell */ 32550a96aa3bSJed Brown if (baseLabel) { 32569566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 32570a96aa3bSJed Brown } else { 32580a96aa3bSJed Brown val = t + cStartBase; 32590a96aa3bSJed Brown } 32609566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32610a96aa3bSJed Brown } else if (l >= 1 && l < 1 + P4EST_FACES) { /* facet */ 32620a96aa3bSJed Brown p4est_quadrant_t nq; 32630a96aa3bSJed Brown int isInside; 32640a96aa3bSJed Brown 32650a96aa3bSJed Brown l = PetscFaceToP4estFace[l - 1]; 3266792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor, (q, l, &nq)); 3267792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq)); 32680a96aa3bSJed Brown if (isInside) { 32690a96aa3bSJed Brown /* this facet is in the interior of a tree, so it inherits the label of the tree */ 32700a96aa3bSJed Brown if (baseLabel) { 32719566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 32720a96aa3bSJed Brown } else { 32730a96aa3bSJed Brown val = t + cStartBase; 32740a96aa3bSJed Brown } 32759566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32760a96aa3bSJed Brown } else { 32770a96aa3bSJed Brown PetscInt f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + l]; 32780a96aa3bSJed Brown 32790a96aa3bSJed Brown if (baseLabel) { 32809566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val)); 32810a96aa3bSJed Brown } else { 32820a96aa3bSJed Brown val = f + fStartBase; 32830a96aa3bSJed Brown } 32849566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 32850a96aa3bSJed Brown } 32860a96aa3bSJed Brown #if defined(P4_TO_P8) 32870a96aa3bSJed Brown } else if (l >= 1 + P4EST_FACES && l < 1 + P4EST_FACES + P8EST_EDGES) { /* edge */ 32880a96aa3bSJed Brown p4est_quadrant_t nq; 32890a96aa3bSJed Brown int isInside; 32900a96aa3bSJed Brown 32910a96aa3bSJed Brown l = PetscEdgeToP4estEdge[l - (1 + P4EST_FACES)]; 3292792fecdfSBarry Smith PetscCallP4est(p8est_quadrant_edge_neighbor, (q, l, &nq)); 3293792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq)); 32940a96aa3bSJed Brown if (isInside) { 32950a96aa3bSJed Brown /* this edge is in the interior of a tree, so it inherits the label of the tree */ 32960a96aa3bSJed Brown if (baseLabel) { 32979566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 32980a96aa3bSJed Brown } else { 32990a96aa3bSJed Brown val = t + cStartBase; 33000a96aa3bSJed Brown } 33019566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33020a96aa3bSJed Brown } else { 33030a96aa3bSJed Brown int isOutsideFace; 33040a96aa3bSJed Brown 3305792fecdfSBarry Smith PetscCallP4estReturn(isOutsideFace, p4est_quadrant_is_outside_face, (&nq)); 33060a96aa3bSJed Brown if (isOutsideFace) { 33070a96aa3bSJed Brown PetscInt f; 33080a96aa3bSJed Brown 33090a96aa3bSJed Brown if (nq.x < 0) { 33100a96aa3bSJed Brown f = 0; 33110a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 33120a96aa3bSJed Brown f = 1; 33130a96aa3bSJed Brown } else if (nq.y < 0) { 33140a96aa3bSJed Brown f = 2; 33150a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 33160a96aa3bSJed Brown f = 3; 33170a96aa3bSJed Brown } else if (nq.z < 0) { 33180a96aa3bSJed Brown f = 4; 33190a96aa3bSJed Brown } else { 33200a96aa3bSJed Brown f = 5; 33210a96aa3bSJed Brown } 33220a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 33230a96aa3bSJed Brown if (baseLabel) { 33249566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val)); 33250a96aa3bSJed Brown } else { 33260a96aa3bSJed Brown val = f + fStartBase; 33270a96aa3bSJed Brown } 33289566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33290a96aa3bSJed Brown } else { /* the quadrant edge corresponds to the tree edge */ 33300a96aa3bSJed Brown PetscInt e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + l]; 33310a96aa3bSJed Brown 33320a96aa3bSJed Brown if (baseLabel) { 33339566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, e + eStartBase, &val)); 33340a96aa3bSJed Brown } else { 33350a96aa3bSJed Brown val = e + eStartBase; 33360a96aa3bSJed Brown } 33379566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33380a96aa3bSJed Brown } 33390a96aa3bSJed Brown } 33400a96aa3bSJed Brown #endif 33410a96aa3bSJed Brown } else { /* vertex */ 33420a96aa3bSJed Brown p4est_quadrant_t nq; 33430a96aa3bSJed Brown int isInside; 33440a96aa3bSJed Brown 33450a96aa3bSJed Brown #if defined(P4_TO_P8) 33460a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES + P8EST_EDGES)]; 33470a96aa3bSJed Brown #else 33480a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES)]; 33490a96aa3bSJed Brown #endif 3350792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_neighbor, (q, l, &nq)); 3351792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq)); 33520a96aa3bSJed Brown if (isInside) { 33530a96aa3bSJed Brown if (baseLabel) { 33549566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val)); 33550a96aa3bSJed Brown } else { 33560a96aa3bSJed Brown val = t + cStartBase; 33570a96aa3bSJed Brown } 33589566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33590a96aa3bSJed Brown } else { 33600a96aa3bSJed Brown int isOutside; 33610a96aa3bSJed Brown 3362792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p4est_quadrant_is_outside_face, (&nq)); 33630a96aa3bSJed Brown if (isOutside) { 33640a96aa3bSJed Brown PetscInt f = -1; 33650a96aa3bSJed Brown 33660a96aa3bSJed Brown if (nq.x < 0) { 33670a96aa3bSJed Brown f = 0; 33680a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 33690a96aa3bSJed Brown f = 1; 33700a96aa3bSJed Brown } else if (nq.y < 0) { 33710a96aa3bSJed Brown f = 2; 33720a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 33730a96aa3bSJed Brown f = 3; 33740a96aa3bSJed Brown #if defined(P4_TO_P8) 33750a96aa3bSJed Brown } else if (nq.z < 0) { 33760a96aa3bSJed Brown f = 4; 33770a96aa3bSJed Brown } else { 33780a96aa3bSJed Brown f = 5; 33790a96aa3bSJed Brown #endif 33800a96aa3bSJed Brown } 33810a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 33820a96aa3bSJed Brown if (baseLabel) { 33839566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val)); 33840a96aa3bSJed Brown } else { 33850a96aa3bSJed Brown val = f + fStartBase; 33860a96aa3bSJed Brown } 33879566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 33880a96aa3bSJed Brown continue; 33890a96aa3bSJed Brown } 33900a96aa3bSJed Brown #if defined(P4_TO_P8) 3391792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p8est_quadrant_is_outside_edge, (&nq)); 33920a96aa3bSJed Brown if (isOutside) { 33930a96aa3bSJed Brown /* outside edge */ 33940a96aa3bSJed Brown PetscInt e = -1; 33950a96aa3bSJed Brown 33960a96aa3bSJed Brown if (nq.x >= 0 && nq.x < P4EST_ROOT_LEN) { 33970a96aa3bSJed Brown if (nq.z < 0) { 33980a96aa3bSJed Brown if (nq.y < 0) { 33990a96aa3bSJed Brown e = 0; 34000a96aa3bSJed Brown } else { 34010a96aa3bSJed Brown e = 1; 34020a96aa3bSJed Brown } 34030a96aa3bSJed Brown } else { 34040a96aa3bSJed Brown if (nq.y < 0) { 34050a96aa3bSJed Brown e = 2; 34060a96aa3bSJed Brown } else { 34070a96aa3bSJed Brown e = 3; 34080a96aa3bSJed Brown } 34090a96aa3bSJed Brown } 34100a96aa3bSJed Brown } else if (nq.y >= 0 && nq.y < P4EST_ROOT_LEN) { 34110a96aa3bSJed Brown if (nq.z < 0) { 34120a96aa3bSJed Brown if (nq.x < 0) { 34130a96aa3bSJed Brown e = 4; 34140a96aa3bSJed Brown } else { 34150a96aa3bSJed Brown e = 5; 34160a96aa3bSJed Brown } 34170a96aa3bSJed Brown } else { 34180a96aa3bSJed Brown if (nq.x < 0) { 34190a96aa3bSJed Brown e = 6; 34200a96aa3bSJed Brown } else { 34210a96aa3bSJed Brown e = 7; 34220a96aa3bSJed Brown } 34230a96aa3bSJed Brown } 34240a96aa3bSJed Brown } else { 34250a96aa3bSJed Brown if (nq.y < 0) { 34260a96aa3bSJed Brown if (nq.x < 0) { 34270a96aa3bSJed Brown e = 8; 34280a96aa3bSJed Brown } else { 34290a96aa3bSJed Brown e = 9; 34300a96aa3bSJed Brown } 34310a96aa3bSJed Brown } else { 34320a96aa3bSJed Brown if (nq.x < 0) { 34330a96aa3bSJed Brown e = 10; 34340a96aa3bSJed Brown } else { 34350a96aa3bSJed Brown e = 11; 34360a96aa3bSJed Brown } 34370a96aa3bSJed Brown } 34380a96aa3bSJed Brown } 34390a96aa3bSJed Brown 34400a96aa3bSJed Brown e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + e]; 34410a96aa3bSJed Brown if (baseLabel) { 34429566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, e + eStartBase, &val)); 34430a96aa3bSJed Brown } else { 34440a96aa3bSJed Brown val = e + eStartBase; 34450a96aa3bSJed Brown } 34469566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 34470a96aa3bSJed Brown continue; 34480a96aa3bSJed Brown } 34490a96aa3bSJed Brown #endif 34500a96aa3bSJed Brown { 34510a96aa3bSJed Brown /* outside vertex: same corner as quadrant corner */ 34520a96aa3bSJed Brown PetscInt v = pforest->topo->conn->tree_to_corner[P4EST_CHILDREN * t + l]; 34530a96aa3bSJed Brown 34540a96aa3bSJed Brown if (baseLabel) { 34559566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, v + vStartBase, &val)); 34560a96aa3bSJed Brown } else { 34570a96aa3bSJed Brown val = v + vStartBase; 34580a96aa3bSJed Brown } 34599566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val)); 34600a96aa3bSJed Brown } 34610a96aa3bSJed Brown } 34620a96aa3bSJed Brown } 34630a96aa3bSJed Brown } 34640a96aa3bSJed Brown next = next->next; 34650a96aa3bSJed Brown } 34663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34670a96aa3bSJed Brown } 34680a96aa3bSJed Brown 3469d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestLabelsFinalize(DM dm, DM plex) 3470d71ae5a4SJacob Faibussowitsch { 34710a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 34720a96aa3bSJed Brown DM adapt; 34730a96aa3bSJed Brown 34740a96aa3bSJed Brown PetscFunctionBegin; 34753ba16761SJacob Faibussowitsch if (pforest->labelsFinalized) PetscFunctionReturn(PETSC_SUCCESS); 34760a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 34779566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm, &adapt)); 34780a96aa3bSJed Brown if (!adapt) { 34790a96aa3bSJed Brown /* Initialize labels from the base dm */ 34809566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsInitialize(dm, plex)); 34810a96aa3bSJed Brown } else { 34820a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1}; 34830a96aa3bSJed Brown PetscSF transferForward, transferBackward, pointSF; 34840a96aa3bSJed Brown PetscInt pStart, pEnd, pStartA, pEndA; 34850a96aa3bSJed Brown PetscInt *values, *adaptValues; 34860a96aa3bSJed Brown DMLabelLink next = adapt->labels; 34870a96aa3bSJed Brown DMLabel adaptLabel; 34880a96aa3bSJed Brown DM adaptPlex; 34890a96aa3bSJed Brown 34909566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm, &adaptLabel)); 34919566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(adapt, &adaptPlex)); 34929566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(adapt, dm, dofPerDim, &transferForward, &transferBackward)); 34939566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &pStart, &pEnd)); 34949566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(adaptPlex, &pStartA, &pEndA)); 34959566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &values, pEndA - pStartA, &adaptValues)); 34969566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plex, &pointSF)); 34970a96aa3bSJed Brown if (PetscDefined(USE_DEBUG)) { 34980a96aa3bSJed Brown PetscInt p; 34990a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) adaptValues[p - pStartA] = -1; 35000a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p - pStart] = -2; 35010a96aa3bSJed Brown if (transferForward) { 35029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 35039566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 35040a96aa3bSJed Brown } 35050a96aa3bSJed Brown if (transferBackward) { 350657168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 350757168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 35080a96aa3bSJed Brown } 35090a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 35100a96aa3bSJed Brown PetscInt q = p, parent; 35110a96aa3bSJed Brown 35129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35130a96aa3bSJed Brown while (parent != q) { 35140a96aa3bSJed Brown if (values[parent] == -2) values[parent] = values[q]; 35150a96aa3bSJed Brown q = parent; 35169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35170a96aa3bSJed Brown } 35180a96aa3bSJed Brown } 351957168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, values, values, MPI_MAX)); 352057168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, values, values, MPI_MAX)); 35219566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 35229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 3523ad540459SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCheck(values[p - pStart] != -2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "uncovered point %" PetscInt_FMT, p); 35240a96aa3bSJed Brown } 35250a96aa3bSJed Brown while (next) { 35260a96aa3bSJed Brown DMLabel nextLabel = next->label; 35270a96aa3bSJed Brown const char *name; 35280a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 35290a96aa3bSJed Brown DMLabel label; 35300a96aa3bSJed Brown PetscInt p; 35310a96aa3bSJed Brown 35329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)nextLabel, &name)); 35339566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth)); 35340a96aa3bSJed Brown if (isDepth) { 35350a96aa3bSJed Brown next = next->next; 35360a96aa3bSJed Brown continue; 35370a96aa3bSJed Brown } 35389566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType)); 35390a96aa3bSJed Brown if (isCellType) { 35400a96aa3bSJed Brown next = next->next; 35410a96aa3bSJed Brown continue; 35420a96aa3bSJed Brown } 35439566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost)); 35440a96aa3bSJed Brown if (isGhost) { 35450a96aa3bSJed Brown next = next->next; 35460a96aa3bSJed Brown continue; 35470a96aa3bSJed Brown } 35489566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK)); 35490a96aa3bSJed Brown if (isVTK) { 35500a96aa3bSJed Brown next = next->next; 35510a96aa3bSJed Brown continue; 35520a96aa3bSJed Brown } 35530a96aa3bSJed Brown if (nextLabel == adaptLabel) { 35540a96aa3bSJed Brown next = next->next; 35550a96aa3bSJed Brown continue; 35560a96aa3bSJed Brown } 35570a96aa3bSJed Brown /* label was created earlier */ 35589566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 355948a46eb9SPierre Jolivet for (p = pStartA; p < pEndA; p++) PetscCall(DMLabelGetValue(nextLabel, p, &adaptValues[p])); 35600a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p] = PETSC_MIN_INT; 35610a96aa3bSJed Brown 35621baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastBegin(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 356357168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceBegin(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 35641baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastEnd(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE)); 356557168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceEnd(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX)); 35660a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 35670a96aa3bSJed Brown PetscInt q = p, parent; 35680a96aa3bSJed Brown 35699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35700a96aa3bSJed Brown while (parent != q) { 35710a96aa3bSJed Brown if (values[parent] == PETSC_MIN_INT) values[parent] = values[q]; 35720a96aa3bSJed Brown q = parent; 35739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL)); 35740a96aa3bSJed Brown } 35750a96aa3bSJed Brown } 357657168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, values, values, MPI_MAX)); 357757168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, values, values, MPI_MAX)); 35789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 35799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, values, values, MPI_REPLACE)); 35800a96aa3bSJed Brown 358148a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMLabelSetValue(label, p, values[p])); 35820a96aa3bSJed Brown next = next->next; 35830a96aa3bSJed Brown } 35849566063dSJacob Faibussowitsch PetscCall(PetscFree2(values, adaptValues)); 35859566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferForward)); 35869566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferBackward)); 35870a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 35880a96aa3bSJed Brown } 35893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35900a96aa3bSJed Brown } 35910a96aa3bSJed Brown 3592d71ae5a4SJacob 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) 3593d71ae5a4SJacob Faibussowitsch { 35940a96aa3bSJed Brown PetscInt closureSize, c, coordStart, coordEnd, coordDim; 35950a96aa3bSJed Brown PetscInt *closure = NULL; 35960a96aa3bSJed Brown PetscSection coordSec; 35970a96aa3bSJed Brown 35980a96aa3bSJed Brown PetscFunctionBegin; 35999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &coordSec)); 36009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec, &coordStart, &coordEnd)); 36019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex, &coordDim)); 36029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, cell, PETSC_TRUE, &closureSize, &closure)); 36030a96aa3bSJed Brown for (c = 0; c < closureSize; c++) { 36040a96aa3bSJed Brown PetscInt point = closure[2 * c]; 36050a96aa3bSJed Brown 36060a96aa3bSJed Brown if (point >= coordStart && point < coordEnd) { 36070a96aa3bSJed Brown PetscInt dof, off; 36080a96aa3bSJed Brown PetscInt nCoords, i; 36099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec, point, &dof)); 361008401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Did not understand coordinate layout"); 36110a96aa3bSJed Brown nCoords = dof / coordDim; 36129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec, point, &off)); 36130a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 36140a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 36150a96aa3bSJed Brown double coordP4est[3] = {0.}; 36160a96aa3bSJed Brown double coordP4estMapped[3] = {0.}; 36170a96aa3bSJed Brown PetscInt j; 36180a96aa3bSJed Brown PetscReal treeCoords[P4EST_CHILDREN][3] = {{0.}}; 36190a96aa3bSJed Brown PetscReal eta[3] = {0.}; 36200a96aa3bSJed Brown PetscInt numRounds = 10; 36210a96aa3bSJed Brown PetscReal coordGuess[3] = {0.}; 36220a96aa3bSJed Brown 36230a96aa3bSJed Brown eta[0] = (PetscReal)q->x / (PetscReal)P4EST_ROOT_LEN; 36240a96aa3bSJed Brown eta[1] = (PetscReal)q->y / (PetscReal)P4EST_ROOT_LEN; 36250a96aa3bSJed Brown #if defined(P4_TO_P8) 36260a96aa3bSJed Brown eta[2] = (PetscReal)q->z / (PetscReal)P4EST_ROOT_LEN; 36270a96aa3bSJed Brown #endif 36280a96aa3bSJed Brown 36290a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 36300a96aa3bSJed Brown PetscInt k; 36310a96aa3bSJed Brown 36320a96aa3bSJed Brown for (k = 0; k < 3; k++) treeCoords[j][k] = conn->vertices[3 * conn->tree_to_vertex[P4EST_CHILDREN * t + j] + k]; 36330a96aa3bSJed Brown } 36340a96aa3bSJed Brown 36350a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 36360a96aa3bSJed Brown PetscInt k; 36370a96aa3bSJed Brown PetscReal prod = 1.; 36380a96aa3bSJed Brown 36390a96aa3bSJed Brown for (k = 0; k < P4EST_DIM; k++) prod *= (j & (1 << k)) ? eta[k] : (1. - eta[k]); 36400a96aa3bSJed Brown for (k = 0; k < 3; k++) coordGuess[k] += prod * treeCoords[j][k]; 36410a96aa3bSJed Brown } 36420a96aa3bSJed Brown 36430a96aa3bSJed Brown for (j = 0; j < numRounds; j++) { 36440a96aa3bSJed Brown PetscInt dir; 36450a96aa3bSJed Brown 36460a96aa3bSJed Brown for (dir = 0; dir < P4EST_DIM; dir++) { 36470a96aa3bSJed Brown PetscInt k; 36480a96aa3bSJed Brown PetscReal diff[3]; 36490a96aa3bSJed Brown PetscReal dXdeta[3] = {0.}; 36500a96aa3bSJed Brown PetscReal rhs, scale, update; 36510a96aa3bSJed Brown 36520a96aa3bSJed Brown for (k = 0; k < 3; k++) diff[k] = coordP4est[k] - coordGuess[k]; 36530a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 36540a96aa3bSJed Brown PetscInt l; 36550a96aa3bSJed Brown PetscReal prod = 1.; 36560a96aa3bSJed Brown 36570a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) { 36580a96aa3bSJed Brown if (l == dir) { 36590a96aa3bSJed Brown prod *= (k & (1 << l)) ? 1. : -1.; 36600a96aa3bSJed Brown } else { 36610a96aa3bSJed Brown prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 36620a96aa3bSJed Brown } 36630a96aa3bSJed Brown } 36640a96aa3bSJed Brown for (l = 0; l < 3; l++) dXdeta[l] += prod * treeCoords[k][l]; 36650a96aa3bSJed Brown } 36660a96aa3bSJed Brown rhs = 0.; 36670a96aa3bSJed Brown scale = 0; 36680a96aa3bSJed Brown for (k = 0; k < 3; k++) { 36690a96aa3bSJed Brown rhs += diff[k] * dXdeta[k]; 36700a96aa3bSJed Brown scale += dXdeta[k] * dXdeta[k]; 36710a96aa3bSJed Brown } 36720a96aa3bSJed Brown update = rhs / scale; 36730a96aa3bSJed Brown eta[dir] += update; 36740a96aa3bSJed Brown eta[dir] = PetscMin(eta[dir], 1.); 36750a96aa3bSJed Brown eta[dir] = PetscMax(eta[dir], 0.); 36760a96aa3bSJed Brown 36770a96aa3bSJed Brown coordGuess[0] = coordGuess[1] = coordGuess[2] = 0.; 36780a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 36790a96aa3bSJed Brown PetscInt l; 36800a96aa3bSJed Brown PetscReal prod = 1.; 36810a96aa3bSJed Brown 36820a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 36830a96aa3bSJed Brown for (l = 0; l < 3; l++) coordGuess[l] += prod * treeCoords[k][l]; 36840a96aa3bSJed Brown } 36850a96aa3bSJed Brown } 36860a96aa3bSJed Brown } 36870a96aa3bSJed Brown for (j = 0; j < 3; j++) coordP4est[j] = (double)eta[j]; 36880a96aa3bSJed Brown 36890a96aa3bSJed Brown if (geom) { 36900a96aa3bSJed Brown (geom->X)(geom, t, coordP4est, coordP4estMapped); 36910a96aa3bSJed Brown for (j = 0; j < coordDim; j++) coord[j] = (PetscScalar)coordP4estMapped[j]; 36920a96aa3bSJed Brown } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded"); 36930a96aa3bSJed Brown } 36940a96aa3bSJed Brown } 36950a96aa3bSJed Brown } 36969566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, cell, PETSC_TRUE, &closureSize, &closure)); 36973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36980a96aa3bSJed Brown } 36990a96aa3bSJed Brown 3700d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestMapCoordinates(DM dm, DM plex) 3701d71ae5a4SJacob Faibussowitsch { 37020a96aa3bSJed Brown DM_Forest *forest; 37030a96aa3bSJed Brown DM_Forest_pforest *pforest; 37040a96aa3bSJed Brown p4est_geometry_t *geom; 37050a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd; 37060a96aa3bSJed Brown Vec coordLocalVec; 37070a96aa3bSJed Brown PetscScalar *coords; 37080a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 37090a96aa3bSJed Brown p4est_tree_t *trees; 37100a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *); 37110a96aa3bSJed Brown void *mapCtx; 37120a96aa3bSJed Brown 37130a96aa3bSJed Brown PetscFunctionBegin; 37140a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 37150a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 37160a96aa3bSJed Brown geom = pforest->topo->geom; 37179566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx)); 37183ba16761SJacob Faibussowitsch if (!geom && !map) PetscFunctionReturn(PETSC_SUCCESS); 37199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(plex, &coordLocalVec)); 37209566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordLocalVec, &coords)); 37210a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 37220a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 37230a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 37240a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 37250a96aa3bSJed Brown trees = (p4est_tree_t *)pforest->forest->trees->array; 37260a96aa3bSJed Brown if (map) { /* apply the map directly to the existing coordinates */ 37270a96aa3bSJed Brown PetscSection coordSec; 37280a96aa3bSJed Brown PetscInt coordStart, coordEnd, p, coordDim, p4estCoordDim, cStart, cEnd, cEndInterior; 37290a96aa3bSJed Brown DM base; 37300a96aa3bSJed Brown 37319566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 37322827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(plex, DM_POLYTOPE_FV_GHOST, &cEndInterior, NULL)); 37330a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 37349566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 37359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &coordSec)); 37369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec, &coordStart, &coordEnd)); 37379566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex, &coordDim)); 37380a96aa3bSJed Brown p4estCoordDim = PetscMin(coordDim, 3); 37390a96aa3bSJed Brown for (p = coordStart; p < coordEnd; p++) { 37400a96aa3bSJed Brown PetscInt *star = NULL, starSize; 37410a96aa3bSJed Brown PetscInt dof, off, cell = -1, coarsePoint = -1; 37420a96aa3bSJed Brown PetscInt nCoords, i; 37439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec, p, &dof)); 374408401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Did not understand coordinate layout"); 37450a96aa3bSJed Brown nCoords = dof / coordDim; 37469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec, p, &off)); 37479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star)); 37480a96aa3bSJed Brown for (i = 0; i < starSize; i++) { 37490a96aa3bSJed Brown PetscInt point = star[2 * i]; 37500a96aa3bSJed Brown 37510a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 37520a96aa3bSJed Brown cell = point; 37530a96aa3bSJed Brown break; 37540a96aa3bSJed Brown } 37550a96aa3bSJed Brown } 37569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star)); 37570a96aa3bSJed Brown if (cell >= 0) { 37580a96aa3bSJed Brown if (cell < cLocalStart) { 37590a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37600a96aa3bSJed Brown 37610a96aa3bSJed Brown coarsePoint = ghosts[cell].p.which_tree; 37620a96aa3bSJed Brown } else if (cell < cLocalEnd) { 37630a96aa3bSJed Brown cell -= cLocalStart; 37640a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 3765f4f49eeaSPierre Jolivet p4est_tree_t *tree = &trees[t]; 37660a96aa3bSJed Brown 37670a96aa3bSJed Brown if (cell >= tree->quadrants_offset && (size_t)cell < tree->quadrants_offset + tree->quadrants.elem_count) { 37680a96aa3bSJed Brown coarsePoint = t; 37690a96aa3bSJed Brown break; 37700a96aa3bSJed Brown } 37710a96aa3bSJed Brown } 37720a96aa3bSJed Brown } else { 37730a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37740a96aa3bSJed Brown 37750a96aa3bSJed Brown coarsePoint = ghosts[cell - cLocalEnd].p.which_tree; 37760a96aa3bSJed Brown } 37770a96aa3bSJed Brown } 37780a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 37790a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 37800a96aa3bSJed Brown PetscReal coordP4est[3] = {0.}; 37810a96aa3bSJed Brown PetscReal coordP4estMapped[3] = {0.}; 37820a96aa3bSJed Brown PetscInt j; 37830a96aa3bSJed Brown 37840a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coordP4est[j] = PetscRealPart(coord[j]); 37859566063dSJacob Faibussowitsch PetscCall((map)(base, coarsePoint, p4estCoordDim, coordP4est, coordP4estMapped, mapCtx)); 37860a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coord[j] = (PetscScalar)coordP4estMapped[j]; 37870a96aa3bSJed Brown } 37880a96aa3bSJed Brown } 37890a96aa3bSJed Brown } else { /* we have to transform coordinates back to the unit cube (where geom is defined), and then apply geom */ 37900a96aa3bSJed Brown PetscInt cStart, cEnd, cEndInterior; 37910a96aa3bSJed Brown 37929566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 37932827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(plex, DM_POLYTOPE_FV_GHOST, &cEndInterior, NULL)); 37940a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 37950a96aa3bSJed Brown if (cLocalStart > 0) { 37960a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 37970a96aa3bSJed Brown PetscInt count; 37980a96aa3bSJed Brown 37990a96aa3bSJed Brown for (count = 0; count < cLocalStart; count++) { 38000a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count]; 38010a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 38020a96aa3bSJed Brown 38039566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count, quad, t, pforest->topo->conn, coords)); 38040a96aa3bSJed Brown } 38050a96aa3bSJed Brown } 38060a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 3807f4f49eeaSPierre Jolivet p4est_tree_t *tree = &trees[t]; 38080a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset, i; 38090a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 38100a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 38110a96aa3bSJed Brown 38120a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 38130a96aa3bSJed Brown PetscInt count = i + offset; 38140a96aa3bSJed Brown 38159566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count, &quads[i], t, pforest->topo->conn, coords)); 38160a96aa3bSJed Brown } 38170a96aa3bSJed Brown } 38180a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 38190a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 38200a96aa3bSJed Brown PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count; 38210a96aa3bSJed Brown PetscInt count; 38220a96aa3bSJed Brown 38230a96aa3bSJed Brown for (count = 0; count < numGhosts - cLocalStart; count++) { 38240a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 38250a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 38260a96aa3bSJed Brown 38279566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count + cLocalEnd, quad, t, pforest->topo->conn, coords)); 38280a96aa3bSJed Brown } 38290a96aa3bSJed Brown } 38300a96aa3bSJed Brown } 38319566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordLocalVec, &coords)); 38323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38330a96aa3bSJed Brown } 38340a96aa3bSJed Brown 3835d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestQuadrantIsInterior(p4est_quadrant_t *quad, PetscBool *is_interior) 3836d71ae5a4SJacob Faibussowitsch { 3837852b71a7SToby Isaac PetscFunctionBegin; 3838852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level); 3839852b71a7SToby Isaac if ((quad->x > 0) && (quad->x + h < P4EST_ROOT_LEN) 3840852b71a7SToby Isaac #ifdef P4_TO_P8 3841852b71a7SToby Isaac && (quad->z > 0) && (quad->z + h < P4EST_ROOT_LEN) 3842852b71a7SToby Isaac #endif 3843852b71a7SToby Isaac && (quad->y > 0) && (quad->y + h < P4EST_ROOT_LEN)) { 3844852b71a7SToby Isaac *is_interior = PETSC_TRUE; 3845852b71a7SToby Isaac } else { 3846852b71a7SToby Isaac *is_interior = PETSC_FALSE; 3847852b71a7SToby Isaac } 38483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3849852b71a7SToby Isaac } 3850852b71a7SToby Isaac 3851852b71a7SToby Isaac /* We always use DG coordinates with p4est: if they do not match the vertex 3852852b71a7SToby Isaac coordinates, add space for them in the section */ 3853d71ae5a4SJacob 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) 3854d71ae5a4SJacob Faibussowitsch { 3855852b71a7SToby Isaac PetscBool is_interior; 3856852b71a7SToby Isaac 3857852b71a7SToby Isaac PetscFunctionBegin; 3858852b71a7SToby Isaac PetscCall(PforestQuadrantIsInterior(quad, &is_interior)); 3859852b71a7SToby Isaac if (is_interior) { // quads in the interior of a coarse cell can't touch periodic interfaces 3860852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3861852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3862852b71a7SToby Isaac } else { 3863852b71a7SToby Isaac PetscInt cSize; 3864852b71a7SToby Isaac PetscScalar *values = NULL; 3865852b71a7SToby Isaac PetscBool same_coords = PETSC_TRUE; 3866852b71a7SToby Isaac 3867852b71a7SToby Isaac PetscCall(DMPlexVecGetClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3868852b71a7SToby Isaac PetscAssert(cSize == cDim * P4EST_CHILDREN, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected closure size"); 3869852b71a7SToby Isaac for (int c = 0; c < P4EST_CHILDREN; c++) { 3870852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3871852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level); 3872852b71a7SToby Isaac double corner_coords[3]; 3873852b71a7SToby Isaac double vert_coords[3]; 3874852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 3875852b71a7SToby Isaac 3876ad540459SPierre Jolivet for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) vert_coords[d] = PetscRealPart(values[c * cDim + d]); 3877852b71a7SToby Isaac 3878852b71a7SToby Isaac quad_coords[0] = quad->x; 3879852b71a7SToby Isaac quad_coords[1] = quad->y; 3880852b71a7SToby Isaac #ifdef P4_TO_P8 3881852b71a7SToby Isaac quad_coords[2] = quad->z; 3882852b71a7SToby Isaac #endif 3883ad540459SPierre Jolivet for (int d = 0; d < 3; d++) quad_coords[d] += (corner & (1 << d)) ? h : 0; 3884852b71a7SToby Isaac #ifndef P4_TO_P8 3885648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 3886852b71a7SToby Isaac #else 3887648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 3888852b71a7SToby Isaac #endif 3889852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) { 3890852b71a7SToby Isaac if (fabs(vert_coords[d] - corner_coords[d]) > PETSC_SMALL) { 3891852b71a7SToby Isaac same_coords = PETSC_FALSE; 3892852b71a7SToby Isaac break; 3893852b71a7SToby Isaac } 3894852b71a7SToby Isaac } 3895852b71a7SToby Isaac } 3896852b71a7SToby Isaac if (same_coords) { 3897852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3898852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3899852b71a7SToby Isaac } else { 3900852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, cSize)); 3901852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, cSize)); 3902852b71a7SToby Isaac } 3903852b71a7SToby Isaac PetscCall(DMPlexVecRestoreClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3904852b71a7SToby Isaac } 39053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3906852b71a7SToby Isaac } 3907852b71a7SToby Isaac 3908d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestLocalizeCell(DM plex, PetscInt cDim, DM_Forest_pforest *pforest, PetscSection newSection, PetscInt cell, PetscInt coarsePoint, p4est_quadrant_t *quad, PetscScalar coords[]) 3909d71ae5a4SJacob Faibussowitsch { 3910852b71a7SToby Isaac PetscInt cdof, off; 3911852b71a7SToby Isaac 3912852b71a7SToby Isaac PetscFunctionBegin; 3913852b71a7SToby Isaac PetscCall(PetscSectionGetDof(newSection, cell, &cdof)); 39143ba16761SJacob Faibussowitsch if (!cdof) PetscFunctionReturn(PETSC_SUCCESS); 3915852b71a7SToby Isaac 3916852b71a7SToby Isaac PetscCall(PetscSectionGetOffset(newSection, cell, &off)); 3917852b71a7SToby Isaac for (PetscInt c = 0, pos = off; c < P4EST_CHILDREN; c++) { 3918852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3919852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level); 3920852b71a7SToby Isaac double corner_coords[3]; 3921852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 3922852b71a7SToby Isaac 3923852b71a7SToby Isaac quad_coords[0] = quad->x; 3924852b71a7SToby Isaac quad_coords[1] = quad->y; 3925852b71a7SToby Isaac #ifdef P4_TO_P8 3926852b71a7SToby Isaac quad_coords[2] = quad->z; 3927852b71a7SToby Isaac #endif 3928ad540459SPierre Jolivet for (int d = 0; d < 3; d++) quad_coords[d] += (corner & (1 << d)) ? h : 0; 3929852b71a7SToby Isaac #ifndef P4_TO_P8 3930648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 3931852b71a7SToby Isaac #else 3932648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 3933852b71a7SToby Isaac #endif 3934ad540459SPierre Jolivet for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) coords[pos++] = corner_coords[d]; 3935ad540459SPierre Jolivet for (PetscInt d = PetscMin(cDim, 3); d < cDim; d++) coords[pos++] = 0.; 3936852b71a7SToby Isaac } 39373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3938852b71a7SToby Isaac } 3939852b71a7SToby Isaac 3940d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestLocalizeCoordinates(DM dm, DM plex) 3941d71ae5a4SJacob Faibussowitsch { 39420a96aa3bSJed Brown DM_Forest *forest; 39430a96aa3bSJed Brown DM_Forest_pforest *pforest; 39446858538eSMatthew G. Knepley DM base, cdm, cdmCell; 3945852b71a7SToby Isaac Vec cVec, cVecOld; 3946852b71a7SToby Isaac PetscSection oldSection, newSection; 39470a96aa3bSJed Brown PetscScalar *coords2; 39486858538eSMatthew G. Knepley const PetscReal *L; 39490a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, coarsePoint; 3950852b71a7SToby Isaac PetscInt cDim, newStart, newEnd; 3951852b71a7SToby Isaac PetscInt v, vStart, vEnd, cp, cStart, cEnd, cEndInterior; 39520a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 39530a96aa3bSJed Brown p4est_tree_t *trees; 39546858538eSMatthew G. Knepley PetscBool baseLocalized = PETSC_FALSE; 39550a96aa3bSJed Brown 39560a96aa3bSJed Brown PetscFunctionBegin; 39574fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, NULL, NULL, &L)); 39580a96aa3bSJed Brown /* we localize on all cells if we don't have a base DM or the base DM coordinates have not been localized */ 39599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cDim)); 39609566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 39616858538eSMatthew G. Knepley if (base) PetscCall(DMGetCoordinatesLocalized(base, &baseLocalized)); 39620a96aa3bSJed Brown if (!baseLocalized) base = NULL; 39633ba16761SJacob Faibussowitsch if (!baseLocalized && !L) PetscFunctionReturn(PETSC_SUCCESS); 39649566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &newStart, &newEnd)); 39650a96aa3bSJed Brown 39669566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newSection)); 39679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(newSection, 1)); 39689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(newSection, 0, cDim)); 39699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSection, newStart, newEnd)); 39700a96aa3bSJed Brown 39719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &oldSection)); 39729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd)); 3973852b71a7SToby Isaac PetscCall(DMGetCoordinatesLocal(plex, &cVecOld)); 39740a96aa3bSJed Brown 39750a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 39760a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 39770a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 39780a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 39790a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 39800a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 39810a96aa3bSJed Brown trees = (p4est_tree_t *)pforest->forest->trees->array; 39820a96aa3bSJed Brown 39839566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 39842827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(plex, DM_POLYTOPE_FV_GHOST, &cEndInterior, NULL)); 39850a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 3986852b71a7SToby Isaac cp = 0; 39870a96aa3bSJed Brown if (cLocalStart > 0) { 39880a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 3989852b71a7SToby Isaac PetscInt cell; 39900a96aa3bSJed Brown 3991852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 3992852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 3993852b71a7SToby Isaac 39940a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 3995852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 39960a96aa3bSJed Brown } 39970a96aa3bSJed Brown } 39980a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 3999f4f49eeaSPierre Jolivet p4est_tree_t *tree = &trees[t]; 40000a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 40010a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 4002852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 40030a96aa3bSJed Brown PetscInt i; 40040a96aa3bSJed Brown 40050a96aa3bSJed Brown if (!numQuads) continue; 40060a96aa3bSJed Brown coarsePoint = t; 4007852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 4008852b71a7SToby Isaac PetscInt cell = i + offset; 4009852b71a7SToby Isaac p4est_quadrant_t *quad = &quads[i]; 40100a96aa3bSJed Brown 4011852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 40120a96aa3bSJed Brown } 40130a96aa3bSJed Brown } 40140a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 40150a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 40160a96aa3bSJed Brown PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count; 40170a96aa3bSJed Brown PetscInt count; 40180a96aa3bSJed Brown 4019852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 40200a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 40210a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 4022852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 40230a96aa3bSJed Brown 4024852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 40250a96aa3bSJed Brown } 40260a96aa3bSJed Brown } 4027852b71a7SToby Isaac PetscAssert(cp == cEnd - cStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected number of fine cells %" PetscInt_FMT " != %" PetscInt_FMT, cp, cEnd - cStart); 40280a96aa3bSJed Brown 40299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSection)); 40306858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(plex, &cdm)); 40316858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 40326858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(plex, cdmCell)); 40336858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 40346858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(plex, cDim, newSection)); 40359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &v)); 40369566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &cVec)); 40379566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)cVec, "coordinates")); 40389566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(cVec, cDim)); 40399566063dSJacob Faibussowitsch PetscCall(VecSetSizes(cVec, v, PETSC_DETERMINE)); 40409566063dSJacob Faibussowitsch PetscCall(VecSetType(cVec, VECSTANDARD)); 40419566063dSJacob Faibussowitsch PetscCall(VecSet(cVec, PETSC_MIN_REAL)); 40420a96aa3bSJed Brown 40430a96aa3bSJed Brown /* Localize coordinates on cells if needed */ 40446858538eSMatthew G. Knepley PetscCall(VecGetArray(cVec, &coords2)); 4045852b71a7SToby Isaac cp = 0; 4046852b71a7SToby Isaac if (cLocalStart > 0) { 4047852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 4048852b71a7SToby Isaac PetscInt cell; 4049852b71a7SToby Isaac 4050852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 4051852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 4052852b71a7SToby Isaac 4053852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 4054852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 4055852b71a7SToby Isaac } 4056852b71a7SToby Isaac } 40570a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 4058f4f49eeaSPierre Jolivet p4est_tree_t *tree = &trees[t]; 40590a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 40600a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count; 4061852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array; 4062852b71a7SToby Isaac PetscInt i; 40630a96aa3bSJed Brown 40640a96aa3bSJed Brown if (!numQuads) continue; 4065852b71a7SToby Isaac coarsePoint = t; 4066852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 4067852b71a7SToby Isaac PetscInt cell = i + offset; 40680a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[i]; 40690a96aa3bSJed Brown 4070852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 4071852b71a7SToby Isaac } 4072852b71a7SToby Isaac } 4073852b71a7SToby Isaac if (cLocalEnd - cLocalStart < cEnd - cStart) { 4074852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array; 4075852b71a7SToby Isaac PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count; 4076852b71a7SToby Isaac PetscInt count; 40770a96aa3bSJed Brown 4078852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 4079852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 4080852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 4081852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 40820a96aa3bSJed Brown 4083852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 40840a96aa3bSJed Brown } 40850a96aa3bSJed Brown } 40869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cVec, &coords2)); 40876858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(plex, cVec)); 40889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cVec)); 40899566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newSection)); 40903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40910a96aa3bSJed Brown } 40920a96aa3bSJed Brown 40930a96aa3bSJed Brown #define DMForestClearAdaptivityForest_pforest _append_pforest(DMForestClearAdaptivityForest) 4094d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestClearAdaptivityForest_pforest(DM dm) 4095d71ae5a4SJacob Faibussowitsch { 40960a96aa3bSJed Brown DM_Forest *forest; 40970a96aa3bSJed Brown DM_Forest_pforest *pforest; 40980a96aa3bSJed Brown 40990a96aa3bSJed Brown PetscFunctionBegin; 41000a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 41010a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 4102f4f49eeaSPierre Jolivet PetscCall(PetscSFDestroy(&pforest->pointAdaptToSelfSF)); 4103f4f49eeaSPierre Jolivet PetscCall(PetscSFDestroy(&pforest->pointSelfToAdaptSF)); 41049566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 41059566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 41063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41070a96aa3bSJed Brown } 41080a96aa3bSJed Brown 4109d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMConvert_pforest_plex(DM dm, DMType newtype, DM *plex) 4110d71ae5a4SJacob Faibussowitsch { 41110a96aa3bSJed Brown DM_Forest *forest; 41120a96aa3bSJed Brown DM_Forest_pforest *pforest; 41130a96aa3bSJed Brown DM refTree, newPlex, base; 41140a96aa3bSJed Brown PetscInt adjDim, adjCodim, coordDim; 41150a96aa3bSJed Brown MPI_Comm comm; 41160a96aa3bSJed Brown PetscBool isPforest; 41170a96aa3bSJed Brown PetscInt dim; 41180a96aa3bSJed Brown PetscInt overlap; 41190a96aa3bSJed Brown p4est_connect_type_t ctype; 41200a96aa3bSJed Brown p4est_locidx_t first_local_quad = -1; 41210a96aa3bSJed Brown sc_array_t *points_per_dim, *cone_sizes, *cones, *cone_orientations, *coords, *children, *parents, *childids, *leaves, *remotes; 41220a96aa3bSJed Brown PetscSection parentSection; 41230a96aa3bSJed Brown PetscSF pointSF; 41240a96aa3bSJed Brown size_t zz, count; 41250a96aa3bSJed Brown PetscInt pStart, pEnd; 41260a96aa3bSJed Brown DMLabel ghostLabelBase = NULL; 41270a96aa3bSJed Brown 41280a96aa3bSJed Brown PetscFunctionBegin; 41290a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41300a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 41319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPFOREST, &isPforest)); 413228b400f6SJacob Faibussowitsch PetscCheck(isPforest, comm, PETSC_ERR_ARG_WRONG, "Expected DM type %s, got %s", DMPFOREST, ((PetscObject)dm)->type_name); 4133671c294aSToby Isaac PetscCall(DMSetUp(dm)); 41349566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 413563a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM, comm, PETSC_ERR_ARG_WRONG, "Expected DM dimension %d, got %" PetscInt_FMT, P4EST_DIM, dim); 41360a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 41370a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 41389566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 413948a46eb9SPierre Jolivet if (base) PetscCall(DMGetLabel(base, "ghost", &ghostLabelBase)); 41400a96aa3bSJed Brown if (!pforest->plex) { 41410a96aa3bSJed Brown PetscMPIInt size; 4142*c7d28b7cSMatthew G. Knepley const char *name; 41430a96aa3bSJed Brown 41449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 41459566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &newPlex)); 4146*c7d28b7cSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 4147*c7d28b7cSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)newPlex, name)); 41489566063dSJacob Faibussowitsch PetscCall(DMSetType(newPlex, DMPLEX)); 41499566063dSJacob Faibussowitsch PetscCall(DMSetMatType(newPlex, dm->mattype)); 41500a96aa3bSJed Brown /* share labels */ 41519566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, newPlex, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 41529566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyDimension(dm, &adjDim)); 41539566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyCodimension(dm, &adjCodim)); 41549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim)); 41550a96aa3bSJed Brown if (adjDim == 0) { 41560a96aa3bSJed Brown ctype = P4EST_CONNECT_FULL; 41570a96aa3bSJed Brown } else if (adjCodim == 1) { 41580a96aa3bSJed Brown ctype = P4EST_CONNECT_FACE; 41590a96aa3bSJed Brown #if defined(P4_TO_P8) 41600a96aa3bSJed Brown } else if (adjDim == 1) { 41610a96aa3bSJed Brown ctype = P8EST_CONNECT_EDGE; 41620a96aa3bSJed Brown #endif 41630a96aa3bSJed Brown } else { 416463a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid adjacency dimension %" PetscInt_FMT, adjDim); 41650a96aa3bSJed Brown } 416663a3b9bcSJacob 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); 41679566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 416860667520SVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(newPlex, NULL, overlap)); 41690a96aa3bSJed Brown 41700a96aa3bSJed Brown points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 41710a96aa3bSJed Brown cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 41720a96aa3bSJed Brown cones = sc_array_new(sizeof(p4est_locidx_t)); 41730a96aa3bSJed Brown cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 41740a96aa3bSJed Brown coords = sc_array_new(3 * sizeof(double)); 41750a96aa3bSJed Brown children = sc_array_new(sizeof(p4est_locidx_t)); 41760a96aa3bSJed Brown parents = sc_array_new(sizeof(p4est_locidx_t)); 41770a96aa3bSJed Brown childids = sc_array_new(sizeof(p4est_locidx_t)); 41780a96aa3bSJed Brown leaves = sc_array_new(sizeof(p4est_locidx_t)); 41790a96aa3bSJed Brown remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 41800a96aa3bSJed Brown 4181792fecdfSBarry 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)); 41820a96aa3bSJed Brown 41830a96aa3bSJed Brown pforest->cLocalStart = (PetscInt)first_local_quad; 41840a96aa3bSJed Brown pforest->cLocalEnd = pforest->cLocalStart + (PetscInt)pforest->forest->local_num_quadrants; 41859566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 41869566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 41879566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 41889566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 41899566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, coordDim)); 41909566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(children)); 41919566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(parents)); 41929566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(childids)); 41939566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(leaves)); 41949566063dSJacob Faibussowitsch PetscCall(locidx_pair_to_PetscSFNode(remotes)); 41950a96aa3bSJed Brown 41969566063dSJacob Faibussowitsch PetscCall(DMSetDimension(newPlex, P4EST_DIM)); 41979566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(newPlex, coordDim)); 41989566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(newPlex, P4EST_DIM - 1)); 41999566063dSJacob 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)); 42009566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(newPlex)); 42019566063dSJacob Faibussowitsch PetscCall(DMCreateReferenceTree_pforest(comm, &refTree)); 42029566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlex, refTree)); 42039566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &parentSection)); 42049566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(newPlex, &pStart, &pEnd)); 42059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd)); 42060a96aa3bSJed Brown count = children->elem_count; 42070a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 42080a96aa3bSJed Brown PetscInt child = *((PetscInt *)sc_array_index(children, zz)); 42090a96aa3bSJed Brown 42109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(parentSection, child, 1)); 42110a96aa3bSJed Brown } 42129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 42139566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(newPlex, parentSection, (PetscInt *)parents->array, (PetscInt *)childids->array)); 42149566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 42159566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &pointSF)); 42160a96aa3bSJed Brown /* 42170a96aa3bSJed Brown These arrays defining the sf are from the p4est library, but the code there shows the leaves being populated in increasing order. 42180a96aa3bSJed Brown https://gitlab.com/petsc/petsc/merge_requests/2248#note_240186391 42190a96aa3bSJed Brown */ 42209566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(pointSF, pEnd - pStart, (PetscInt)leaves->elem_count, (PetscInt *)leaves->array, PETSC_COPY_VALUES, (PetscSFNode *)remotes->array, PETSC_COPY_VALUES)); 42219566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(newPlex, pointSF)); 42229566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 42230a96aa3bSJed Brown { 42240a96aa3bSJed Brown DM coordDM; 42250a96aa3bSJed Brown 42269566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex, &coordDM)); 42279566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(coordDM, pointSF)); 42280a96aa3bSJed Brown } 42299566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointSF)); 42300a96aa3bSJed Brown sc_array_destroy(points_per_dim); 42310a96aa3bSJed Brown sc_array_destroy(cone_sizes); 42320a96aa3bSJed Brown sc_array_destroy(cones); 42330a96aa3bSJed Brown sc_array_destroy(cone_orientations); 42340a96aa3bSJed Brown sc_array_destroy(coords); 42350a96aa3bSJed Brown sc_array_destroy(children); 42360a96aa3bSJed Brown sc_array_destroy(parents); 42370a96aa3bSJed Brown sc_array_destroy(childids); 42380a96aa3bSJed Brown sc_array_destroy(leaves); 42390a96aa3bSJed Brown sc_array_destroy(remotes); 42400a96aa3bSJed Brown 42410a96aa3bSJed Brown { 42424fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 42430a96aa3bSJed Brown 42444fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 42454fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(newPlex, maxCell, Lstart, L)); 42469566063dSJacob Faibussowitsch PetscCall(DMPforestLocalizeCoordinates(dm, newPlex)); 42470a96aa3bSJed Brown } 42480a96aa3bSJed Brown 42490a96aa3bSJed Brown if (overlap > 0) { /* the p4est routine can't set all of the coordinates in its routine if there is overlap */ 42500a96aa3bSJed Brown Vec coordsGlobal, coordsLocal; 42510a96aa3bSJed Brown const PetscScalar *globalArray; 42520a96aa3bSJed Brown PetscScalar *localArray; 42530a96aa3bSJed Brown PetscSF coordSF; 42540a96aa3bSJed Brown DM coordDM; 42550a96aa3bSJed Brown 42569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex, &coordDM)); 42579566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(coordDM, &coordSF)); 42589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(newPlex, &coordsGlobal)); 42599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coordsLocal)); 42609566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordsGlobal, &globalArray)); 42619566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordsLocal, &localArray)); 42629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coordSF, MPIU_SCALAR, globalArray, localArray, MPI_REPLACE)); 42639566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coordSF, MPIU_SCALAR, globalArray, localArray, MPI_REPLACE)); 42649566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordsLocal, &localArray)); 42659566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordsGlobal, &globalArray)); 42669566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(newPlex, coordsLocal)); 42670a96aa3bSJed Brown } 42689566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates(dm, newPlex)); 42690a96aa3bSJed Brown 42700a96aa3bSJed Brown pforest->plex = newPlex; 42710a96aa3bSJed Brown 42720a96aa3bSJed Brown /* copy labels */ 42739566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsFinalize(dm, newPlex)); 42740a96aa3bSJed Brown 42750a96aa3bSJed Brown if (ghostLabelBase || pforest->ghostName) { /* we have to do this after copying labels because the labels drive the construction of ghost cells */ 42760a96aa3bSJed Brown PetscInt numAdded; 42770a96aa3bSJed Brown DM newPlexGhosted; 42780a96aa3bSJed Brown void *ctx; 42790a96aa3bSJed Brown 42809566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(newPlex, pforest->ghostName, &numAdded, &newPlexGhosted)); 42819566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(newPlex, &ctx)); 42829566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(newPlexGhosted, ctx)); 42830a96aa3bSJed Brown /* we want the sf for the ghost dm to be the one for the p4est dm as well */ 42849566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(newPlexGhosted, &pointSF)); 42859566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF)); 42869566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newPlex)); 42879566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlexGhosted, refTree)); 42889566063dSJacob Faibussowitsch PetscCall(DMForestClearAdaptivityForest_pforest(dm)); 42890a96aa3bSJed Brown newPlex = newPlexGhosted; 42900a96aa3bSJed Brown 42910a96aa3bSJed Brown /* share the labels back */ 42929566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 42939566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(newPlex, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 42940a96aa3bSJed Brown pforest->plex = newPlex; 42950a96aa3bSJed Brown } 42969566063dSJacob Faibussowitsch PetscCall(DMDestroy(&refTree)); 42970a96aa3bSJed Brown if (dm->setfromoptionscalled) { 4298d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)newPlex); 4299dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(newPlex, PetscOptionsObject)); 4300dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)newPlex, PetscOptionsObject)); 4301d0609cedSBarry Smith PetscOptionsEnd(); 43020a96aa3bSJed Brown } 43039566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(newPlex, NULL, "-dm_p4est_plex_view")); 43040a96aa3bSJed Brown { 43056858538eSMatthew G. Knepley DM cdm; 43060a96aa3bSJed Brown PetscSection coordsSec; 43070a96aa3bSJed Brown Vec coords; 43080a96aa3bSJed Brown PetscInt cDim; 43090a96aa3bSJed Brown 43109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(newPlex, &cDim)); 43119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(newPlex, &coordsSec)); 43129566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dm, cDim, coordsSec)); 43139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coords)); 43149566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 4315707c51c7SToby Isaac PetscCall(DMGetCoordinateDM(newPlex, &cdm)); 4316707c51c7SToby Isaac if (cdm) { 4317707c51c7SToby Isaac PetscFE fe; 4318707c51c7SToby Isaac #if !defined(P4_TO_P8) 4319707c51c7SToby Isaac DMPolytopeType celltype = DM_POLYTOPE_QUADRILATERAL; 4320707c51c7SToby Isaac #else 4321707c51c7SToby Isaac DMPolytopeType celltype = DM_POLYTOPE_HEXAHEDRON; 4322707c51c7SToby Isaac #endif 4323707c51c7SToby Isaac 4324707c51c7SToby Isaac PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dim, celltype, 1, PETSC_DEFAULT, &fe)); 4325707c51c7SToby Isaac PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe)); 4326707c51c7SToby Isaac PetscCall(PetscFEDestroy(&fe)); 4327707c51c7SToby Isaac PetscCall(DMCreateDS(cdm)); 4328707c51c7SToby Isaac } 43296858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex, &cdm)); 43306858538eSMatthew G. Knepley if (cdm) PetscCall(DMSetCellCoordinateDM(dm, cdm)); 43316858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(newPlex, &coordsSec)); 43326858538eSMatthew G. Knepley if (coordsSec) PetscCall(DMSetCellCoordinateSection(dm, cDim, coordsSec)); 43336858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(newPlex, &coords)); 43346858538eSMatthew G. Knepley if (coords) PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 43350a96aa3bSJed Brown } 4336cdf84abbSMatthew G. Knepley } else { 4337cdf84abbSMatthew G. Knepley PetscCall(DMCopyLabels(dm, pforest->plex, PETSC_OWN_POINTER, PETSC_FALSE, DM_COPY_LABELS_REPLACE)); 43380a96aa3bSJed Brown } 43390a96aa3bSJed Brown newPlex = pforest->plex; 43400a96aa3bSJed Brown if (plex) { 43419566063dSJacob Faibussowitsch PetscCall(DMClone(newPlex, plex)); 43426858538eSMatthew G. Knepley #if 0 43439566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM)); 43449566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(*plex,coordDM)); 43456858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex,&coordDM)); 43466858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*plex,coordDM)); 43476858538eSMatthew G. Knepley #endif 43489566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm, *plex)); 43490a96aa3bSJed Brown } 43503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43510a96aa3bSJed Brown } 43520a96aa3bSJed Brown 4353d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_pforest(DM dm, PetscOptionItems *PetscOptionsObject) 4354d71ae5a4SJacob Faibussowitsch { 43550a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 43560a96aa3bSJed Brown char stringBuffer[256]; 43570a96aa3bSJed Brown PetscBool flg; 43580a96aa3bSJed Brown 43590a96aa3bSJed Brown PetscFunctionBegin; 4360dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Forest(dm, PetscOptionsObject)); 4361d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DM" P4EST_STRING " options"); 4362217f96c1SStefano Zampini PetscCall(PetscOptionsBool("-dm_p4est_partition_for_coarsening", "partition forest to allow for coarsening", "DMP4estSetPartitionForCoarsening", pforest->partition_for_coarsening, &pforest->partition_for_coarsening, NULL)); 43639566063dSJacob 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)); 4364d0609cedSBarry Smith PetscOptionsHeadEnd(); 43650a96aa3bSJed Brown if (flg) { 43669566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName)); 43679566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(stringBuffer, &pforest->ghostName)); 43680a96aa3bSJed Brown } 43693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43700a96aa3bSJed Brown } 43710a96aa3bSJed Brown 43720a96aa3bSJed Brown #if !defined(P4_TO_P8) 43730a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP4estGetPartitionForCoarsening 43740a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP4estSetPartitionForCoarsening 43750a96aa3bSJed Brown #else 43760a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP8estGetPartitionForCoarsening 43770a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP8estSetPartitionForCoarsening 43780a96aa3bSJed Brown #endif 43790a96aa3bSJed Brown 4380d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMPforestGetPartitionForCoarsening(DM dm, PetscBool *flg) 4381d71ae5a4SJacob Faibussowitsch { 43820a96aa3bSJed Brown DM_Forest_pforest *pforest; 43830a96aa3bSJed Brown 43840a96aa3bSJed Brown PetscFunctionBegin; 43850a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43860a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 43870a96aa3bSJed Brown *flg = pforest->partition_for_coarsening; 43883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43890a96aa3bSJed Brown } 43900a96aa3bSJed Brown 4391d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMPforestSetPartitionForCoarsening(DM dm, PetscBool flg) 4392d71ae5a4SJacob Faibussowitsch { 43930a96aa3bSJed Brown DM_Forest_pforest *pforest; 43940a96aa3bSJed Brown 43950a96aa3bSJed Brown PetscFunctionBegin; 43960a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43970a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 43980a96aa3bSJed Brown pforest->partition_for_coarsening = flg; 43993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44000a96aa3bSJed Brown } 44010a96aa3bSJed Brown 4402d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetPlex(DM dm, DM *plex) 4403d71ae5a4SJacob Faibussowitsch { 44040a96aa3bSJed Brown DM_Forest_pforest *pforest; 44050a96aa3bSJed Brown 44060a96aa3bSJed Brown PetscFunctionBegin; 44070a96aa3bSJed Brown if (plex) *plex = NULL; 44089566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 44090a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data; 441048a46eb9SPierre Jolivet if (!pforest->plex) PetscCall(DMConvert_pforest_plex(dm, DMPLEX, NULL)); 44119566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm, pforest->plex)); 44120a96aa3bSJed Brown if (plex) *plex = pforest->plex; 44133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44140a96aa3bSJed Brown } 44150a96aa3bSJed Brown 44160a96aa3bSJed Brown #define DMCreateInterpolation_pforest _append_pforest(DMCreateInterpolation) 4417d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateInterpolation_pforest(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 4418d71ae5a4SJacob Faibussowitsch { 44190a96aa3bSJed Brown PetscSection gsc, gsf; 44200a96aa3bSJed Brown PetscInt m, n; 44210a96aa3bSJed Brown DM cdm; 44220a96aa3bSJed Brown 44230a96aa3bSJed Brown PetscFunctionBegin; 44249566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 44259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 44269566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 44279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 44280a96aa3bSJed Brown 44299566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmFine), interpolation)); 44309566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 44319566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, MATAIJ)); 44320a96aa3bSJed Brown 44339566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 443408401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse, PetscObjectComm((PetscObject)dmFine), PETSC_ERR_SUP, "Only interpolation from coarse DM for now"); 44350a96aa3bSJed Brown 44360a96aa3bSJed Brown { 44370a96aa3bSJed Brown DM plexF, plexC; 44380a96aa3bSJed Brown PetscSF sf; 44390a96aa3bSJed Brown PetscInt *cids; 44400a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1}; 44410a96aa3bSJed Brown 44429566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse, &plexC)); 44439566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine, &plexF)); 44449566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 44459566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 44469566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInterpolatorTree(plexC, plexF, sf, cids, *interpolation)); 44479566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 44489566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 44490a96aa3bSJed Brown } 44509566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 44510a96aa3bSJed Brown /* Use naive scaling */ 44529566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 44533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44540a96aa3bSJed Brown } 44550a96aa3bSJed Brown 44560a96aa3bSJed Brown #define DMCreateInjection_pforest _append_pforest(DMCreateInjection) 4457d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateInjection_pforest(DM dmCoarse, DM dmFine, Mat *injection) 4458d71ae5a4SJacob Faibussowitsch { 44590a96aa3bSJed Brown PetscSection gsc, gsf; 44600a96aa3bSJed Brown PetscInt m, n; 44610a96aa3bSJed Brown DM cdm; 44620a96aa3bSJed Brown 44630a96aa3bSJed Brown PetscFunctionBegin; 44649566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 44659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &n)); 44669566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 44679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &m)); 44680a96aa3bSJed Brown 44699566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmFine), injection)); 44709566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*injection, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 44719566063dSJacob Faibussowitsch PetscCall(MatSetType(*injection, MATAIJ)); 44720a96aa3bSJed Brown 44739566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 447408401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse, PetscObjectComm((PetscObject)dmFine), PETSC_ERR_SUP, "Only injection to coarse DM for now"); 44750a96aa3bSJed Brown 44760a96aa3bSJed Brown { 44770a96aa3bSJed Brown DM plexF, plexC; 44780a96aa3bSJed Brown PetscSF sf; 44790a96aa3bSJed Brown PetscInt *cids; 44800a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1}; 44810a96aa3bSJed Brown 44829566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse, &plexC)); 44839566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine, &plexF)); 44849566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 44859566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 44869566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorTree(plexC, plexF, sf, cids, *injection)); 44879566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 44889566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 44890a96aa3bSJed Brown } 44909566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*injection, NULL, "-inject_mat_view")); 44910a96aa3bSJed Brown /* Use naive scaling */ 44923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44930a96aa3bSJed Brown } 44940a96aa3bSJed Brown 44950a96aa3bSJed Brown #define DMForestTransferVecFromBase_pforest _append_pforest(DMForestTransferVecFromBase) 4496d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestTransferVecFromBase_pforest(DM dm, Vec vecIn, Vec vecOut) 4497d71ae5a4SJacob Faibussowitsch { 44980a96aa3bSJed Brown DM dmIn, dmVecIn, base, basec, plex, coarseDM; 44990a96aa3bSJed Brown DM *hierarchy; 45000a96aa3bSJed Brown PetscSF sfRed = NULL; 45010a96aa3bSJed Brown PetscDS ds; 45020a96aa3bSJed Brown Vec vecInLocal, vecOutLocal; 45030a96aa3bSJed Brown DMLabel subpointMap; 45040a96aa3bSJed Brown PetscInt minLevel, mh, n_hi, i; 45050a96aa3bSJed Brown PetscBool hiforest, *hierarchy_forest; 45060a96aa3bSJed Brown 45070a96aa3bSJed Brown PetscFunctionBegin; 45089566063dSJacob Faibussowitsch PetscCall(VecGetDM(vecIn, &dmVecIn)); 45099566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmVecIn, &ds)); 451028b400f6SJacob Faibussowitsch PetscCheck(ds, PetscObjectComm((PetscObject)dmVecIn), PETSC_ERR_SUP, "Cannot transfer without a PetscDS object"); 45110a96aa3bSJed Brown { /* we cannot stick user contexts into function callbacks for DMProjectFieldLocal! */ 45120a96aa3bSJed Brown PetscSection section; 45130a96aa3bSJed Brown PetscInt Nf; 45140a96aa3bSJed Brown 45159566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn, §ion)); 45169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 451763a3b9bcSJacob 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); 45180a96aa3bSJed Brown } 45199566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel)); 452063a3b9bcSJacob Faibussowitsch PetscCheck(!minLevel, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot transfer with minimum refinement set to %" PetscInt_FMT ". Rerun with DMForestSetMinimumRefinement(dm,0)", minLevel); 45219566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base)); 452228b400f6SJacob Faibussowitsch PetscCheck(base, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing base DM"); 45230a96aa3bSJed Brown 45249566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0)); 45250a96aa3bSJed Brown if (dmVecIn == base) { /* sequential runs */ 45269566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 45270a96aa3bSJed Brown } else { 45280a96aa3bSJed Brown PetscSection secIn, secInRed; 45290a96aa3bSJed Brown Vec vecInRed, vecInLocal; 45300a96aa3bSJed Brown 45319566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)base, "_base_migration_sf", (PetscObject *)&sfRed)); 453228b400f6SJacob Faibussowitsch PetscCheck(sfRed, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not the DM set with DMForestSetBaseDM()"); 45339566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmVecIn), &secInRed)); 45349566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &vecInRed)); 45359566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn, &secIn)); 45369566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmVecIn, &vecInLocal)); 45379566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmVecIn, vecIn, INSERT_VALUES, vecInLocal)); 45389566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmVecIn, vecIn, INSERT_VALUES, vecInLocal)); 45399566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dmVecIn, sfRed, secIn, vecInLocal, secInRed, vecInRed)); 45409566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmVecIn, &vecInLocal)); 45419566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secInRed)); 45420a96aa3bSJed Brown vecIn = vecInRed; 45430a96aa3bSJed Brown } 45440a96aa3bSJed Brown 45450a96aa3bSJed Brown /* we first search through the AdaptivityForest hierarchy 45460a96aa3bSJed Brown once we found the first disconnected forest, we upsweep the DM hierarchy */ 45470a96aa3bSJed Brown hiforest = PETSC_TRUE; 45480a96aa3bSJed Brown 45490a96aa3bSJed Brown /* upsweep to the coarsest DM */ 45500a96aa3bSJed Brown n_hi = 0; 45510a96aa3bSJed Brown coarseDM = dm; 45520a96aa3bSJed Brown do { 45530a96aa3bSJed Brown PetscBool isforest; 45540a96aa3bSJed Brown 45550a96aa3bSJed Brown dmIn = coarseDM; 45560a96aa3bSJed Brown /* need to call DMSetUp to have the hierarchy recursively setup */ 45579566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmIn)); 45589566063dSJacob Faibussowitsch PetscCall(DMIsForest(dmIn, &isforest)); 455928b400f6SJacob Faibussowitsch PetscCheck(isforest, PetscObjectComm((PetscObject)dmIn), PETSC_ERR_SUP, "Cannot currently transfer through a mixed hierarchy! Found DM type %s", ((PetscObject)dmIn)->type_name); 45600a96aa3bSJed Brown coarseDM = NULL; 456148a46eb9SPierre Jolivet if (hiforest) PetscCall(DMForestGetAdaptivityForest(dmIn, &coarseDM)); 45620a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 45630a96aa3bSJed Brown hiforest = PETSC_FALSE; 45649566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn, &coarseDM)); 45650a96aa3bSJed Brown } 45660a96aa3bSJed Brown n_hi++; 45670a96aa3bSJed Brown } while (coarseDM); 45680a96aa3bSJed Brown 45699566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n_hi, &hierarchy, n_hi, &hierarchy_forest)); 45700a96aa3bSJed Brown 45710a96aa3bSJed Brown i = 0; 45720a96aa3bSJed Brown hiforest = PETSC_TRUE; 45730a96aa3bSJed Brown coarseDM = dm; 45740a96aa3bSJed Brown do { 45750a96aa3bSJed Brown dmIn = coarseDM; 45760a96aa3bSJed Brown coarseDM = NULL; 457748a46eb9SPierre Jolivet if (hiforest) PetscCall(DMForestGetAdaptivityForest(dmIn, &coarseDM)); 45780a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 45790a96aa3bSJed Brown hiforest = PETSC_FALSE; 45809566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn, &coarseDM)); 45810a96aa3bSJed Brown } 45820a96aa3bSJed Brown i++; 45830a96aa3bSJed Brown hierarchy[n_hi - i] = dmIn; 45840a96aa3bSJed Brown } while (coarseDM); 45850a96aa3bSJed Brown 45860a96aa3bSJed Brown /* project base vector on the coarsest forest (minimum refinement = 0) */ 45879566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn, &plex)); 45880a96aa3bSJed Brown 45890a96aa3bSJed Brown /* Check this plex is compatible with the base */ 45900a96aa3bSJed Brown { 45910a96aa3bSJed Brown IS gnum[2]; 45920a96aa3bSJed Brown PetscInt ncells[2], gncells[2]; 45930a96aa3bSJed Brown 45949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(base, &gnum[0])); 45959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(plex, &gnum[1])); 45969566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[0], NULL, &ncells[0])); 45979566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[1], NULL, &ncells[1])); 45981c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(ncells, gncells, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 459963a3b9bcSJacob 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); 46000a96aa3bSJed Brown } 46010a96aa3bSJed Brown 46029566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmIn, "_forest_base_subpoint_map", &subpointMap)); 460328b400f6SJacob Faibussowitsch PetscCheck(subpointMap, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing _forest_base_subpoint_map label"); 46040a96aa3bSJed Brown 46059566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(base, &mh)); 46069566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(plex, mh)); 46070a96aa3bSJed Brown 46089566063dSJacob Faibussowitsch PetscCall(DMClone(base, &basec)); 46099566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmVecIn, basec)); 46100a96aa3bSJed Brown if (sfRed) { 46119566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 46120a96aa3bSJed Brown vecInLocal = vecIn; 46130a96aa3bSJed Brown } else { 46149566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(basec, &vecInLocal)); 46159566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(basec, vecIn, INSERT_VALUES, vecInLocal)); 46169566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(basec, vecIn, INSERT_VALUES, vecInLocal)); 46170a96aa3bSJed Brown } 46180a96aa3bSJed Brown 46199566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecOutLocal)); 46200a96aa3bSJed Brown { /* get degrees of freedom ordered onto dmIn */ 46210a96aa3bSJed Brown PetscSF basetocoarse; 46220a96aa3bSJed Brown PetscInt bStart, bEnd, nroots; 46230a96aa3bSJed Brown PetscInt iStart, iEnd, nleaves, leaf; 46240a96aa3bSJed Brown PetscMPIInt rank; 46250a96aa3bSJed Brown PetscSFNode *remotes; 46260a96aa3bSJed Brown PetscSection secIn, secOut; 46270a96aa3bSJed Brown PetscInt *remoteOffsets; 46280a96aa3bSJed Brown PetscSF transferSF; 46290a96aa3bSJed Brown const PetscScalar *inArray; 46300a96aa3bSJed Brown PetscScalar *outArray; 46310a96aa3bSJed Brown 46329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)basec), &rank)); 46339566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(basec, &bStart, &bEnd)); 46340a96aa3bSJed Brown nroots = PetscMax(bEnd - bStart, 0); 46359566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &iStart, &iEnd)); 46360a96aa3bSJed Brown nleaves = PetscMax(iEnd - iStart, 0); 46370a96aa3bSJed Brown 46389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotes)); 46390a96aa3bSJed Brown for (leaf = iStart; leaf < iEnd; leaf++) { 46400a96aa3bSJed Brown PetscInt index; 46410a96aa3bSJed Brown 46420a96aa3bSJed Brown remotes[leaf - iStart].rank = rank; 46439566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, leaf, &index)); 46440a96aa3bSJed Brown remotes[leaf - iStart].index = index; 46450a96aa3bSJed Brown } 46460a96aa3bSJed Brown 46479566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)basec), &basetocoarse)); 46489566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(basetocoarse, nroots, nleaves, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 46499566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(basetocoarse)); 46509566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(basec, &secIn)); 46519566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmIn), &secOut)); 46529566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(basetocoarse, secIn, &remoteOffsets, secOut)); 46539566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(basetocoarse, secIn, remoteOffsets, secOut, &transferSF)); 46549566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 46559566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(vecOutLocal, &outArray)); 46569566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecInLocal, &inArray)); 46579566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferSF, MPIU_SCALAR, inArray, outArray, MPI_REPLACE)); 46589566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferSF, MPIU_SCALAR, inArray, outArray, MPI_REPLACE)); 46599566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecInLocal, &inArray)); 46609566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(vecOutLocal, &outArray)); 46619566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferSF)); 46629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secOut)); 46639566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&basetocoarse)); 46640a96aa3bSJed Brown } 46659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecInLocal)); 46669566063dSJacob Faibussowitsch PetscCall(DMDestroy(&basec)); 46679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecIn)); 46680a96aa3bSJed Brown 46690a96aa3bSJed Brown /* output */ 46700a96aa3bSJed Brown if (n_hi > 1) { /* downsweep the stored hierarchy */ 46710a96aa3bSJed Brown Vec vecOut1, vecOut2; 46720a96aa3bSJed Brown DM fineDM; 46730a96aa3bSJed Brown 46749566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmIn, &vecOut1)); 46759566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn, vecOutLocal, INSERT_VALUES, vecOut1)); 46769566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecOutLocal)); 46770a96aa3bSJed Brown for (i = 1; i < n_hi - 1; i++) { 46780a96aa3bSJed Brown fineDM = hierarchy[i]; 46799566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(fineDM, &vecOut2)); 46809566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn, vecOut1, fineDM, vecOut2, PETSC_TRUE, 0.0)); 46819566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn, &vecOut1)); 46820a96aa3bSJed Brown vecOut1 = vecOut2; 46830a96aa3bSJed Brown dmIn = fineDM; 46840a96aa3bSJed Brown } 46859566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn, vecOut1, dm, vecOut, PETSC_TRUE, 0.0)); 46869566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn, &vecOut1)); 46870a96aa3bSJed Brown } else { 46889566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn, vecOutLocal, INSERT_VALUES, vecOut)); 46899566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecOutLocal)); 46900a96aa3bSJed Brown } 46919566063dSJacob Faibussowitsch PetscCall(PetscFree2(hierarchy, hierarchy_forest)); 46923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46930a96aa3bSJed Brown } 46940a96aa3bSJed Brown 46950a96aa3bSJed Brown #define DMForestTransferVec_pforest _append_pforest(DMForestTransferVec) 4696d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestTransferVec_pforest(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time) 4697d71ae5a4SJacob Faibussowitsch { 46980a96aa3bSJed Brown DM adaptIn, adaptOut, plexIn, plexOut; 46990a96aa3bSJed Brown DM_Forest *forestIn, *forestOut, *forestAdaptIn, *forestAdaptOut; 47000a96aa3bSJed Brown PetscInt dofPerDim[] = {1, 1, 1, 1}; 47010a96aa3bSJed Brown PetscSF inSF = NULL, outSF = NULL; 47020a96aa3bSJed Brown PetscInt *inCids = NULL, *outCids = NULL; 47030a96aa3bSJed Brown DMAdaptFlag purposeIn, purposeOut; 47040a96aa3bSJed Brown 47050a96aa3bSJed Brown PetscFunctionBegin; 47060a96aa3bSJed Brown forestOut = (DM_Forest *)dmOut->data; 47070a96aa3bSJed Brown forestIn = (DM_Forest *)dmIn->data; 47080a96aa3bSJed Brown 47099566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmOut, &adaptOut)); 47109566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmOut, &purposeOut)); 47110a96aa3bSJed Brown forestAdaptOut = adaptOut ? (DM_Forest *)adaptOut->data : NULL; 47120a96aa3bSJed Brown 47139566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn, &adaptIn)); 47149566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmIn, &purposeIn)); 47150a96aa3bSJed Brown forestAdaptIn = adaptIn ? (DM_Forest *)adaptIn->data : NULL; 47160a96aa3bSJed Brown 47170a96aa3bSJed Brown if (forestAdaptOut == forestIn) { 47180a96aa3bSJed Brown switch (purposeOut) { 47190a96aa3bSJed Brown case DM_ADAPT_REFINE: 47209566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 47219566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47220a96aa3bSJed Brown break; 47230a96aa3bSJed Brown case DM_ADAPT_COARSEN: 47240a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 47259566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_TRUE, &outCids)); 47269566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 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 if (forestAdaptIn == forestOut) { 47350a96aa3bSJed Brown switch (purposeIn) { 47360a96aa3bSJed Brown case DM_ADAPT_REFINE: 47379566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_TRUE, &inCids)); 47389566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 47390a96aa3bSJed Brown break; 47400a96aa3bSJed Brown case DM_ADAPT_COARSEN: 47410a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 47429566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 47439566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47440a96aa3bSJed Brown break; 47450a96aa3bSJed Brown default: 47469566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids)); 47479566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_FALSE, &outCids)); 47489566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47499566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 47500a96aa3bSJed Brown } 47510a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dmIn), PETSC_ERR_SUP, "Only support transfer from pre-adaptivity to post-adaptivity right now"); 47529566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn, &plexIn)); 47539566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmOut, &plexOut)); 47540a96aa3bSJed Brown 47559566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree(plexIn, vecIn, plexOut, vecOut, inSF, outSF, inCids, outCids, useBCs, time)); 47569566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 47579566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 47589566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&inSF)); 47599566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&outSF)); 47609566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 47619566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 47623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47630a96aa3bSJed Brown } 47640a96aa3bSJed Brown 47650a96aa3bSJed Brown #define DMCreateCoordinateDM_pforest _append_pforest(DMCreateCoordinateDM) 4766d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateCoordinateDM_pforest(DM dm, DM *cdm) 4767d71ae5a4SJacob Faibussowitsch { 47680a96aa3bSJed Brown DM plex; 47690a96aa3bSJed Brown 47700a96aa3bSJed Brown PetscFunctionBegin; 47710a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47729566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(plex, cdm)); 47749566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*cdm)); 47753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47760a96aa3bSJed Brown } 47770a96aa3bSJed Brown 47780a96aa3bSJed Brown #define VecViewLocal_pforest _append_pforest(VecViewLocal) 4779d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecViewLocal_pforest(Vec vec, PetscViewer viewer) 4780d71ae5a4SJacob Faibussowitsch { 47810a96aa3bSJed Brown DM dm, plex; 47820a96aa3bSJed Brown 47830a96aa3bSJed Brown PetscFunctionBegin; 47849566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 4785217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm)); 47869566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 47879566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 47889566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(vec, viewer)); 47899566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 4790217f96c1SStefano Zampini PetscCall(DMDestroy(&dm)); 47913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47920a96aa3bSJed Brown } 47930a96aa3bSJed Brown 47940a96aa3bSJed Brown #define VecView_pforest _append_pforest(VecView) 4795d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_pforest(Vec vec, PetscViewer viewer) 4796d71ae5a4SJacob Faibussowitsch { 47970a96aa3bSJed Brown DM dm, plex; 47980a96aa3bSJed Brown 47990a96aa3bSJed Brown PetscFunctionBegin; 48009566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 4801217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm)); 48029566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48039566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 48049566063dSJacob Faibussowitsch PetscCall(VecView_Plex(vec, viewer)); 48059566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 4806217f96c1SStefano Zampini PetscCall(DMDestroy(&dm)); 48073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48080a96aa3bSJed Brown } 48090a96aa3bSJed Brown 48100a96aa3bSJed Brown #define VecView_pforest_Native _infix_pforest(VecView, _Native) 4811d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_pforest_Native(Vec vec, PetscViewer viewer) 4812d71ae5a4SJacob Faibussowitsch { 48130a96aa3bSJed Brown DM dm, plex; 48140a96aa3bSJed Brown 48150a96aa3bSJed Brown PetscFunctionBegin; 48169566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 4817217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm)); 48189566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48199566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 48209566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Native(vec, viewer)); 48219566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 4822217f96c1SStefano Zampini PetscCall(DMDestroy(&dm)); 48233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48240a96aa3bSJed Brown } 48250a96aa3bSJed Brown 48260a96aa3bSJed Brown #define VecLoad_pforest _append_pforest(VecLoad) 4827d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecLoad_pforest(Vec vec, PetscViewer viewer) 4828d71ae5a4SJacob Faibussowitsch { 48290a96aa3bSJed Brown DM dm, plex; 48300a96aa3bSJed Brown 48310a96aa3bSJed Brown PetscFunctionBegin; 48329566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 4833217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm)); 48349566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48359566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 48369566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex(vec, viewer)); 48379566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 4838217f96c1SStefano Zampini PetscCall(DMDestroy(&dm)); 48393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48400a96aa3bSJed Brown } 48410a96aa3bSJed Brown 48420a96aa3bSJed Brown #define VecLoad_pforest_Native _infix_pforest(VecLoad, _Native) 4843d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecLoad_pforest_Native(Vec vec, PetscViewer viewer) 4844d71ae5a4SJacob Faibussowitsch { 48450a96aa3bSJed Brown DM dm, plex; 48460a96aa3bSJed Brown 48470a96aa3bSJed Brown PetscFunctionBegin; 48489566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm)); 4849217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm)); 48509566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48519566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex)); 48529566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_Native(vec, viewer)); 48539566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm)); 4854217f96c1SStefano Zampini PetscCall(DMDestroy(&dm)); 48553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48560a96aa3bSJed Brown } 48570a96aa3bSJed Brown 48580a96aa3bSJed Brown #define DMCreateGlobalVector_pforest _append_pforest(DMCreateGlobalVector) 4859d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_pforest(DM dm, Vec *vec) 4860d71ae5a4SJacob Faibussowitsch { 48610a96aa3bSJed Brown PetscFunctionBegin; 48629566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 48639566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 48649566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_pforest)); 48659566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_pforest_Native)); 48669566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_pforest)); 48679566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_pforest_Native)); 48683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48690a96aa3bSJed Brown } 48700a96aa3bSJed Brown 48710a96aa3bSJed Brown #define DMCreateLocalVector_pforest _append_pforest(DMCreateLocalVector) 4872d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_pforest(DM dm, Vec *vec) 4873d71ae5a4SJacob Faibussowitsch { 48740a96aa3bSJed Brown PetscFunctionBegin; 48759566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 48769566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecViewLocal_pforest)); 48773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48780a96aa3bSJed Brown } 48790a96aa3bSJed Brown 48800a96aa3bSJed Brown #define DMCreateMatrix_pforest _append_pforest(DMCreateMatrix) 4881d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_pforest(DM dm, Mat *mat) 4882d71ae5a4SJacob Faibussowitsch { 48830a96aa3bSJed Brown DM plex; 48840a96aa3bSJed Brown 48850a96aa3bSJed Brown PetscFunctionBegin; 48860a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48879566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 48880a96aa3bSJed Brown if (plex->prealloc_only != dm->prealloc_only) plex->prealloc_only = dm->prealloc_only; /* maybe this should go into forest->plex */ 48892495aca6SStefano Zampini PetscCall(DMSetMatType(plex, dm->mattype)); 48909566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(plex, mat)); 48919566063dSJacob Faibussowitsch PetscCall(MatSetDM(*mat, dm)); 48923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48930a96aa3bSJed Brown } 48940a96aa3bSJed Brown 48950a96aa3bSJed Brown #define DMProjectFunctionLocal_pforest _append_pforest(DMProjectFunctionLocal) 4896d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMProjectFunctionLocal_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 4897d71ae5a4SJacob Faibussowitsch { 48980a96aa3bSJed Brown DM plex; 48990a96aa3bSJed Brown 49000a96aa3bSJed Brown PetscFunctionBegin; 49010a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49029566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49039566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLocal(plex, time, funcs, ctxs, mode, localX)); 49043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49050a96aa3bSJed Brown } 49060a96aa3bSJed Brown 49070a96aa3bSJed Brown #define DMProjectFunctionLabelLocal_pforest _append_pforest(DMProjectFunctionLabelLocal) 4908d71ae5a4SJacob 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) 4909d71ae5a4SJacob Faibussowitsch { 49100a96aa3bSJed Brown DM plex; 49110a96aa3bSJed Brown 49120a96aa3bSJed Brown PetscFunctionBegin; 49130a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49149566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49159566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLabelLocal(plex, time, label, numIds, ids, Ncc, comps, funcs, ctxs, mode, localX)); 49163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49170a96aa3bSJed Brown } 49180a96aa3bSJed Brown 49190a96aa3bSJed Brown #define DMProjectFieldLocal_pforest _append_pforest(DMProjectFieldLocal) 4920d71ae5a4SJacob 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) 4921d71ae5a4SJacob Faibussowitsch { 49220a96aa3bSJed Brown DM plex; 49230a96aa3bSJed Brown 49240a96aa3bSJed Brown PetscFunctionBegin; 49250a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49269566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49279566063dSJacob Faibussowitsch PetscCall(DMProjectFieldLocal(plex, time, localU, funcs, mode, localX)); 49283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49290a96aa3bSJed Brown } 49300a96aa3bSJed Brown 49310a96aa3bSJed Brown #define DMComputeL2Diff_pforest _append_pforest(DMComputeL2Diff) 4932d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 4933d71ae5a4SJacob Faibussowitsch { 49340a96aa3bSJed Brown DM plex; 49350a96aa3bSJed Brown 49360a96aa3bSJed Brown PetscFunctionBegin; 49370a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49389566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49399566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(plex, time, funcs, ctxs, X, diff)); 49403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49410a96aa3bSJed Brown } 49420a96aa3bSJed Brown 49430a96aa3bSJed Brown #define DMComputeL2FieldDiff_pforest _append_pforest(DMComputeL2FieldDiff) 4944d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 4945d71ae5a4SJacob Faibussowitsch { 49460a96aa3bSJed Brown DM plex; 49470a96aa3bSJed Brown 49480a96aa3bSJed Brown PetscFunctionBegin; 49490a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49509566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49519566063dSJacob Faibussowitsch PetscCall(DMComputeL2FieldDiff(plex, time, funcs, ctxs, X, diff)); 49523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49530a96aa3bSJed Brown } 49540a96aa3bSJed Brown 49550a96aa3bSJed Brown #define DMCreatelocalsection_pforest _append_pforest(DMCreatelocalsection) 4956d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreatelocalsection_pforest(DM dm) 4957d71ae5a4SJacob Faibussowitsch { 49580a96aa3bSJed Brown DM plex; 49590a96aa3bSJed Brown PetscSection section; 49600a96aa3bSJed Brown 49610a96aa3bSJed Brown PetscFunctionBegin; 49620a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49639566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49649566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(plex, §ion)); 49659566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(dm, section)); 49663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49670a96aa3bSJed Brown } 49680a96aa3bSJed Brown 49690a96aa3bSJed Brown #define DMCreateDefaultConstraints_pforest _append_pforest(DMCreateDefaultConstraints) 4970d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateDefaultConstraints_pforest(DM dm) 4971d71ae5a4SJacob Faibussowitsch { 49720a96aa3bSJed Brown DM plex; 49730a96aa3bSJed Brown Mat mat; 497479769bd5SJed Brown Vec bias; 49750a96aa3bSJed Brown PetscSection section; 49760a96aa3bSJed Brown 49770a96aa3bSJed Brown PetscFunctionBegin; 49780a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49799566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49809566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(plex, §ion, &mat, &bias)); 49819566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, section, mat, bias)); 49823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49830a96aa3bSJed Brown } 49840a96aa3bSJed Brown 49850a96aa3bSJed Brown #define DMGetDimPoints_pforest _append_pforest(DMGetDimPoints) 4986d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_pforest(DM dm, PetscInt dim, PetscInt *cStart, PetscInt *cEnd) 4987d71ae5a4SJacob Faibussowitsch { 49880a96aa3bSJed Brown DM plex; 49890a96aa3bSJed Brown 49900a96aa3bSJed Brown PetscFunctionBegin; 49910a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49929566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 49939566063dSJacob Faibussowitsch PetscCall(DMGetDimPoints(plex, dim, cStart, cEnd)); 49943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49950a96aa3bSJed Brown } 49960a96aa3bSJed Brown 49970a96aa3bSJed Brown /* Need to forward declare */ 49980a96aa3bSJed Brown #define DMInitialize_pforest _append_pforest(DMInitialize) 49990a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm); 50000a96aa3bSJed Brown 50010a96aa3bSJed Brown #define DMClone_pforest _append_pforest(DMClone) 5002d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMClone_pforest(DM dm, DM *newdm) 5003d71ae5a4SJacob Faibussowitsch { 50040a96aa3bSJed Brown PetscFunctionBegin; 50059566063dSJacob Faibussowitsch PetscCall(DMClone_Forest(dm, newdm)); 50069566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(*newdm)); 50073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50080a96aa3bSJed Brown } 50090a96aa3bSJed Brown 50100a96aa3bSJed Brown #define DMForestCreateCellChart_pforest _append_pforest(DMForestCreateCellChart) 5011d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestCreateCellChart_pforest(DM dm, PetscInt *cStart, PetscInt *cEnd) 5012d71ae5a4SJacob Faibussowitsch { 50130a96aa3bSJed Brown DM_Forest *forest; 50140a96aa3bSJed Brown DM_Forest_pforest *pforest; 50150a96aa3bSJed Brown PetscInt overlap; 50160a96aa3bSJed Brown 50170a96aa3bSJed Brown PetscFunctionBegin; 50189566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 50190a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 50200a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 50210a96aa3bSJed Brown *cStart = 0; 50229566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 50230a96aa3bSJed Brown if (overlap && pforest->ghost) { 50240a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[pforest->forest->mpisize]; 50250a96aa3bSJed Brown } else { 50260a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants; 50270a96aa3bSJed Brown } 50283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50290a96aa3bSJed Brown } 50300a96aa3bSJed Brown 50310a96aa3bSJed Brown #define DMForestCreateCellSF_pforest _append_pforest(DMForestCreateCellSF) 5032d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestCreateCellSF_pforest(DM dm, PetscSF *cellSF) 5033d71ae5a4SJacob Faibussowitsch { 50340a96aa3bSJed Brown DM_Forest *forest; 50350a96aa3bSJed Brown DM_Forest_pforest *pforest; 50360a96aa3bSJed Brown PetscMPIInt rank; 50370a96aa3bSJed Brown PetscInt overlap; 50380a96aa3bSJed Brown PetscInt cStart, cEnd, cLocalStart, cLocalEnd; 50390a96aa3bSJed Brown PetscInt nRoots, nLeaves, *mine = NULL; 50400a96aa3bSJed Brown PetscSFNode *remote = NULL; 50410a96aa3bSJed Brown PetscSF sf; 50420a96aa3bSJed Brown 50430a96aa3bSJed Brown PetscFunctionBegin; 50449566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(dm, &cStart, &cEnd)); 50450a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 50460a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data; 50470a96aa3bSJed Brown nRoots = cEnd - cStart; 50480a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 50490a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 50500a96aa3bSJed Brown nLeaves = 0; 50519566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap)); 50529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 50530a96aa3bSJed Brown if (overlap && pforest->ghost) { 50540a96aa3bSJed Brown PetscSFNode *mirror; 50550a96aa3bSJed Brown p4est_quadrant_t *mirror_array; 50560a96aa3bSJed Brown PetscInt nMirror, nGhostPre, nSelf, q; 50570a96aa3bSJed Brown void **mirrorPtrs; 50580a96aa3bSJed Brown 50590a96aa3bSJed Brown nMirror = (PetscInt)pforest->ghost->mirrors.elem_count; 50600a96aa3bSJed Brown nSelf = cLocalEnd - cLocalStart; 50610a96aa3bSJed Brown nLeaves = nRoots - nSelf; 50620a96aa3bSJed Brown nGhostPre = (PetscInt)pforest->ghost->proc_offsets[rank]; 50639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &mine)); 50649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &remote)); 50659566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nMirror, &mirror, nMirror, &mirrorPtrs)); 50660a96aa3bSJed Brown mirror_array = (p4est_quadrant_t *)pforest->ghost->mirrors.array; 50670a96aa3bSJed Brown for (q = 0; q < nMirror; q++) { 5068f4f49eeaSPierre Jolivet p4est_quadrant_t *mir = &mirror_array[q]; 50690a96aa3bSJed Brown 50700a96aa3bSJed Brown mirror[q].rank = rank; 50710a96aa3bSJed Brown mirror[q].index = (PetscInt)mir->p.piggy3.local_num + cLocalStart; 5072f4f49eeaSPierre Jolivet mirrorPtrs[q] = (void *)&mirror[q]; 50730a96aa3bSJed Brown } 5074792fecdfSBarry Smith PetscCallP4est(p4est_ghost_exchange_custom, (pforest->forest, pforest->ghost, sizeof(PetscSFNode), mirrorPtrs, remote)); 50759566063dSJacob Faibussowitsch PetscCall(PetscFree2(mirror, mirrorPtrs)); 50760a96aa3bSJed Brown for (q = 0; q < nGhostPre; q++) mine[q] = q; 50770a96aa3bSJed Brown for (; q < nLeaves; q++) mine[q] = (q - nGhostPre) + cLocalEnd; 50780a96aa3bSJed Brown } 50799566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &sf)); 50809566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nRoots, nLeaves, mine, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER)); 50810a96aa3bSJed Brown *cellSF = sf; 50823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50830a96aa3bSJed Brown } 50840a96aa3bSJed Brown 5085d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateNeumannOverlap_pforest(DM dm, IS *ovl, Mat *J, PetscErrorCode (**setup)(Mat, PetscReal, Vec, Vec, PetscReal, IS, void *), void **setup_ctx) 5086d71ae5a4SJacob Faibussowitsch { 50870a96aa3bSJed Brown DM plex; 50880a96aa3bSJed Brown 50890a96aa3bSJed Brown PetscFunctionBegin; 50909566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 5091e4d5475eSStefano Zampini PetscCall(DMCopyAuxiliaryVec(dm, plex)); 50929566063dSJacob Faibussowitsch PetscCall(DMCreateNeumannOverlap_Plex(plex, ovl, J, setup, setup_ctx)); 5093e4d5475eSStefano Zampini PetscCall(DMClearAuxiliaryVec(plex)); 50940a96aa3bSJed Brown if (!*setup) { 50959566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", setup)); 509648a46eb9SPierre Jolivet if (*setup) PetscCall(PetscObjectCompose((PetscObject)*ovl, "_DM_Original_HPDDM", (PetscObject)dm)); 50970a96aa3bSJed Brown } 50983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50990a96aa3bSJed Brown } 51000a96aa3bSJed Brown 5101907a3e9cSStefano Zampini #define DMCreateDomainDecomposition_pforest _append_pforest(DMCreateDomainDecomposition) 5102907a3e9cSStefano Zampini static PetscErrorCode DMCreateDomainDecomposition_pforest(DM dm, PetscInt *nsub, char ***names, IS **innerises, IS **outerises, DM **dms) 5103907a3e9cSStefano Zampini { 5104907a3e9cSStefano Zampini DM plex; 5105907a3e9cSStefano Zampini 5106907a3e9cSStefano Zampini PetscFunctionBegin; 5107907a3e9cSStefano Zampini PetscCall(DMPforestGetPlex(dm, &plex)); 5108e4d5475eSStefano Zampini PetscCall(DMCopyAuxiliaryVec(dm, plex)); 5109907a3e9cSStefano Zampini PetscCall(DMCreateDomainDecomposition(plex, nsub, names, innerises, outerises, dms)); 5110e4d5475eSStefano Zampini PetscCall(DMClearAuxiliaryVec(plex)); 5111907a3e9cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 5112907a3e9cSStefano Zampini } 5113907a3e9cSStefano Zampini 5114907a3e9cSStefano Zampini #define DMCreateDomainDecompositionScatters_pforest _append_pforest(DMCreateDomainDecompositionScatters) 5115907a3e9cSStefano Zampini static PetscErrorCode DMCreateDomainDecompositionScatters_pforest(DM dm, PetscInt n, DM *subdms, VecScatter **iscat, VecScatter **oscat, VecScatter **lscat) 5116907a3e9cSStefano Zampini { 5117907a3e9cSStefano Zampini DM plex; 5118907a3e9cSStefano Zampini 5119907a3e9cSStefano Zampini PetscFunctionBegin; 5120907a3e9cSStefano Zampini PetscCall(DMPforestGetPlex(dm, &plex)); 5121e4d5475eSStefano Zampini PetscCall(DMCopyAuxiliaryVec(dm, plex)); 5122907a3e9cSStefano Zampini PetscCall(DMCreateDomainDecompositionScatters(plex, n, subdms, iscat, oscat, lscat)); 5123907a3e9cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 5124907a3e9cSStefano Zampini } 5125907a3e9cSStefano Zampini 5126d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_pforest(DM dm) 5127d71ae5a4SJacob Faibussowitsch { 51280a96aa3bSJed Brown PetscFunctionBegin; 51290a96aa3bSJed Brown dm->ops->setup = DMSetUp_pforest; 51300a96aa3bSJed Brown dm->ops->view = DMView_pforest; 51310a96aa3bSJed Brown dm->ops->clone = DMClone_pforest; 51320a96aa3bSJed Brown dm->ops->createinterpolation = DMCreateInterpolation_pforest; 51330a96aa3bSJed Brown dm->ops->createinjection = DMCreateInjection_pforest; 51340a96aa3bSJed Brown dm->ops->setfromoptions = DMSetFromOptions_pforest; 51350a96aa3bSJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_pforest; 51360a96aa3bSJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_pforest; 51370a96aa3bSJed Brown dm->ops->createlocalvector = DMCreateLocalVector_pforest; 51380a96aa3bSJed Brown dm->ops->creatematrix = DMCreateMatrix_pforest; 51390a96aa3bSJed Brown dm->ops->projectfunctionlocal = DMProjectFunctionLocal_pforest; 51400a96aa3bSJed Brown dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_pforest; 51410a96aa3bSJed Brown dm->ops->projectfieldlocal = DMProjectFieldLocal_pforest; 51420a96aa3bSJed Brown dm->ops->createlocalsection = DMCreatelocalsection_pforest; 51430a96aa3bSJed Brown dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_pforest; 51440a96aa3bSJed Brown dm->ops->computel2diff = DMComputeL2Diff_pforest; 51450a96aa3bSJed Brown dm->ops->computel2fielddiff = DMComputeL2FieldDiff_pforest; 51460a96aa3bSJed Brown dm->ops->getdimpoints = DMGetDimPoints_pforest; 5147907a3e9cSStefano Zampini dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_pforest; 5148907a3e9cSStefano Zampini dm->ops->createddscatters = DMCreateDomainDecompositionScatters_pforest; 51490a96aa3bSJed Brown 51509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_plex_pforest) "_C", DMConvert_plex_pforest)); 51519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_pforest_plex) "_C", DMConvert_pforest_plex)); 51529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_pforest)); 51539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMForestGetPartitionOverlap)); 51543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51550a96aa3bSJed Brown } 51560a96aa3bSJed Brown 51570a96aa3bSJed Brown #define DMCreate_pforest _append_pforest(DMCreate) 5158d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_pforest(DM dm) 5159d71ae5a4SJacob Faibussowitsch { 51600a96aa3bSJed Brown DM_Forest *forest; 51610a96aa3bSJed Brown DM_Forest_pforest *pforest; 51620a96aa3bSJed Brown 51630a96aa3bSJed Brown PetscFunctionBegin; 51649566063dSJacob Faibussowitsch PetscCall(PetscP4estInitialize()); 51659566063dSJacob Faibussowitsch PetscCall(DMCreate_Forest(dm)); 51669566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(dm)); 51679566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, P4EST_DIM)); 51680a96aa3bSJed Brown 51690a96aa3bSJed Brown /* set forest defaults */ 51709566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm, "unit")); 51719566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(dm, 0)); 51729566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(dm, 0)); 51739566063dSJacob Faibussowitsch PetscCall(DMForestSetMaximumRefinement(dm, P4EST_QMAXLEVEL)); 51749566063dSJacob Faibussowitsch PetscCall(DMForestSetGradeFactor(dm, 2)); 51759566063dSJacob Faibussowitsch PetscCall(DMForestSetAdjacencyDimension(dm, 0)); 51769566063dSJacob Faibussowitsch PetscCall(DMForestSetPartitionOverlap(dm, 0)); 51770a96aa3bSJed Brown 51780a96aa3bSJed Brown /* create p4est data */ 51794dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&pforest)); 51800a96aa3bSJed Brown 51810a96aa3bSJed Brown forest = (DM_Forest *)dm->data; 51820a96aa3bSJed Brown forest->data = pforest; 51830a96aa3bSJed Brown forest->destroy = DMForestDestroy_pforest; 51840a96aa3bSJed Brown forest->ftemplate = DMForestTemplate_pforest; 51850a96aa3bSJed Brown forest->transfervec = DMForestTransferVec_pforest; 51860a96aa3bSJed Brown forest->transfervecfrombase = DMForestTransferVecFromBase_pforest; 51870a96aa3bSJed Brown forest->createcellchart = DMForestCreateCellChart_pforest; 51880a96aa3bSJed Brown forest->createcellsf = DMForestCreateCellSF_pforest; 51890a96aa3bSJed Brown forest->clearadaptivityforest = DMForestClearAdaptivityForest_pforest; 51900a96aa3bSJed Brown forest->getadaptivitysuccess = DMForestGetAdaptivitySuccess_pforest; 51910a96aa3bSJed Brown pforest->topo = NULL; 51920a96aa3bSJed Brown pforest->forest = NULL; 51930a96aa3bSJed Brown pforest->ghost = NULL; 51940a96aa3bSJed Brown pforest->lnodes = NULL; 51950a96aa3bSJed Brown pforest->partition_for_coarsening = PETSC_TRUE; 51960a96aa3bSJed Brown pforest->coarsen_hierarchy = PETSC_FALSE; 51970a96aa3bSJed Brown pforest->cLocalStart = -1; 51980a96aa3bSJed Brown pforest->cLocalEnd = -1; 51990a96aa3bSJed Brown pforest->labelsFinalized = PETSC_FALSE; 52000a96aa3bSJed Brown pforest->ghostName = NULL; 52013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52020a96aa3bSJed Brown } 52030a96aa3bSJed Brown 52040a96aa3bSJed Brown #endif /* defined(PETSC_HAVE_P4EST) */ 5205