10a96aa3bSJed Brown #include <petscds.h> 20a96aa3bSJed Brown #include <petsc/private/dmimpl.h> 30a96aa3bSJed Brown #include <petsc/private/dmforestimpl.h> 40a96aa3bSJed Brown #include <petsc/private/dmpleximpl.h> 50a96aa3bSJed Brown #include <petsc/private/dmlabelimpl.h> 60a96aa3bSJed Brown #include <petsc/private/viewerimpl.h> 70a96aa3bSJed Brown #include <../src/sys/classes/viewer/impls/vtk/vtkvimpl.h> 80a96aa3bSJed Brown #include "petsc_p4est_package.h" 90a96aa3bSJed Brown 100a96aa3bSJed Brown #if defined(PETSC_HAVE_P4EST) 110a96aa3bSJed Brown 120a96aa3bSJed Brown #if !defined(P4_TO_P8) 130a96aa3bSJed Brown #include <p4est.h> 140a96aa3bSJed Brown #include <p4est_extended.h> 150a96aa3bSJed Brown #include <p4est_geometry.h> 160a96aa3bSJed Brown #include <p4est_ghost.h> 170a96aa3bSJed Brown #include <p4est_lnodes.h> 180a96aa3bSJed Brown #include <p4est_vtk.h> 190a96aa3bSJed Brown #include <p4est_plex.h> 200a96aa3bSJed Brown #include <p4est_bits.h> 210a96aa3bSJed Brown #include <p4est_algorithms.h> 220a96aa3bSJed Brown #else 230a96aa3bSJed Brown #include <p8est.h> 240a96aa3bSJed Brown #include <p8est_extended.h> 250a96aa3bSJed Brown #include <p8est_geometry.h> 260a96aa3bSJed Brown #include <p8est_ghost.h> 270a96aa3bSJed Brown #include <p8est_lnodes.h> 280a96aa3bSJed Brown #include <p8est_vtk.h> 290a96aa3bSJed Brown #include <p8est_plex.h> 300a96aa3bSJed Brown #include <p8est_bits.h> 310a96aa3bSJed Brown #include <p8est_algorithms.h> 320a96aa3bSJed Brown #endif 330a96aa3bSJed Brown 340a96aa3bSJed Brown typedef enum {PATTERN_HASH,PATTERN_FRACTAL,PATTERN_CORNER,PATTERN_CENTER,PATTERN_COUNT} DMRefinePattern; 350a96aa3bSJed Brown static const char *DMRefinePatternName[PATTERN_COUNT] = {"hash","fractal","corner","center"}; 360a96aa3bSJed Brown 370a96aa3bSJed Brown typedef struct _DMRefinePatternCtx 380a96aa3bSJed Brown { 390a96aa3bSJed Brown PetscInt corner; 400a96aa3bSJed Brown PetscBool fractal[P4EST_CHILDREN]; 410a96aa3bSJed Brown PetscReal hashLikelihood; 420a96aa3bSJed Brown PetscInt maxLevel; 430a96aa3bSJed Brown p4est_refine_t refine_fn; 440a96aa3bSJed Brown } 450a96aa3bSJed Brown DMRefinePatternCtx; 460a96aa3bSJed Brown 470a96aa3bSJed Brown static int DMRefinePattern_Corner(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 480a96aa3bSJed Brown { 490a96aa3bSJed Brown p4est_quadrant_t root, rootcorner; 500a96aa3bSJed Brown DMRefinePatternCtx *ctx; 510a96aa3bSJed Brown 520a96aa3bSJed Brown ctx = (DMRefinePatternCtx*) p4est->user_pointer; 530a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 540a96aa3bSJed Brown 550a96aa3bSJed Brown root.x = root.y = 0; 560a96aa3bSJed Brown #if defined(P4_TO_P8) 570a96aa3bSJed Brown root.z = 0; 580a96aa3bSJed Brown #endif 590a96aa3bSJed Brown root.level = 0; 600a96aa3bSJed Brown p4est_quadrant_corner_descendant(&root,&rootcorner,ctx->corner,quadrant->level); 610a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant,&rootcorner)) return 1; 620a96aa3bSJed Brown return 0; 630a96aa3bSJed Brown } 640a96aa3bSJed Brown 650a96aa3bSJed Brown static int DMRefinePattern_Center(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 660a96aa3bSJed Brown { 670a96aa3bSJed Brown int cid; 680a96aa3bSJed Brown p4est_quadrant_t ancestor, ancestorcorner; 690a96aa3bSJed Brown DMRefinePatternCtx *ctx; 700a96aa3bSJed Brown 710a96aa3bSJed Brown ctx = (DMRefinePatternCtx*) p4est->user_pointer; 720a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 730a96aa3bSJed Brown if (quadrant->level <= 1) return 1; 740a96aa3bSJed Brown 750a96aa3bSJed Brown p4est_quadrant_ancestor(quadrant,1,&ancestor); 760a96aa3bSJed Brown cid = p4est_quadrant_child_id(&ancestor); 770a96aa3bSJed Brown p4est_quadrant_corner_descendant(&ancestor,&ancestorcorner,P4EST_CHILDREN - 1 - cid,quadrant->level); 780a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant,&ancestorcorner)) return 1; 790a96aa3bSJed Brown return 0; 800a96aa3bSJed Brown } 810a96aa3bSJed Brown 820a96aa3bSJed Brown static int DMRefinePattern_Fractal(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 830a96aa3bSJed Brown { 840a96aa3bSJed Brown int cid; 850a96aa3bSJed Brown DMRefinePatternCtx *ctx; 860a96aa3bSJed Brown 870a96aa3bSJed Brown ctx = (DMRefinePatternCtx*) p4est->user_pointer; 880a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 890a96aa3bSJed Brown if (!quadrant->level) return 1; 900a96aa3bSJed Brown cid = p4est_quadrant_child_id(quadrant); 910a96aa3bSJed Brown if (ctx->fractal[cid ^ ((int) (quadrant->level % P4EST_CHILDREN))]) return 1; 920a96aa3bSJed Brown return 0; 930a96aa3bSJed Brown } 940a96aa3bSJed Brown 950a96aa3bSJed Brown /* simplified from MurmurHash3 by Austin Appleby */ 960a96aa3bSJed Brown #define DMPROT32(x, y) ((x << y) | (x >> (32 - y))) 970a96aa3bSJed Brown static uint32_t DMPforestHash(const uint32_t *blocks, uint32_t nblocks) 980a96aa3bSJed Brown { 990a96aa3bSJed Brown uint32_t c1 = 0xcc9e2d51; 1000a96aa3bSJed Brown uint32_t c2 = 0x1b873593; 1010a96aa3bSJed Brown uint32_t r1 = 15; 1020a96aa3bSJed Brown uint32_t r2 = 13; 1030a96aa3bSJed Brown uint32_t m = 5; 1040a96aa3bSJed Brown uint32_t n = 0xe6546b64; 1050a96aa3bSJed Brown uint32_t hash = 0; 1060a96aa3bSJed Brown int len = nblocks * 4; 1070a96aa3bSJed Brown uint32_t i; 1080a96aa3bSJed Brown 1090a96aa3bSJed Brown for (i = 0; i < nblocks; i++) { 1100a96aa3bSJed Brown uint32_t k; 1110a96aa3bSJed Brown 1120a96aa3bSJed Brown k = blocks[i]; 1130a96aa3bSJed Brown k *= c1; 1140a96aa3bSJed Brown k = DMPROT32(k, r1); 1150a96aa3bSJed Brown k *= c2; 1160a96aa3bSJed Brown 1170a96aa3bSJed Brown hash ^= k; 1180a96aa3bSJed Brown hash = DMPROT32(hash, r2) * m + n; 1190a96aa3bSJed Brown } 1200a96aa3bSJed Brown 1210a96aa3bSJed Brown hash ^= len; 1220a96aa3bSJed Brown hash ^= (hash >> 16); 1230a96aa3bSJed Brown hash *= 0x85ebca6b; 1240a96aa3bSJed Brown hash ^= (hash >> 13); 1250a96aa3bSJed Brown hash *= 0xc2b2ae35; 1260a96aa3bSJed Brown hash ^= (hash >> 16); 1270a96aa3bSJed Brown 1280a96aa3bSJed Brown return hash; 1290a96aa3bSJed Brown } 1300a96aa3bSJed Brown 1310a96aa3bSJed Brown #if defined(UINT32_MAX) 1320a96aa3bSJed Brown #define DMP4EST_HASH_MAX UINT32_MAX 1330a96aa3bSJed Brown #else 1340a96aa3bSJed Brown #define DMP4EST_HASH_MAX ((uint32_t) 0xffffffff) 1350a96aa3bSJed Brown #endif 1360a96aa3bSJed Brown 1370a96aa3bSJed Brown static int DMRefinePattern_Hash(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 1380a96aa3bSJed Brown { 1390a96aa3bSJed Brown uint32_t data[5]; 1400a96aa3bSJed Brown uint32_t result; 1410a96aa3bSJed Brown DMRefinePatternCtx *ctx; 1420a96aa3bSJed Brown 1430a96aa3bSJed Brown ctx = (DMRefinePatternCtx*) p4est->user_pointer; 1440a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 1450a96aa3bSJed Brown data[0] = ((uint32_t) quadrant->level) << 24; 1460a96aa3bSJed Brown data[1] = (uint32_t) which_tree; 1470a96aa3bSJed Brown data[2] = (uint32_t) quadrant->x; 1480a96aa3bSJed Brown data[3] = (uint32_t) quadrant->y; 1490a96aa3bSJed Brown #if defined(P4_TO_P8) 1500a96aa3bSJed Brown data[4] = (uint32_t) quadrant->z; 1510a96aa3bSJed Brown #endif 1520a96aa3bSJed Brown 1530a96aa3bSJed Brown result = DMPforestHash(data,2+P4EST_DIM); 1540a96aa3bSJed Brown if (((double) result / (double) DMP4EST_HASH_MAX) < ctx->hashLikelihood) return 1; 1550a96aa3bSJed Brown return 0; 1560a96aa3bSJed Brown } 1570a96aa3bSJed Brown 1580a96aa3bSJed Brown #define DMConvert_pforest_plex _infix_pforest(DMConvert,_plex) 1590a96aa3bSJed Brown static PetscErrorCode DMConvert_pforest_plex(DM,DMType,DM*); 1600a96aa3bSJed Brown 1610a96aa3bSJed Brown #define DMFTopology_pforest _append_pforest(DMFTopology) 1620a96aa3bSJed Brown typedef struct { 1630a96aa3bSJed Brown PetscInt refct; 1640a96aa3bSJed Brown p4est_connectivity_t *conn; 1650a96aa3bSJed Brown p4est_geometry_t *geom; 1660a96aa3bSJed Brown PetscInt *tree_face_to_uniq; /* p4est does not explicitly enumerate facets, but we must to keep track of labels */ 1670a96aa3bSJed Brown } DMFTopology_pforest; 1680a96aa3bSJed Brown 1690a96aa3bSJed Brown #define DM_Forest_pforest _append_pforest(DM_Forest) 1700a96aa3bSJed Brown typedef struct { 1710a96aa3bSJed Brown DMFTopology_pforest *topo; 1720a96aa3bSJed Brown p4est_t *forest; 1730a96aa3bSJed Brown p4est_ghost_t *ghost; 1740a96aa3bSJed Brown p4est_lnodes_t *lnodes; 1750a96aa3bSJed Brown PetscBool partition_for_coarsening; 1760a96aa3bSJed Brown PetscBool coarsen_hierarchy; 1770a96aa3bSJed Brown PetscBool labelsFinalized; 1780a96aa3bSJed Brown PetscBool adaptivitySuccess; 1790a96aa3bSJed Brown PetscInt cLocalStart; 1800a96aa3bSJed Brown PetscInt cLocalEnd; 1810a96aa3bSJed Brown DM plex; 1820a96aa3bSJed Brown char *ghostName; 1830a96aa3bSJed Brown PetscSF pointAdaptToSelfSF; 1840a96aa3bSJed Brown PetscSF pointSelfToAdaptSF; 1850a96aa3bSJed Brown PetscInt *pointAdaptToSelfCids; 1860a96aa3bSJed Brown PetscInt *pointSelfToAdaptCids; 1870a96aa3bSJed Brown } DM_Forest_pforest; 1880a96aa3bSJed Brown 1890a96aa3bSJed Brown #define DM_Forest_geometry_pforest _append_pforest(DM_Forest_geometry) 1900a96aa3bSJed Brown typedef struct { 1910a96aa3bSJed Brown DM base; 1920a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void*); 1930a96aa3bSJed Brown void *mapCtx; 1940a96aa3bSJed Brown PetscInt coordDim; 1950a96aa3bSJed Brown p4est_geometry_t *inner; 1960a96aa3bSJed Brown } 1970a96aa3bSJed Brown DM_Forest_geometry_pforest; 1980a96aa3bSJed Brown 1990a96aa3bSJed Brown #define GeometryMapping_pforest _append_pforest(GeometryMapping) 2000a96aa3bSJed Brown static void GeometryMapping_pforest(p4est_geometry_t *geom, p4est_topidx_t which_tree, const double abc[3], double xyz[3]) 2010a96aa3bSJed Brown { 2020a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest*)geom->user; 2030a96aa3bSJed Brown PetscReal PetscABC[3] = {0.}; 2040a96aa3bSJed Brown PetscReal PetscXYZ[3] = {0.}; 2050a96aa3bSJed Brown PetscInt i, d = PetscMin(3,geom_pforest->coordDim); 2060a96aa3bSJed Brown double ABC[3]; 2070a96aa3bSJed Brown PetscErrorCode ierr; 2080a96aa3bSJed Brown 2090a96aa3bSJed Brown (geom_pforest->inner->X)(geom_pforest->inner,which_tree,abc,ABC); 2100a96aa3bSJed Brown 2110a96aa3bSJed Brown for (i = 0; i < d; i++) PetscABC[i] = ABC[i]; 2120a96aa3bSJed Brown ierr = (geom_pforest->map)(geom_pforest->base,(PetscInt) which_tree,geom_pforest->coordDim,PetscABC,PetscXYZ,geom_pforest->mapCtx);PETSC_P4EST_ASSERT(!ierr); 2130a96aa3bSJed Brown for (i = 0; i < d; i++) xyz[i] = PetscXYZ[i]; 2140a96aa3bSJed Brown } 2150a96aa3bSJed Brown 2160a96aa3bSJed Brown #define GeometryDestroy_pforest _append_pforest(GeometryDestroy) 2170a96aa3bSJed Brown static void GeometryDestroy_pforest(p4est_geometry_t *geom) 2180a96aa3bSJed Brown { 2190a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest*)geom->user; 2200a96aa3bSJed Brown PetscErrorCode ierr; 2210a96aa3bSJed Brown 2220a96aa3bSJed Brown p4est_geometry_destroy(geom_pforest->inner); 2230a96aa3bSJed Brown ierr = PetscFree(geom->user);PETSC_P4EST_ASSERT(!ierr); 2240a96aa3bSJed Brown ierr = PetscFree(geom);PETSC_P4EST_ASSERT(!ierr); 2250a96aa3bSJed Brown } 2260a96aa3bSJed Brown 2270a96aa3bSJed Brown #define DMFTopologyDestroy_pforest _append_pforest(DMFTopologyDestroy) 2280a96aa3bSJed Brown static PetscErrorCode DMFTopologyDestroy_pforest(DMFTopology_pforest **topo) 2290a96aa3bSJed Brown { 2300a96aa3bSJed Brown PetscFunctionBegin; 2310a96aa3bSJed Brown if (!(*topo)) PetscFunctionReturn(0); 2320a96aa3bSJed Brown if (--((*topo)->refct) > 0) { 2330a96aa3bSJed Brown *topo = NULL; 2340a96aa3bSJed Brown PetscFunctionReturn(0); 2350a96aa3bSJed Brown } 236792fecdfSBarry Smith if ((*topo)->geom) PetscCallP4est(p4est_geometry_destroy,((*topo)->geom)); 237792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy,((*topo)->conn)); 2389566063dSJacob Faibussowitsch PetscCall(PetscFree((*topo)->tree_face_to_uniq)); 2399566063dSJacob Faibussowitsch PetscCall(PetscFree(*topo)); 2400a96aa3bSJed Brown *topo = NULL; 2410a96aa3bSJed Brown PetscFunctionReturn(0); 2420a96aa3bSJed Brown } 2430a96aa3bSJed Brown 2440a96aa3bSJed Brown static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t*,PetscInt**); 2450a96aa3bSJed Brown 2460a96aa3bSJed Brown #define DMFTopologyCreateBrick_pforest _append_pforest(DMFTopologyCreateBrick) 2470a96aa3bSJed Brown static PetscErrorCode DMFTopologyCreateBrick_pforest(DM dm,PetscInt N[], PetscInt P[], PetscReal B[],DMFTopology_pforest **topo, PetscBool useMorton) 2480a96aa3bSJed Brown { 2490a96aa3bSJed Brown double *vertices; 2500a96aa3bSJed Brown PetscInt i, numVerts; 2510a96aa3bSJed Brown 2520a96aa3bSJed Brown PetscFunctionBegin; 25328b400f6SJacob Faibussowitsch PetscCheck(useMorton,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Lexicographic ordering not implemented yet"); 2549566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm,topo)); 2550a96aa3bSJed Brown 2560a96aa3bSJed Brown (*topo)->refct = 1; 2570a96aa3bSJed Brown #if !defined(P4_TO_P8) 258792fecdfSBarry 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)); 2590a96aa3bSJed Brown #else 260792fecdfSBarry 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)); 2610a96aa3bSJed Brown #endif 2620a96aa3bSJed Brown numVerts = (*topo)->conn->num_vertices; 2630a96aa3bSJed Brown vertices = (*topo)->conn->vertices; 2640a96aa3bSJed Brown for (i = 0; i < 3 * numVerts; i++) { 2650a96aa3bSJed Brown PetscInt j = i % 3; 2660a96aa3bSJed Brown 2670a96aa3bSJed Brown vertices[i] = B[2 * j] + (vertices[i]/N[j]) * (B[2 * j + 1] - B[2 * j]); 2680a96aa3bSJed Brown } 2690a96aa3bSJed Brown (*topo)->geom = NULL; 2709566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn,&(*topo)->tree_face_to_uniq)); 2710a96aa3bSJed Brown PetscFunctionReturn(0); 2720a96aa3bSJed Brown } 2730a96aa3bSJed Brown 2740a96aa3bSJed Brown #define DMFTopologyCreate_pforest _append_pforest(DMFTopologyCreate) 2750a96aa3bSJed Brown static PetscErrorCode DMFTopologyCreate_pforest(DM dm, DMForestTopology topologyName, DMFTopology_pforest **topo) 2760a96aa3bSJed Brown { 2770a96aa3bSJed Brown const char *name = (const char*) topologyName; 2780a96aa3bSJed Brown const char *prefix; 2790a96aa3bSJed Brown PetscBool isBrick, isShell, isSphere, isMoebius; 2800a96aa3bSJed Brown 2810a96aa3bSJed Brown PetscFunctionBegin; 2820a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2830a96aa3bSJed Brown PetscValidCharPointer(name,2); 2840a96aa3bSJed Brown PetscValidPointer(topo,3); 2859566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"brick",&isBrick)); 2869566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"shell",&isShell)); 2879566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"sphere",&isSphere)); 2889566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"moebius",&isMoebius)); 2899566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix)); 2900a96aa3bSJed Brown if (isBrick) { 2910a96aa3bSJed Brown PetscBool flgN, flgP, flgM, flgB, useMorton = PETSC_TRUE, periodic = PETSC_FALSE; 2920a96aa3bSJed Brown PetscInt N[3] = {2,2,2}, P[3] = {0,0,0}, nretN = P4EST_DIM, nretP = P4EST_DIM, nretB = 2 * P4EST_DIM, i; 2934fb89dddSMatthew 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}; 2940a96aa3bSJed Brown 2950a96aa3bSJed Brown if (dm->setfromoptionscalled) { 2969566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options,prefix,"-dm_p4est_brick_size",N,&nretN,&flgN)); 2979566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options,prefix,"-dm_p4est_brick_periodicity",P,&nretP,&flgP)); 2989566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(((PetscObject)dm)->options,prefix,"-dm_p4est_brick_bounds",B,&nretB,&flgB)); 2999566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options,prefix,"-dm_p4est_brick_use_morton_curve",&useMorton,&flgM)); 3001dca8a05SBarry 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); 3011dca8a05SBarry 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); 3021dca8a05SBarry 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); 3030a96aa3bSJed Brown } 3040a96aa3bSJed Brown for (i = 0; i < P4EST_DIM; i++) { 3050a96aa3bSJed Brown P[i] = (P[i] ? DM_BOUNDARY_PERIODIC : DM_BOUNDARY_NONE); 3060a96aa3bSJed Brown periodic = (PetscBool)(P[i] || periodic); 3070a96aa3bSJed Brown if (!flgB) B[2 * i + 1] = N[i]; 3086858538eSMatthew G. Knepley if (P[i]) { 3094fb89dddSMatthew G. Knepley Lstart[i] = B[2 * i + 0]; 3104fb89dddSMatthew G. Knepley L[i] = B[2 * i + 1] - B[2 * i + 0]; 3116858538eSMatthew G. Knepley maxCell[i] = 1.1 * (L[i] / N[i]); 3126858538eSMatthew G. Knepley } 3130a96aa3bSJed Brown } 3149566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm,N,P,B,topo,useMorton)); 3154fb89dddSMatthew G. Knepley if (periodic) PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 3160a96aa3bSJed Brown } else { 3179566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm,topo)); 3180a96aa3bSJed Brown 3190a96aa3bSJed Brown (*topo)->refct = 1; 320792fecdfSBarry Smith PetscCallP4estReturn((*topo)->conn,p4est_connectivity_new_byname,(name)); 3210a96aa3bSJed Brown (*topo)->geom = NULL; 3221baa6e33SBarry Smith if (isMoebius) PetscCall(DMSetCoordinateDim(dm,3)); 3230a96aa3bSJed Brown #if defined(P4_TO_P8) 3240a96aa3bSJed Brown if (isShell) { 3250a96aa3bSJed Brown PetscReal R2 = 1., R1 = .55; 3260a96aa3bSJed Brown 3270a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_shell_outer_radius",&R2,NULL)); 3299566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_shell_inner_radius",&R1,NULL)); 3300a96aa3bSJed Brown } 331792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom,p8est_geometry_new_shell,((*topo)->conn,R2,R1)); 3320a96aa3bSJed Brown } else if (isSphere) { 3330a96aa3bSJed Brown PetscReal R2 = 1., R1 = 0.191728, R0 = 0.039856; 3340a96aa3bSJed Brown 3350a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_sphere_outer_radius",&R2,NULL)); 3379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_sphere_inner_radius",&R1,NULL)); 3389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_sphere_core_radius",&R0,NULL)); 3390a96aa3bSJed Brown } 340792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom,p8est_geometry_new_sphere,((*topo)->conn,R2,R1,R0)); 3410a96aa3bSJed Brown } 3420a96aa3bSJed Brown #endif 3439566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn,&(*topo)->tree_face_to_uniq)); 3440a96aa3bSJed Brown } 3450a96aa3bSJed Brown PetscFunctionReturn(0); 3460a96aa3bSJed Brown } 3470a96aa3bSJed Brown 3480a96aa3bSJed Brown #define DMConvert_plex_pforest _append_pforest(DMConvert_plex) 3490a96aa3bSJed Brown static PetscErrorCode DMConvert_plex_pforest(DM dm, DMType newtype, DM *pforest) 3500a96aa3bSJed Brown { 3510a96aa3bSJed Brown MPI_Comm comm; 3520a96aa3bSJed Brown PetscBool isPlex; 3530a96aa3bSJed Brown PetscInt dim; 3540a96aa3bSJed Brown void *ctx; 3550a96aa3bSJed Brown 3560a96aa3bSJed Brown PetscFunctionBegin; 3570a96aa3bSJed Brown 3580a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3590a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 3609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isPlex)); 36128b400f6SJacob Faibussowitsch PetscCheck(isPlex,comm,PETSC_ERR_ARG_WRONG,"Expected DM type %s, got %s",DMPLEX,((PetscObject)dm)->type_name); 3629566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm,&dim)); 36363a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM,comm,PETSC_ERR_ARG_WRONG,"Expected DM dimension %d, got %" PetscInt_FMT,P4EST_DIM,dim); 3649566063dSJacob Faibussowitsch PetscCall(DMCreate(comm,pforest)); 3659566063dSJacob Faibussowitsch PetscCall(DMSetType(*pforest,DMPFOREST)); 3669566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(*pforest,dm)); 3679566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dm,&ctx)); 3689566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(*pforest,ctx)); 3699566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm,*pforest)); 3700a96aa3bSJed Brown PetscFunctionReturn(0); 3710a96aa3bSJed Brown } 3720a96aa3bSJed Brown 3730a96aa3bSJed Brown #define DMForestDestroy_pforest _append_pforest(DMForestDestroy) 3740a96aa3bSJed Brown static PetscErrorCode DMForestDestroy_pforest(DM dm) 3750a96aa3bSJed Brown { 3760a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 3770a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 3780a96aa3bSJed Brown 3790a96aa3bSJed Brown PetscFunctionBegin; 3800a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 381792fecdfSBarry Smith if (pforest->lnodes) PetscCallP4est(p4est_lnodes_destroy,(pforest->lnodes)); 3820a96aa3bSJed Brown pforest->lnodes = NULL; 383792fecdfSBarry Smith if (pforest->ghost) PetscCallP4est(p4est_ghost_destroy,(pforest->ghost)); 3840a96aa3bSJed Brown pforest->ghost = NULL; 385792fecdfSBarry Smith if (pforest->forest) PetscCallP4est(p4est_destroy,(pforest->forest)); 3860a96aa3bSJed Brown pforest->forest = NULL; 3879566063dSJacob Faibussowitsch PetscCall(DMFTopologyDestroy_pforest(&pforest->topo)); 3889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_plex_pforest) "_C",NULL)); 3899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_pforest_plex) "_C",NULL)); 3902e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL)); 3919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",NULL)); 3922e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",NULL)); 3932e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",NULL)); 3949566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName)); 3959566063dSJacob Faibussowitsch PetscCall(DMDestroy(&pforest->plex)); 3969566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointAdaptToSelfSF)); 3979566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointSelfToAdaptSF)); 3989566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 3999566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 4009566063dSJacob Faibussowitsch PetscCall(PetscFree(forest->data)); 4010a96aa3bSJed Brown PetscFunctionReturn(0); 4020a96aa3bSJed Brown } 4030a96aa3bSJed Brown 4040a96aa3bSJed Brown #define DMForestTemplate_pforest _append_pforest(DMForestTemplate) 4050a96aa3bSJed Brown static PetscErrorCode DMForestTemplate_pforest(DM dm, DM tdm) 4060a96aa3bSJed Brown { 4070a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 4080a96aa3bSJed Brown DM_Forest_pforest *tpforest = (DM_Forest_pforest*) ((DM_Forest*) tdm->data)->data; 4090a96aa3bSJed Brown 4100a96aa3bSJed Brown PetscFunctionBegin; 4110a96aa3bSJed Brown if (pforest->topo) pforest->topo->refct++; 4129566063dSJacob Faibussowitsch PetscCall(DMFTopologyDestroy_pforest(&(tpforest->topo))); 4130a96aa3bSJed Brown tpforest->topo = pforest->topo; 4140a96aa3bSJed Brown PetscFunctionReturn(0); 4150a96aa3bSJed Brown } 4160a96aa3bSJed Brown 4170a96aa3bSJed Brown #define DMPlexCreateConnectivity_pforest _append_pforest(DMPlexCreateConnectivity) 4180a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM,p4est_connectivity_t**,PetscInt**); 4190a96aa3bSJed Brown 4200a96aa3bSJed Brown typedef struct _PforestAdaptCtx 4210a96aa3bSJed Brown { 4220a96aa3bSJed Brown PetscInt maxLevel; 4230a96aa3bSJed Brown PetscInt minLevel; 4240a96aa3bSJed Brown PetscInt currLevel; 4250a96aa3bSJed Brown PetscBool anyChange; 4260a96aa3bSJed Brown } 4270a96aa3bSJed Brown PforestAdaptCtx; 4280a96aa3bSJed Brown 4290a96aa3bSJed Brown static int pforest_coarsen_currlevel(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 4300a96aa3bSJed Brown { 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 4390a96aa3bSJed Brown static int pforest_coarsen_uniform(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 4400a96aa3bSJed Brown { 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 4470a96aa3bSJed Brown static int pforest_coarsen_flag_any(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 4480a96aa3bSJed Brown { 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 4680a96aa3bSJed Brown static int pforest_coarsen_flag_all(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 4690a96aa3bSJed Brown { 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 4850a96aa3bSJed Brown static void pforest_init_determine(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 4860a96aa3bSJed Brown { 4870a96aa3bSJed Brown quadrant->p.user_int = DM_ADAPT_DETERMINE; 4880a96aa3bSJed Brown } 4890a96aa3bSJed Brown 4900a96aa3bSJed Brown static int pforest_refine_uniform(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 4910a96aa3bSJed Brown { 4920a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 4930a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 4940a96aa3bSJed Brown 4950a96aa3bSJed Brown return ((PetscInt) quadrant->level < maxLevel); 4960a96aa3bSJed Brown } 4970a96aa3bSJed Brown 4980a96aa3bSJed Brown static int pforest_refine_flag(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 4990a96aa3bSJed Brown { 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 5050a96aa3bSJed Brown return (quadrant->p.user_int == DM_ADAPT_REFINE); 5060a96aa3bSJed Brown } 5070a96aa3bSJed Brown 5080a96aa3bSJed Brown 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) 5090a96aa3bSJed Brown { 5100a96aa3bSJed Brown PetscMPIInt rank = p4estFrom->mpirank; 5110a96aa3bSJed Brown p4est_topidx_t t; 5120a96aa3bSJed Brown PetscInt toFineLeaves = 0, fromFineLeaves = 0; 5130a96aa3bSJed Brown 5140a96aa3bSJed Brown PetscFunctionBegin; 5150a96aa3bSJed Brown for (t = flt; t <= llt; t++) { /* count roots and leaves */ 5160a96aa3bSJed Brown p4est_tree_t *treeFrom = &(((p4est_tree_t*) p4estFrom->trees->array)[t]); 5170a96aa3bSJed Brown p4est_tree_t *treeTo = &(((p4est_tree_t*) p4estTo->trees->array)[t]); 5180a96aa3bSJed Brown p4est_quadrant_t *firstFrom = &treeFrom->first_desc; 5190a96aa3bSJed Brown p4est_quadrant_t *firstTo = &treeTo->first_desc; 5200a96aa3bSJed Brown PetscInt numFrom = (PetscInt) treeFrom->quadrants.elem_count; 5210a96aa3bSJed Brown PetscInt numTo = (PetscInt) treeTo->quadrants.elem_count; 5220a96aa3bSJed Brown p4est_quadrant_t *quadsFrom = (p4est_quadrant_t*) treeFrom->quadrants.array; 5230a96aa3bSJed Brown p4est_quadrant_t *quadsTo = (p4est_quadrant_t*) treeTo->quadrants.array; 5240a96aa3bSJed Brown PetscInt currentFrom, currentTo; 5250a96aa3bSJed Brown PetscInt treeOffsetFrom = (PetscInt) treeFrom->quadrants_offset; 5260a96aa3bSJed Brown PetscInt treeOffsetTo = (PetscInt) treeTo->quadrants_offset; 5270a96aa3bSJed Brown int comp; 5280a96aa3bSJed Brown 529792fecdfSBarry Smith PetscCallP4estReturn(comp,p4est_quadrant_is_equal,(firstFrom,firstTo)); 53028b400f6SJacob Faibussowitsch PetscCheck(comp,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"non-matching partitions"); 5310a96aa3bSJed Brown 5320a96aa3bSJed Brown for (currentFrom = 0, currentTo = 0; currentFrom < numFrom && currentTo < numTo;) { 5330a96aa3bSJed Brown p4est_quadrant_t *quadFrom = &quadsFrom[currentFrom]; 5340a96aa3bSJed Brown p4est_quadrant_t *quadTo = &quadsTo[currentTo]; 5350a96aa3bSJed Brown 5360a96aa3bSJed Brown if (quadFrom->level == quadTo->level) { 5370a96aa3bSJed Brown if (toLeaves) { 5380a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5390a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5400a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5410a96aa3bSJed Brown } 5420a96aa3bSJed Brown toFineLeaves++; 5430a96aa3bSJed Brown currentFrom++; 5440a96aa3bSJed Brown currentTo++; 5450a96aa3bSJed Brown } else { 5460a96aa3bSJed Brown int fromIsAncestor; 5470a96aa3bSJed Brown 548792fecdfSBarry Smith PetscCallP4estReturn(fromIsAncestor,p4est_quadrant_is_ancestor,(quadFrom,quadTo)); 5490a96aa3bSJed Brown if (fromIsAncestor) { 5500a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5510a96aa3bSJed Brown 5520a96aa3bSJed Brown if (toLeaves) { 5530a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5540a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5550a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5560a96aa3bSJed Brown } 5570a96aa3bSJed Brown toFineLeaves++; 5580a96aa3bSJed Brown currentTo++; 559792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant,(quadFrom,&lastDesc,quadTo->level)); 560792fecdfSBarry Smith PetscCallP4estReturn(comp,p4est_quadrant_is_equal,(quadTo,&lastDesc)); 5610a96aa3bSJed Brown if (comp) currentFrom++; 5620a96aa3bSJed Brown } else { 5630a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5640a96aa3bSJed Brown 5650a96aa3bSJed Brown if (fromLeaves) { 5660a96aa3bSJed Brown fromLeaves[fromFineLeaves] = currentFrom + treeOffsetFrom + FromOffset; 5670a96aa3bSJed Brown toRoots[fromFineLeaves].rank = rank; 5680a96aa3bSJed Brown toRoots[fromFineLeaves].index = currentTo + treeOffsetTo + ToOffset; 5690a96aa3bSJed Brown } 5700a96aa3bSJed Brown fromFineLeaves++; 5710a96aa3bSJed Brown currentFrom++; 572792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant,(quadTo,&lastDesc,quadFrom->level)); 573792fecdfSBarry Smith PetscCallP4estReturn(comp,p4est_quadrant_is_equal,(quadFrom,&lastDesc)); 5740a96aa3bSJed Brown if (comp) currentTo++; 5750a96aa3bSJed Brown } 5760a96aa3bSJed Brown } 5770a96aa3bSJed Brown } 5780a96aa3bSJed Brown } 5790a96aa3bSJed Brown *toFineLeavesCount = toFineLeaves; 5800a96aa3bSJed Brown *fromFineLeavesCount = fromFineLeaves; 5810a96aa3bSJed Brown PetscFunctionReturn(0); 5820a96aa3bSJed Brown } 5830a96aa3bSJed Brown 5840a96aa3bSJed Brown /* Compute the maximum level across all the trees */ 5850a96aa3bSJed Brown static PetscErrorCode DMPforestGetRefinementLevel(DM dm, PetscInt *lev) 5860a96aa3bSJed Brown { 5870a96aa3bSJed Brown p4est_topidx_t t, flt, llt; 5880a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 5890a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 5900a96aa3bSJed Brown PetscInt maxlevelloc = 0; 5910a96aa3bSJed Brown p4est_t *p4est; 5920a96aa3bSJed Brown 5930a96aa3bSJed Brown PetscFunctionBegin; 59428b400f6SJacob Faibussowitsch PetscCheck(pforest,PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Missing DM_Forest_pforest"); 59528b400f6SJacob Faibussowitsch PetscCheck(pforest->forest,PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Missing p4est_t"); 5960a96aa3bSJed Brown p4est = pforest->forest; 5970a96aa3bSJed Brown flt = p4est->first_local_tree; 5980a96aa3bSJed Brown llt = p4est->last_local_tree; 5990a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 6000a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4est->trees->array)[t]); 6010a96aa3bSJed Brown maxlevelloc = PetscMax((PetscInt)tree->maxlevel,maxlevelloc); 6020a96aa3bSJed Brown } 6031c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&maxlevelloc,lev,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm))); 6040a96aa3bSJed Brown PetscFunctionReturn(0); 6050a96aa3bSJed Brown } 6060a96aa3bSJed Brown 6070a96aa3bSJed Brown /* Puts identity in coarseToFine */ 6080a96aa3bSJed Brown /* assumes a matching partition */ 6090a96aa3bSJed Brown static PetscErrorCode DMPforestComputeLocalCellTransferSF(MPI_Comm comm, p4est_t *p4estFrom, PetscInt FromOffset, p4est_t *p4estTo, PetscInt ToOffset, PetscSF *fromCoarseToFine, PetscSF *toCoarseFromFine) 6100a96aa3bSJed Brown { 6110a96aa3bSJed Brown p4est_topidx_t flt, llt; 6120a96aa3bSJed Brown PetscSF fromCoarse, toCoarse; 6130a96aa3bSJed Brown PetscInt numRootsFrom, numRootsTo, numLeavesFrom, numLeavesTo; 6140a96aa3bSJed Brown PetscInt *fromLeaves = NULL, *toLeaves = NULL; 6150a96aa3bSJed Brown PetscSFNode *fromRoots = NULL, *toRoots = NULL; 6160a96aa3bSJed Brown 6170a96aa3bSJed Brown PetscFunctionBegin; 6180a96aa3bSJed Brown flt = p4estFrom->first_local_tree; 6190a96aa3bSJed Brown llt = p4estFrom->last_local_tree; 6209566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&fromCoarse)); 6210a96aa3bSJed Brown if (toCoarseFromFine) { 6229566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&toCoarse)); 6230a96aa3bSJed Brown } 6240a96aa3bSJed Brown numRootsFrom = p4estFrom->local_num_quadrants + FromOffset; 6250a96aa3bSJed Brown numRootsTo = p4estTo->local_num_quadrants + ToOffset; 6269566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom,FromOffset,p4estTo,ToOffset,flt,llt,&numLeavesTo,NULL,NULL,&numLeavesFrom,NULL,NULL)); 6279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo,&toLeaves)); 6289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo,&fromRoots)); 6290a96aa3bSJed Brown if (toCoarseFromFine) { 6309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom,&fromLeaves)); 6319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom,&fromRoots)); 6320a96aa3bSJed Brown } 6339566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom,FromOffset,p4estTo,ToOffset,flt,llt,&numLeavesTo,toLeaves,fromRoots,&numLeavesFrom,fromLeaves,toRoots)); 6340a96aa3bSJed Brown if (!ToOffset && (numLeavesTo == numRootsTo)) { /* compress */ 6359566063dSJacob Faibussowitsch PetscCall(PetscFree(toLeaves)); 6369566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(fromCoarse,numRootsFrom,numLeavesTo,NULL,PETSC_OWN_POINTER,fromRoots,PETSC_OWN_POINTER)); 6371baa6e33SBarry Smith } else PetscCall(PetscSFSetGraph(fromCoarse,numRootsFrom,numLeavesTo,toLeaves,PETSC_OWN_POINTER,fromRoots,PETSC_OWN_POINTER)); 6380a96aa3bSJed Brown *fromCoarseToFine = fromCoarse; 6390a96aa3bSJed Brown if (toCoarseFromFine) { 6409566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(toCoarse,numRootsTo,numLeavesFrom,fromLeaves,PETSC_OWN_POINTER,toRoots,PETSC_OWN_POINTER)); 6410a96aa3bSJed Brown *toCoarseFromFine = toCoarse; 6420a96aa3bSJed Brown } 6430a96aa3bSJed Brown PetscFunctionReturn(0); 6440a96aa3bSJed Brown } 6450a96aa3bSJed Brown 6460a96aa3bSJed Brown /* range of processes whose B sections overlap this ranks A section */ 6470a96aa3bSJed Brown static PetscErrorCode DMPforestComputeOverlappingRanks(PetscMPIInt size, PetscMPIInt rank, p4est_t *p4estA, p4est_t *p4estB, PetscInt *startB, PetscInt *endB) 6480a96aa3bSJed Brown { 6490a96aa3bSJed Brown p4est_quadrant_t * myCoarseStart = &(p4estA->global_first_position[rank]); 6500a96aa3bSJed Brown p4est_quadrant_t * myCoarseEnd = &(p4estA->global_first_position[rank+1]); 6510a96aa3bSJed Brown p4est_quadrant_t * globalFirstB = p4estB->global_first_position; 6520a96aa3bSJed Brown 6530a96aa3bSJed Brown PetscFunctionBegin; 6540a96aa3bSJed Brown *startB = -1; 6550a96aa3bSJed Brown *endB = -1; 6560a96aa3bSJed Brown if (p4estA->local_num_quadrants) { 6570a96aa3bSJed Brown PetscInt lo, hi, guess; 6580a96aa3bSJed Brown /* binary search to find interval containing myCoarseStart */ 6590a96aa3bSJed Brown lo = 0; 6600a96aa3bSJed Brown hi = size; 6610a96aa3bSJed Brown guess = rank; 6620a96aa3bSJed Brown while (1) { 6630a96aa3bSJed Brown int startCompMy, myCompEnd; 6640a96aa3bSJed Brown 665792fecdfSBarry Smith PetscCallP4estReturn(startCompMy,p4est_quadrant_compare_piggy,(&globalFirstB[guess],myCoarseStart)); 666792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd,p4est_quadrant_compare_piggy,(myCoarseStart,&globalFirstB[guess+1])); 6670a96aa3bSJed Brown if (startCompMy <= 0 && myCompEnd < 0) { 6680a96aa3bSJed Brown *startB = guess; 6690a96aa3bSJed Brown break; 6700a96aa3bSJed Brown } else if (startCompMy > 0) { /* guess is to high */ 6710a96aa3bSJed Brown hi = guess; 6720a96aa3bSJed Brown } else { /* guess is to low */ 6730a96aa3bSJed Brown lo = guess + 1; 6740a96aa3bSJed Brown } 6750a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6760a96aa3bSJed Brown } 6770a96aa3bSJed Brown /* reset bounds, but not guess */ 6780a96aa3bSJed Brown lo = 0; 6790a96aa3bSJed Brown hi = size; 6800a96aa3bSJed Brown while (1) { 6810a96aa3bSJed Brown int startCompMy, myCompEnd; 6820a96aa3bSJed Brown 683792fecdfSBarry Smith PetscCallP4estReturn(startCompMy,p4est_quadrant_compare_piggy,(&globalFirstB[guess],myCoarseEnd)); 684792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd,p4est_quadrant_compare_piggy,(myCoarseEnd,&globalFirstB[guess+1])); 6850a96aa3bSJed Brown if (startCompMy < 0 && myCompEnd <= 0) { /* notice that the comparison operators are different from above */ 6860a96aa3bSJed Brown *endB = guess + 1; 6870a96aa3bSJed Brown break; 6880a96aa3bSJed Brown } else if (startCompMy >= 0) { /* guess is to high */ 6890a96aa3bSJed Brown hi = guess; 6900a96aa3bSJed Brown } else { /* guess is to low */ 6910a96aa3bSJed Brown lo = guess + 1; 6920a96aa3bSJed Brown } 6930a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6940a96aa3bSJed Brown } 6950a96aa3bSJed Brown } 6960a96aa3bSJed Brown PetscFunctionReturn(0); 6970a96aa3bSJed Brown } 6980a96aa3bSJed Brown 6990a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM,DM*); 7000a96aa3bSJed Brown 7010a96aa3bSJed Brown #define DMSetUp_pforest _append_pforest(DMSetUp) 7020a96aa3bSJed Brown static PetscErrorCode DMSetUp_pforest(DM dm) 7030a96aa3bSJed Brown { 7040a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 7050a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 7060a96aa3bSJed Brown DM base, adaptFrom; 7070a96aa3bSJed Brown DMForestTopology topoName; 7080a96aa3bSJed Brown PetscSF preCoarseToFine = NULL, coarseToPreFine = NULL; 7090a96aa3bSJed Brown PforestAdaptCtx ctx; 7100a96aa3bSJed Brown 7110a96aa3bSJed Brown PetscFunctionBegin; 7120a96aa3bSJed Brown ctx.minLevel = PETSC_MAX_INT; 7130a96aa3bSJed Brown ctx.maxLevel = 0; 7140a96aa3bSJed Brown ctx.currLevel = 0; 7150a96aa3bSJed Brown ctx.anyChange = PETSC_FALSE; 7160a96aa3bSJed Brown /* sanity check */ 7179566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm,&adaptFrom)); 7189566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 7199566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm,&topoName)); 7201dca8a05SBarry 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"); 7210a96aa3bSJed Brown 7220a96aa3bSJed Brown /* === Step 1: DMFTopology === */ 7230a96aa3bSJed Brown if (adaptFrom) { /* reference already created topology */ 7240a96aa3bSJed Brown PetscBool ispforest; 7250a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest*) adaptFrom->data; 7260a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest*) aforest->data; 7270a96aa3bSJed Brown 7289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)adaptFrom,DMPFOREST,&ispforest)); 72928b400f6SJacob Faibussowitsch PetscCheck(ispforest,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_NOTSAMETYPE,"Trying to adapt from %s, which is not %s",((PetscObject)adaptFrom)->type_name,DMPFOREST); 73028b400f6SJacob Faibussowitsch PetscCheck(apforest->topo,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"The pre-adaptation forest must have a topology"); 7319566063dSJacob Faibussowitsch PetscCall(DMSetUp(adaptFrom)); 7329566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 7339566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm,&topoName)); 7340a96aa3bSJed Brown } else if (base) { /* construct a connectivity from base */ 7350a96aa3bSJed Brown PetscBool isPlex, isDA; 7360a96aa3bSJed Brown 7379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)base,&topoName)); 7389566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm,topoName)); 7399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base,DMPLEX,&isPlex)); 7409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base,DMDA,&isDA)); 7410a96aa3bSJed Brown if (isPlex) { 7420a96aa3bSJed Brown MPI_Comm comm = PetscObjectComm((PetscObject)dm); 7430a96aa3bSJed Brown PetscInt depth; 7440a96aa3bSJed Brown PetscMPIInt size; 7450a96aa3bSJed Brown p4est_connectivity_t *conn = NULL; 7460a96aa3bSJed Brown DMFTopology_pforest *topo; 7470a96aa3bSJed Brown PetscInt *tree_face_to_uniq = NULL; 7480a96aa3bSJed Brown 7499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(base,&depth)); 7500a96aa3bSJed Brown if (depth == 1) { 7510a96aa3bSJed Brown DM connDM; 7520a96aa3bSJed Brown 7539566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(base,&connDM)); 7540a96aa3bSJed Brown base = connDM; 7559566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm,base)); 7569566063dSJacob Faibussowitsch PetscCall(DMDestroy(&connDM)); 75763a3b9bcSJacob 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); 7589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 7590a96aa3bSJed Brown if (size > 1) { 7600a96aa3bSJed Brown DM dmRedundant; 7610a96aa3bSJed Brown PetscSF sf; 7620a96aa3bSJed Brown 7639566063dSJacob Faibussowitsch PetscCall(DMPlexGetRedundantDM(base,&sf,&dmRedundant)); 76428b400f6SJacob Faibussowitsch PetscCheck(dmRedundant,comm,PETSC_ERR_PLIB,"Could not create redundant DM"); 7659566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dmRedundant,"_base_migration_sf",(PetscObject)sf)); 7669566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 7670a96aa3bSJed Brown base = dmRedundant; 7689566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm,base)); 7699566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRedundant)); 7700a96aa3bSJed Brown } 7719566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(base,NULL,"-dm_p4est_base_view")); 7729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConnectivity_pforest(base,&conn,&tree_face_to_uniq)); 7739566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm,&topo)); 7740a96aa3bSJed Brown topo->refct = 1; 7750a96aa3bSJed Brown topo->conn = conn; 7760a96aa3bSJed Brown topo->geom = NULL; 7770a96aa3bSJed Brown { 7780a96aa3bSJed Brown PetscErrorCode (*map)(DM,PetscInt,PetscInt,const PetscReal[],PetscReal[],void*); 7790a96aa3bSJed Brown void *mapCtx; 7800a96aa3bSJed Brown 7819566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx)); 7820a96aa3bSJed Brown if (map) { 7830a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest; 7840a96aa3bSJed Brown p4est_geometry_t *geom; 7850a96aa3bSJed Brown 7869566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom_pforest)); 7879566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm,&geom_pforest->coordDim)); 7880a96aa3bSJed Brown geom_pforest->map = map; 7890a96aa3bSJed Brown geom_pforest->mapCtx = mapCtx; 790792fecdfSBarry Smith PetscCallP4estReturn(geom_pforest->inner,p4est_geometry_new_connectivity,(conn)); 7919566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom)); 7920a96aa3bSJed Brown geom->name = topoName; 7930a96aa3bSJed Brown geom->user = geom_pforest; 7940a96aa3bSJed Brown geom->X = GeometryMapping_pforest; 7950a96aa3bSJed Brown geom->destroy = GeometryDestroy_pforest; 7960a96aa3bSJed Brown topo->geom = geom; 7970a96aa3bSJed Brown } 7980a96aa3bSJed Brown } 7990a96aa3bSJed Brown topo->tree_face_to_uniq = tree_face_to_uniq; 8000a96aa3bSJed Brown pforest->topo = topo; 80128b400f6SJacob Faibussowitsch } else PetscCheck(!isDA,PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Not implemented yet"); 8020a96aa3bSJed Brown #if 0 8030a96aa3bSJed Brown PetscInt N[3], P[3]; 8040a96aa3bSJed Brown 8050a96aa3bSJed Brown /* get the sizes, periodicities */ 8060a96aa3bSJed Brown /* ... */ 8070a96aa3bSJed Brown /* don't use Morton order */ 8089566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm,N,P,&pforest->topo,PETSC_FALSE)); 8090a96aa3bSJed Brown #endif 8100a96aa3bSJed Brown { 8110a96aa3bSJed Brown PetscInt numLabels, l; 8120a96aa3bSJed Brown 8139566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(base,&numLabels)); 8140a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 8150a96aa3bSJed Brown PetscBool isDepth, isGhost, isVTK, isDim, isCellType; 8160a96aa3bSJed Brown DMLabel label, labelNew; 8170a96aa3bSJed Brown PetscInt defVal; 8180a96aa3bSJed Brown const char *name; 8190a96aa3bSJed Brown 8209566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(base, l, &name)); 8219566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(base, l, &label)); 8229566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"depth",&isDepth)); 8230a96aa3bSJed Brown if (isDepth) continue; 8249566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"dim",&isDim)); 8250a96aa3bSJed Brown if (isDim) continue; 8269566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"celltype",&isCellType)); 8270a96aa3bSJed Brown if (isCellType) continue; 8289566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"ghost",&isGhost)); 8290a96aa3bSJed Brown if (isGhost) continue; 8309566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"vtk",&isVTK)); 8310a96aa3bSJed Brown if (isVTK) continue; 8329566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm,name)); 8339566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm,name,&labelNew)); 8349566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label,&defVal)); 8359566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew,defVal)); 8360a96aa3bSJed Brown } 8370a96aa3bSJed Brown /* map dm points (internal plex) to base 8380a96aa3bSJed Brown we currently create the subpoint_map for the entire hierarchy, starting from the finest forest 8390a96aa3bSJed Brown and propagating back to the coarsest 8400a96aa3bSJed Brown This is not an optimal approach, since we need the map only on the coarsest level 8410a96aa3bSJed Brown during DMForestTransferVecFromBase */ 8429566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&l)); 8430a96aa3bSJed Brown if (!l) { 8449566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm,"_forest_base_subpoint_map")); 8450a96aa3bSJed Brown } 8460a96aa3bSJed Brown } 8470a96aa3bSJed Brown } else { /* construct from topology name */ 8480a96aa3bSJed Brown DMFTopology_pforest *topo; 8490a96aa3bSJed Brown 8509566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreate_pforest(dm,topoName,&topo)); 8510a96aa3bSJed Brown pforest->topo = topo; 8520a96aa3bSJed Brown /* TODO: construct base? */ 8530a96aa3bSJed Brown } 8540a96aa3bSJed Brown 8550a96aa3bSJed Brown /* === Step 2: get the leaves of the forest === */ 8560a96aa3bSJed Brown if (adaptFrom) { /* start with the old forest */ 8570a96aa3bSJed Brown DMLabel adaptLabel; 8580a96aa3bSJed Brown PetscInt defaultValue; 8590a96aa3bSJed Brown PetscInt numValues, numValuesGlobal, cLocalStart, count; 8600a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest*) adaptFrom->data; 8610a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest*) aforest->data; 8620a96aa3bSJed Brown PetscBool computeAdaptSF; 8630a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 8640a96aa3bSJed Brown 8650a96aa3bSJed Brown flt = apforest->forest->first_local_tree; 8660a96aa3bSJed Brown llt = apforest->forest->last_local_tree; 8670a96aa3bSJed Brown cLocalStart = apforest->cLocalStart; 8689566063dSJacob Faibussowitsch PetscCall(DMForestGetComputeAdaptivitySF(dm,&computeAdaptSF)); 869792fecdfSBarry Smith PetscCallP4estReturn(pforest->forest,p4est_copy,(apforest->forest, 0)); /* 0 indicates no data copying */ 8709566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm,&adaptLabel)); 8710a96aa3bSJed Brown if (adaptLabel) { 8720a96aa3bSJed Brown /* apply the refinement/coarsening by flags, plus minimum/maximum refinement */ 8739566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(adaptLabel,&numValues)); 8749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&numValues,&numValuesGlobal,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)adaptFrom))); 8759566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(adaptLabel,&defaultValue)); 8760a96aa3bSJed Brown if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN_LAST) { /* uniform coarsen of the last level only (equivalent to DM_ADAPT_COARSEN for conforming grids) */ 8779566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&ctx.minLevel)); 8789566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm,&ctx.currLevel)); 8790a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 880792fecdfSBarry Smith PetscCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_currlevel,NULL)); 8810a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 882792fecdfSBarry Smith PetscCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 8830a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 8840a96aa3bSJed Brown if (computeAdaptSF) { 8859566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),pforest->forest,0,apforest->forest,apforest->cLocalStart,&coarseToPreFine,NULL)); 8860a96aa3bSJed Brown } 8870a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN) { /* uniform coarsen */ 8889566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&ctx.minLevel)); 8890a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 890792fecdfSBarry Smith PetscCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_uniform,NULL)); 8910a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 892792fecdfSBarry Smith PetscCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 8930a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 8940a96aa3bSJed Brown if (computeAdaptSF) { 8959566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),pforest->forest,0,apforest->forest,apforest->cLocalStart,&coarseToPreFine,NULL)); 8960a96aa3bSJed Brown } 8970a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_REFINE) { /* uniform refine */ 8989566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm,&ctx.maxLevel)); 8990a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 900792fecdfSBarry Smith PetscCallP4est(p4est_refine,(pforest->forest,0,pforest_refine_uniform,NULL)); 9010a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 902792fecdfSBarry Smith PetscCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 9030a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 9040a96aa3bSJed Brown if (computeAdaptSF) { 9059566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),apforest->forest,apforest->cLocalStart,pforest->forest,0,&preCoarseToFine,NULL)); 9060a96aa3bSJed Brown } 9070a96aa3bSJed Brown } else if (numValuesGlobal) { 9080a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 9090a96aa3bSJed Brown PetscInt *cellFlags; 9100a96aa3bSJed Brown DMForestAdaptivityStrategy strategy; 9110a96aa3bSJed Brown PetscSF cellSF; 9120a96aa3bSJed Brown PetscInt c, cStart, cEnd; 9130a96aa3bSJed Brown PetscBool adaptAny; 9140a96aa3bSJed Brown 9159566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm,&ctx.maxLevel)); 9169566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&ctx.minLevel)); 9179566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityStrategy(dm,&strategy)); 9189566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(strategy,"any",3,&adaptAny)); 9199566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(adaptFrom,&cStart,&cEnd)); 9209566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(adaptFrom,&cellSF)); 9219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd-cStart,&cellFlags)); 9229566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; c++) PetscCall(DMLabelGetValue(adaptLabel,c,&cellFlags[c-cStart])); 9230a96aa3bSJed Brown if (cellSF) { 9240a96aa3bSJed Brown if (adaptAny) { 9259566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MAX)); 9269566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MAX)); 9270a96aa3bSJed Brown } else { 9289566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MIN)); 9299566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MIN)); 9300a96aa3bSJed Brown } 9310a96aa3bSJed Brown } 9320a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9330a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4est->trees->array)[t]); 9340a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count, i; 9350a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 9360a96aa3bSJed Brown 9370a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9380a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9390a96aa3bSJed Brown q->p.user_int = cellFlags[count++]; 9400a96aa3bSJed Brown } 9410a96aa3bSJed Brown } 9429566063dSJacob Faibussowitsch PetscCall(PetscFree(cellFlags)); 9430a96aa3bSJed Brown 9440a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 945792fecdfSBarry Smith if (adaptAny) PetscCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_flag_any,pforest_init_determine)); 946792fecdfSBarry Smith else PetscCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_flag_all,pforest_init_determine)); 947792fecdfSBarry Smith PetscCallP4est(p4est_refine,(pforest->forest,0,pforest_refine_flag,NULL)); 9480a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 949792fecdfSBarry Smith PetscCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 9500a96aa3bSJed Brown if (computeAdaptSF) { 9519566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),apforest->forest,apforest->cLocalStart,pforest->forest,0,&preCoarseToFine,&coarseToPreFine)); 9520a96aa3bSJed Brown } 9530a96aa3bSJed Brown } 9540a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9550a96aa3bSJed Brown p4est_tree_t *atree = &(((p4est_tree_t*) apforest->forest->trees->array)[t]); 9560a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) pforest->forest->trees->array)[t]); 9570a96aa3bSJed Brown PetscInt anumQuads = (PetscInt) atree->quadrants.elem_count, i; 9580a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 9590a96aa3bSJed Brown p4est_quadrant_t *aquads = (p4est_quadrant_t *) atree->quadrants.array; 9600a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 9610a96aa3bSJed Brown 9620a96aa3bSJed Brown if (anumQuads != numQuads) { 9630a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9640a96aa3bSJed Brown } else { 9650a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9660a96aa3bSJed Brown p4est_quadrant_t *aq = &aquads[i]; 9670a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9680a96aa3bSJed Brown 9690a96aa3bSJed Brown if (aq->level != q->level) { 9700a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9710a96aa3bSJed Brown break; 9720a96aa3bSJed Brown } 9730a96aa3bSJed Brown } 9740a96aa3bSJed Brown } 9750a96aa3bSJed Brown if (ctx.anyChange) { 9760a96aa3bSJed Brown break; 9770a96aa3bSJed Brown } 9780a96aa3bSJed Brown } 9790a96aa3bSJed Brown } 9800a96aa3bSJed Brown { 9810a96aa3bSJed Brown PetscInt numLabels, l; 9820a96aa3bSJed Brown 9839566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(adaptFrom,&numLabels)); 9840a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 9850a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 9860a96aa3bSJed Brown DMLabel label, labelNew; 9870a96aa3bSJed Brown PetscInt defVal; 9880a96aa3bSJed Brown const char *name; 9890a96aa3bSJed Brown 9909566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(adaptFrom, l, &name)); 9919566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(adaptFrom, l, &label)); 9929566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"depth",&isDepth)); 9930a96aa3bSJed Brown if (isDepth) continue; 9949566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"celltype",&isCellType)); 9950a96aa3bSJed Brown if (isCellType) continue; 9969566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"ghost",&isGhost)); 9970a96aa3bSJed Brown if (isGhost) continue; 9989566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"vtk",&isVTK)); 9990a96aa3bSJed Brown if (isVTK) continue; 10009566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm,name)); 10019566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm,name,&labelNew)); 10029566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label,&defVal)); 10039566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew,defVal)); 10040a96aa3bSJed Brown } 10050a96aa3bSJed Brown } 10060a96aa3bSJed Brown } else { /* initial */ 10070a96aa3bSJed Brown PetscInt initLevel, minLevel; 100866c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI) 100966c0a4b5SToby Isaac sc_MPI_Comm comm = sc_MPI_COMM_WORLD; 101066c0a4b5SToby Isaac #else 101166c0a4b5SToby Isaac MPI_Comm comm = PetscObjectComm((PetscObject)dm); 101266c0a4b5SToby Isaac #endif 10130a96aa3bSJed Brown 10149566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm,&initLevel)); 10159566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&minLevel)); 1016792fecdfSBarry Smith PetscCallP4estReturn(pforest->forest,p4est_new_ext,(comm,pforest->topo->conn, 10170a96aa3bSJed Brown 0, /* minimum number of quadrants per processor */ 10180a96aa3bSJed Brown initLevel, /* level of refinement */ 10190a96aa3bSJed Brown 1, /* uniform refinement */ 10200a96aa3bSJed Brown 0, /* we don't allocate any per quadrant data */ 10210a96aa3bSJed Brown NULL, /* there is no special quadrant initialization */ 10220a96aa3bSJed Brown (void*)dm)); /* this dm is the user context */ 10230a96aa3bSJed Brown 10240a96aa3bSJed Brown if (initLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 10250a96aa3bSJed Brown if (dm->setfromoptionscalled) { 10260a96aa3bSJed Brown PetscBool flgPattern, flgFractal; 10270a96aa3bSJed Brown PetscInt corner = 0; 10280a96aa3bSJed Brown PetscInt corners[P4EST_CHILDREN], ncorner = P4EST_CHILDREN; 10290a96aa3bSJed Brown PetscReal likelihood = 1./ P4EST_DIM; 10300a96aa3bSJed Brown PetscInt pattern; 10310a96aa3bSJed Brown const char *prefix; 10320a96aa3bSJed Brown 10339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix)); 10349566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEList(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_pattern",DMRefinePatternName,PATTERN_COUNT,&pattern,&flgPattern)); 10359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_corner",&corner,NULL)); 10369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_fractal_corners",corners,&ncorner,&flgFractal)); 10379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_hash_likelihood",&likelihood,NULL)); 10380a96aa3bSJed Brown 10390a96aa3bSJed Brown if (flgPattern) { 10400a96aa3bSJed Brown DMRefinePatternCtx *ctx; 10410a96aa3bSJed Brown PetscInt maxLevel; 10420a96aa3bSJed Brown 10439566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm,&maxLevel)); 10449566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm,&ctx)); 10450a96aa3bSJed Brown ctx->maxLevel = PetscMin(maxLevel,P4EST_QMAXLEVEL); 10460a96aa3bSJed Brown if (initLevel + ctx->maxLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 10470a96aa3bSJed Brown switch (pattern) { 10480a96aa3bSJed Brown case PATTERN_HASH: 10490a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Hash; 10500a96aa3bSJed Brown ctx->hashLikelihood = likelihood; 10510a96aa3bSJed Brown break; 10520a96aa3bSJed Brown case PATTERN_CORNER: 10530a96aa3bSJed Brown ctx->corner = corner; 10540a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Corner; 10550a96aa3bSJed Brown break; 10560a96aa3bSJed Brown case PATTERN_CENTER: 10570a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Center; 10580a96aa3bSJed Brown break; 10590a96aa3bSJed Brown case PATTERN_FRACTAL: 10600a96aa3bSJed Brown if (flgFractal) { 10610a96aa3bSJed Brown PetscInt i; 10620a96aa3bSJed Brown 10630a96aa3bSJed Brown for (i = 0; i < ncorner; i++) ctx->fractal[corners[i]] = PETSC_TRUE; 10640a96aa3bSJed Brown } else { 10650a96aa3bSJed Brown #if !defined(P4_TO_P8) 10660a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[1] = ctx->fractal[2] = PETSC_TRUE; 10670a96aa3bSJed Brown #else 10680a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[3] = ctx->fractal[5] = ctx->fractal[6] = PETSC_TRUE; 10690a96aa3bSJed Brown #endif 10700a96aa3bSJed Brown } 10710a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Fractal; 10720a96aa3bSJed Brown break; 10730a96aa3bSJed Brown default: 10740a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Not a valid refinement pattern"); 10750a96aa3bSJed Brown } 10760a96aa3bSJed Brown 10770a96aa3bSJed Brown pforest->forest->user_pointer = (void*) ctx; 1078792fecdfSBarry Smith PetscCallP4est(p4est_refine,(pforest->forest,1,ctx->refine_fn,NULL)); 1079792fecdfSBarry Smith PetscCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 10809566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 10810a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 10820a96aa3bSJed Brown } 10830a96aa3bSJed Brown } 10840a96aa3bSJed Brown } 10850a96aa3bSJed Brown if (pforest->coarsen_hierarchy) { 10860a96aa3bSJed Brown PetscInt initLevel, currLevel, minLevel; 10870a96aa3bSJed Brown 10889566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm,&currLevel)); 10899566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm,&initLevel)); 10909566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&minLevel)); 10910a96aa3bSJed Brown if (currLevel > minLevel) { 10920a96aa3bSJed Brown DM_Forest_pforest *coarse_pforest; 10930a96aa3bSJed Brown DMLabel coarsen; 10940a96aa3bSJed Brown DM coarseDM; 10950a96aa3bSJed Brown 10969566063dSJacob Faibussowitsch PetscCall(DMForestTemplate(dm,MPI_COMM_NULL,&coarseDM)); 10979566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityPurpose(coarseDM,DM_ADAPT_COARSEN)); 10989566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "coarsen",&coarsen)); 10999566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(coarsen,DM_ADAPT_COARSEN)); 11009566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityLabel(coarseDM,coarsen)); 11019566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&coarsen)); 11029566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm,coarseDM)); 11039566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 11040a96aa3bSJed Brown initLevel = currLevel == initLevel ? initLevel - 1 : initLevel; 11059566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(coarseDM,initLevel)); 11069566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(coarseDM,minLevel)); 11070a96aa3bSJed Brown coarse_pforest = (DM_Forest_pforest*) ((DM_Forest*) coarseDM->data)->data; 11080a96aa3bSJed Brown coarse_pforest->coarsen_hierarchy = PETSC_TRUE; 11090a96aa3bSJed Brown } 11100a96aa3bSJed Brown } 11110a96aa3bSJed Brown 11120a96aa3bSJed Brown { /* repartitioning and overlap */ 11130a96aa3bSJed Brown PetscMPIInt size, rank; 11140a96aa3bSJed Brown 11159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size)); 11169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank)); 11170a96aa3bSJed Brown if ((size > 1) && (pforest->partition_for_coarsening || forest->cellWeights || forest->weightCapacity != 1. || forest->weightsFactor != 1.)) { 11180a96aa3bSJed Brown PetscBool copyForest = PETSC_FALSE; 11190a96aa3bSJed Brown p4est_t *forest_copy = NULL; 11200a96aa3bSJed Brown p4est_gloidx_t shipped = 0; 11210a96aa3bSJed Brown 11220a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) copyForest = PETSC_TRUE; 1123792fecdfSBarry Smith if (copyForest) PetscCallP4estReturn(forest_copy,p4est_copy,(pforest->forest,0)); 11240a96aa3bSJed Brown 11250a96aa3bSJed Brown if (!forest->cellWeights && forest->weightCapacity == 1. && forest->weightsFactor == 1.) { 1126792fecdfSBarry Smith PetscCallP4estReturn(shipped,p4est_partition_ext,(pforest->forest,(int)pforest->partition_for_coarsening,NULL)); 11270a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Non-uniform partition cases not implemented yet"); 11280a96aa3bSJed Brown if (shipped) ctx.anyChange = PETSC_TRUE; 11290a96aa3bSJed Brown if (forest_copy) { 11300a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 11310a96aa3bSJed Brown PetscSF repartSF; /* repartSF has roots in the old partition */ 11320a96aa3bSJed Brown PetscInt pStart = -1, pEnd = -1, p; 11330a96aa3bSJed Brown PetscInt numRoots, numLeaves; 11340a96aa3bSJed Brown PetscSFNode *repartRoots; 11350a96aa3bSJed Brown p4est_gloidx_t postStart = pforest->forest->global_first_quadrant[rank]; 11360a96aa3bSJed Brown p4est_gloidx_t postEnd = pforest->forest->global_first_quadrant[rank+1]; 11370a96aa3bSJed Brown p4est_gloidx_t partOffset = postStart; 11380a96aa3bSJed Brown 11390a96aa3bSJed Brown numRoots = (PetscInt) (forest_copy->global_first_quadrant[rank + 1] - forest_copy->global_first_quadrant[rank]); 11400a96aa3bSJed Brown numLeaves = (PetscInt) (postEnd - postStart); 11419566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(size,rank,pforest->forest,forest_copy,&pStart,&pEnd)); 11429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((PetscInt) pforest->forest->local_num_quadrants,&repartRoots)); 11430a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 11440a96aa3bSJed Brown p4est_gloidx_t preStart = forest_copy->global_first_quadrant[p]; 11450a96aa3bSJed Brown p4est_gloidx_t preEnd = forest_copy->global_first_quadrant[p+1]; 11460a96aa3bSJed Brown PetscInt q; 11470a96aa3bSJed Brown 11480a96aa3bSJed Brown if (preEnd == preStart) continue; 114908401ef6SPierre Jolivet PetscCheck(preStart <= postStart,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Bad partition overlap computation"); 11500a96aa3bSJed Brown preEnd = preEnd > postEnd ? postEnd : preEnd; 11510a96aa3bSJed Brown for (q = partOffset; q < preEnd; q++) { 11520a96aa3bSJed Brown repartRoots[q - postStart].rank = p; 11530a96aa3bSJed Brown repartRoots[q - postStart].index = partOffset - preStart; 11540a96aa3bSJed Brown } 11550a96aa3bSJed Brown partOffset = preEnd; 11560a96aa3bSJed Brown } 11579566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&repartSF)); 11589566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(repartSF,numRoots,numLeaves,NULL,PETSC_OWN_POINTER,repartRoots,PETSC_OWN_POINTER)); 11599566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(repartSF)); 11600a96aa3bSJed Brown if (preCoarseToFine) { 11610a96aa3bSJed Brown PetscSF repartSFembed, preCoarseToFineNew; 11620a96aa3bSJed Brown PetscInt nleaves; 11630a96aa3bSJed Brown const PetscInt *leaves; 11640a96aa3bSJed Brown 11659566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 11669566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine,NULL,&nleaves,&leaves,NULL)); 11670a96aa3bSJed Brown if (leaves) { 11689566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(repartSF,nleaves,leaves,&repartSFembed)); 11690a96aa3bSJed Brown } else { 11700a96aa3bSJed Brown repartSFembed = repartSF; 11719566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)repartSFembed)); 11720a96aa3bSJed Brown } 11739566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(preCoarseToFine,repartSFembed,&preCoarseToFineNew)); 11749566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 11759566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFembed)); 11760a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 11770a96aa3bSJed Brown } 11780a96aa3bSJed Brown if (coarseToPreFine) { 11790a96aa3bSJed Brown PetscSF repartSFinv, coarseToPreFineNew; 11800a96aa3bSJed Brown 11819566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(repartSF,&repartSFinv)); 11829566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(repartSFinv,coarseToPreFine,&coarseToPreFineNew)); 11839566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 11849566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFinv)); 11850a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 11860a96aa3bSJed Brown } 11879566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSF)); 11880a96aa3bSJed Brown } 1189792fecdfSBarry Smith PetscCallP4est(p4est_destroy,(forest_copy)); 11900a96aa3bSJed Brown } 11910a96aa3bSJed Brown } 11920a96aa3bSJed Brown if (size > 1) { 11930a96aa3bSJed Brown PetscInt overlap; 11940a96aa3bSJed Brown 11959566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm,&overlap)); 11960a96aa3bSJed Brown 11970a96aa3bSJed Brown if (adaptFrom) { 11980a96aa3bSJed Brown PetscInt aoverlap; 11990a96aa3bSJed Brown 12009566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(adaptFrom,&aoverlap)); 12010a96aa3bSJed Brown if (aoverlap != overlap) { 12020a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 12030a96aa3bSJed Brown } 12040a96aa3bSJed Brown } 12050a96aa3bSJed Brown 12060a96aa3bSJed Brown if (overlap > 0) { 12070a96aa3bSJed Brown PetscInt i, cLocalStart; 12080a96aa3bSJed Brown PetscInt cEnd; 12090a96aa3bSJed Brown PetscSF preCellSF = NULL, cellSF = NULL; 12100a96aa3bSJed Brown 1211792fecdfSBarry Smith PetscCallP4estReturn(pforest->ghost,p4est_ghost_new,(pforest->forest,P4EST_CONNECT_FULL)); 1212792fecdfSBarry Smith PetscCallP4estReturn(pforest->lnodes,p4est_lnodes_new,(pforest->forest,pforest->ghost,-P4EST_DIM)); 1213792fecdfSBarry Smith PetscCallP4est(p4est_ghost_support_lnodes,(pforest->forest,pforest->lnodes,pforest->ghost)); 1214792fecdfSBarry Smith for (i = 1; i < overlap; i++) PetscCallP4est(p4est_ghost_expand_by_lnodes,(pforest->forest,pforest->lnodes,pforest->ghost)); 12150a96aa3bSJed Brown 12160a96aa3bSJed Brown cLocalStart = pforest->cLocalStart = pforest->ghost->proc_offsets[rank]; 12170a96aa3bSJed Brown cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[size]; 12180a96aa3bSJed Brown 12190a96aa3bSJed Brown /* shift sfs by cLocalStart, expand by cell SFs */ 12200a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 12219566063dSJacob Faibussowitsch if (adaptFrom) PetscCall(DMForestGetCellSF(adaptFrom,&preCellSF)); 12220a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 12239566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(dm,&cellSF)); 12240a96aa3bSJed Brown } 12250a96aa3bSJed Brown if (preCoarseToFine) { 12260a96aa3bSJed Brown PetscSF preCoarseToFineNew; 12270a96aa3bSJed Brown PetscInt nleaves, nroots, *leavesNew, i, nleavesNew; 12280a96aa3bSJed Brown const PetscInt *leaves; 12290a96aa3bSJed Brown const PetscSFNode *remotes; 12300a96aa3bSJed Brown PetscSFNode *remotesAll; 12310a96aa3bSJed Brown 12329566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 12339566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine,&nroots,&nleaves,&leaves,&remotes)); 12349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd,&remotesAll)); 12350a96aa3bSJed Brown for (i = 0; i < cEnd; i++) { 12360a96aa3bSJed Brown remotesAll[i].rank = -1; 12370a96aa3bSJed Brown remotesAll[i].index = -1; 12380a96aa3bSJed Brown } 12390a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesAll[(leaves ? leaves[i] : i) + cLocalStart] = remotes[i]; 12409566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(cellSF)); 12419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(cellSF,MPIU_2INT,remotesAll,remotesAll,MPI_REPLACE)); 12429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(cellSF,MPIU_2INT,remotesAll,remotesAll,MPI_REPLACE)); 12430a96aa3bSJed Brown nleavesNew = 0; 12440a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12450a96aa3bSJed Brown if (remotesAll[i].rank >= 0) nleavesNew++; 12460a96aa3bSJed Brown } 12479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesNew,&leavesNew)); 12480a96aa3bSJed Brown nleavesNew = 0; 12490a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12500a96aa3bSJed Brown if (remotesAll[i].rank >= 0) { 12510a96aa3bSJed Brown leavesNew[nleavesNew] = i; 12520a96aa3bSJed Brown if (i > nleavesNew) remotesAll[nleavesNew] = remotesAll[i]; 12530a96aa3bSJed Brown nleavesNew++; 12540a96aa3bSJed Brown } 12550a96aa3bSJed Brown } 12569566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&preCoarseToFineNew)); 12570a96aa3bSJed Brown if (nleavesNew < cEnd) { 12589566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew,nroots,nleavesNew,leavesNew,PETSC_OWN_POINTER,remotesAll,PETSC_COPY_VALUES)); 12590a96aa3bSJed Brown } else { /* all cells are leaves */ 12609566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 12619566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew,nroots,nleavesNew,NULL,PETSC_OWN_POINTER,remotesAll,PETSC_COPY_VALUES)); 12620a96aa3bSJed Brown } 12639566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesAll)); 12649566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 12650a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12660a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12670a96aa3bSJed Brown } 12680a96aa3bSJed Brown if (coarseToPreFine) { 12690a96aa3bSJed Brown PetscSF coarseToPreFineNew; 12700a96aa3bSJed Brown PetscInt nleaves, nroots, i, nleavesCellSF, nleavesExpanded, *leavesNew; 12710a96aa3bSJed Brown const PetscInt *leaves; 12720a96aa3bSJed Brown const PetscSFNode *remotes; 12730a96aa3bSJed Brown PetscSFNode *remotesNew, *remotesNewRoot, *remotesExpanded; 12740a96aa3bSJed Brown 12759566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(coarseToPreFine)); 12769566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToPreFine,&nroots,&nleaves,&leaves,&remotes)); 12779566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCellSF,NULL,&nleavesCellSF,NULL,NULL)); 12789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots,&remotesNewRoot)); 12799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves,&remotesNew)); 12800a96aa3bSJed Brown for (i = 0; i < nroots; i++) { 12810a96aa3bSJed Brown remotesNewRoot[i].rank = rank; 12820a96aa3bSJed Brown remotesNewRoot[i].index = i + cLocalStart; 12830a96aa3bSJed Brown } 12849566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToPreFine,MPIU_2INT,remotesNewRoot,remotesNew,MPI_REPLACE)); 12859566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToPreFine,MPIU_2INT,remotesNewRoot,remotesNew,MPI_REPLACE)); 12869566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNewRoot)); 12879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesCellSF,&remotesExpanded)); 12880a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12890a96aa3bSJed Brown remotesExpanded[i].rank = -1; 12900a96aa3bSJed Brown remotesExpanded[i].index = -1; 12910a96aa3bSJed Brown } 12920a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesExpanded[leaves ? leaves[i] : i] = remotesNew[i]; 12939566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNew)); 12949566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(preCellSF,MPIU_2INT,remotesExpanded,remotesExpanded,MPI_REPLACE)); 12959566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(preCellSF,MPIU_2INT,remotesExpanded,remotesExpanded,MPI_REPLACE)); 12960a96aa3bSJed Brown 12970a96aa3bSJed Brown nleavesExpanded = 0; 12980a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12990a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) nleavesExpanded++; 13000a96aa3bSJed Brown } 13019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesExpanded,&leavesNew)); 13020a96aa3bSJed Brown nleavesExpanded = 0; 13030a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 13040a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) { 13050a96aa3bSJed Brown leavesNew[nleavesExpanded] = i; 13060a96aa3bSJed Brown if (i > nleavesExpanded) remotesExpanded[nleavesExpanded] = remotes[i]; 13070a96aa3bSJed Brown nleavesExpanded++; 13080a96aa3bSJed Brown } 13090a96aa3bSJed Brown } 13109566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&coarseToPreFineNew)); 13110a96aa3bSJed Brown if (nleavesExpanded < nleavesCellSF) { 13129566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew,cEnd,nleavesExpanded,leavesNew,PETSC_OWN_POINTER,remotesExpanded,PETSC_COPY_VALUES)); 13130a96aa3bSJed Brown } else { 13149566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 13159566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew,cEnd,nleavesExpanded,NULL,PETSC_OWN_POINTER,remotesExpanded,PETSC_COPY_VALUES)); 13160a96aa3bSJed Brown } 13179566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesExpanded)); 13189566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 13190a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 13200a96aa3bSJed Brown } 13210a96aa3bSJed Brown } 13220a96aa3bSJed Brown } 13230a96aa3bSJed Brown } 13240a96aa3bSJed Brown forest->preCoarseToFine = preCoarseToFine; 13250a96aa3bSJed Brown forest->coarseToPreFine = coarseToPreFine; 13260a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 13279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&ctx.anyChange,&(pforest->adaptivitySuccess),1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm))); 13289566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,NULL)); 13290a96aa3bSJed Brown PetscFunctionReturn(0); 13300a96aa3bSJed Brown } 13310a96aa3bSJed Brown 13320a96aa3bSJed Brown #define DMForestGetAdaptivitySuccess_pforest _append_pforest(DMForestGetAdaptivitySuccess) 13330a96aa3bSJed Brown static PetscErrorCode DMForestGetAdaptivitySuccess_pforest(DM dm, PetscBool *success) 13340a96aa3bSJed Brown { 13350a96aa3bSJed Brown DM_Forest *forest; 13360a96aa3bSJed Brown DM_Forest_pforest *pforest; 13370a96aa3bSJed Brown 13380a96aa3bSJed Brown PetscFunctionBegin; 13390a96aa3bSJed Brown forest = (DM_Forest *) dm->data; 13400a96aa3bSJed Brown pforest = (DM_Forest_pforest *) forest->data; 13410a96aa3bSJed Brown *success = pforest->adaptivitySuccess; 13420a96aa3bSJed Brown PetscFunctionReturn(0); 13430a96aa3bSJed Brown } 13440a96aa3bSJed Brown 13450a96aa3bSJed Brown #define DMView_ASCII_pforest _append_pforest(DMView_ASCII) 13460a96aa3bSJed Brown static PetscErrorCode DMView_ASCII_pforest(PetscObject odm, PetscViewer viewer) 13470a96aa3bSJed Brown { 13480a96aa3bSJed Brown DM dm = (DM) odm; 13490a96aa3bSJed Brown 13500a96aa3bSJed Brown PetscFunctionBegin; 13510a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13520a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13539566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13540a96aa3bSJed Brown switch (viewer->format) { 13550a96aa3bSJed Brown case PETSC_VIEWER_DEFAULT: 13560a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO: 13570a96aa3bSJed Brown { 13580a96aa3bSJed Brown PetscInt dim; 13590a96aa3bSJed Brown const char *name; 13600a96aa3bSJed Brown 13619566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 13629566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 136363a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "Forest %s in %" PetscInt_FMT " dimensions:\n", name, dim)); 136463a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Forest in %" PetscInt_FMT " dimensions:\n", dim)); 13650a96aa3bSJed Brown } 13660a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO_DETAIL: 13670a96aa3bSJed Brown case PETSC_VIEWER_LOAD_BALANCE: 13680a96aa3bSJed Brown { 13690a96aa3bSJed Brown DM plex; 13700a96aa3bSJed Brown 13719566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 13729566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 13730a96aa3bSJed Brown } 13740a96aa3bSJed Brown break; 137598921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 13760a96aa3bSJed Brown } 13770a96aa3bSJed Brown PetscFunctionReturn(0); 13780a96aa3bSJed Brown } 13790a96aa3bSJed Brown 13800a96aa3bSJed Brown #define DMView_VTK_pforest _append_pforest(DMView_VTK) 13810a96aa3bSJed Brown static PetscErrorCode DMView_VTK_pforest(PetscObject odm, PetscViewer viewer) 13820a96aa3bSJed Brown { 13830a96aa3bSJed Brown DM dm = (DM) odm; 13840a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 13850a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 13860a96aa3bSJed Brown PetscBool isvtk; 13870a96aa3bSJed Brown PetscReal vtkScale = 1. - PETSC_MACHINE_EPSILON; 13880a96aa3bSJed Brown PetscViewer_VTK *vtk = (PetscViewer_VTK*)viewer->data; 13890a96aa3bSJed Brown const char *name; 13900a96aa3bSJed Brown char *filenameStrip = NULL; 13910a96aa3bSJed Brown PetscBool hasExt; 13920a96aa3bSJed Brown size_t len; 13930a96aa3bSJed Brown p4est_geometry_t *geom; 13940a96aa3bSJed Brown 13950a96aa3bSJed Brown PetscFunctionBegin; 13960a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13970a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13989566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13990a96aa3bSJed Brown geom = pforest->topo->geom; 14009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 140128b400f6SJacob Faibussowitsch PetscCheck(isvtk,PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name); 14020a96aa3bSJed Brown switch (viewer->format) { 14030a96aa3bSJed Brown case PETSC_VIEWER_VTK_VTU: 140428b400f6SJacob Faibussowitsch PetscCheck(pforest->forest,PetscObjectComm(odm),PETSC_ERR_ARG_WRONG,"DM has not been setup with a valid forest"); 14050a96aa3bSJed Brown name = vtk->filename; 14069566063dSJacob Faibussowitsch PetscCall(PetscStrlen(name,&len)); 14079566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(name+len-4,".vtu",&hasExt)); 14080a96aa3bSJed Brown if (hasExt) { 14099566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name,&filenameStrip)); 14100a96aa3bSJed Brown filenameStrip[len-4]='\0'; 14110a96aa3bSJed Brown name = filenameStrip; 14120a96aa3bSJed Brown } 1413792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4estReturn(geom,p4est_geometry_new_connectivity,(pforest->topo->conn)); 14140a96aa3bSJed Brown { 14150a96aa3bSJed Brown p4est_vtk_context_t *pvtk; 14160a96aa3bSJed Brown int footerr; 14170a96aa3bSJed Brown 1418792fecdfSBarry Smith PetscCallP4estReturn(pvtk,p4est_vtk_context_new,(pforest->forest,name)); 1419792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_geom,(pvtk,geom)); 1420792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_scale,(pvtk,(double)vtkScale)); 1421792fecdfSBarry Smith PetscCallP4estReturn(pvtk,p4est_vtk_write_header,(pvtk)); 142228b400f6SJacob Faibussowitsch PetscCheck(pvtk,PetscObjectComm((PetscObject)odm),PETSC_ERR_LIB,P4EST_STRING "_vtk_write_header() failed"); 1423792fecdfSBarry Smith PetscCallP4estReturn(pvtk,p4est_vtk_write_cell_dataf,(pvtk, 14240a96aa3bSJed Brown 1, /* write tree */ 14250a96aa3bSJed Brown 1, /* write level */ 14260a96aa3bSJed Brown 1, /* write rank */ 14270a96aa3bSJed Brown 0, /* do not wrap rank */ 14280a96aa3bSJed Brown 0, /* no scalar fields */ 14290a96aa3bSJed Brown 0, /* no vector fields */ 14300a96aa3bSJed Brown pvtk)); 143128b400f6SJacob Faibussowitsch PetscCheck(pvtk,PetscObjectComm((PetscObject)odm),PETSC_ERR_LIB,P4EST_STRING "_vtk_write_cell_dataf() failed"); 1432792fecdfSBarry Smith PetscCallP4estReturn(footerr,p4est_vtk_write_footer,(pvtk)); 143328b400f6SJacob Faibussowitsch PetscCheck(!footerr,PetscObjectComm((PetscObject)odm),PETSC_ERR_LIB,P4EST_STRING "_vtk_write_footer() failed"); 14340a96aa3bSJed Brown } 1435792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4est(p4est_geometry_destroy,(geom)); 14369566063dSJacob Faibussowitsch PetscCall(PetscFree(filenameStrip)); 14370a96aa3bSJed Brown break; 143898921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 14390a96aa3bSJed Brown } 14400a96aa3bSJed Brown PetscFunctionReturn(0); 14410a96aa3bSJed Brown } 14420a96aa3bSJed Brown 14430a96aa3bSJed Brown #define DMView_HDF5_pforest _append_pforest(DMView_HDF5) 14440a96aa3bSJed Brown static PetscErrorCode DMView_HDF5_pforest(DM dm, PetscViewer viewer) 14450a96aa3bSJed Brown { 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)); 14520a96aa3bSJed Brown PetscFunctionReturn(0); 14530a96aa3bSJed Brown } 14540a96aa3bSJed Brown 14550a96aa3bSJed Brown #define DMView_GLVis_pforest _append_pforest(DMView_GLVis) 14560a96aa3bSJed Brown static PetscErrorCode DMView_GLVis_pforest(DM dm, PetscViewer viewer) 14570a96aa3bSJed Brown { 14580a96aa3bSJed Brown DM plex; 14590a96aa3bSJed Brown 14600a96aa3bSJed Brown PetscFunctionBegin; 14619566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 14629566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 14639566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 14640a96aa3bSJed Brown PetscFunctionReturn(0); 14650a96aa3bSJed Brown } 14660a96aa3bSJed Brown 14670a96aa3bSJed Brown #define DMView_pforest _append_pforest(DMView) 14680a96aa3bSJed Brown static PetscErrorCode DMView_pforest(DM dm, PetscViewer viewer) 14690a96aa3bSJed Brown { 14700a96aa3bSJed Brown PetscBool isascii, isvtk, ishdf5, isglvis; 14710a96aa3bSJed Brown 14720a96aa3bSJed Brown PetscFunctionBegin; 14730a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14740a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 14759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii)); 14769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 14779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 14789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 14790a96aa3bSJed Brown if (isascii) { 14809566063dSJacob Faibussowitsch PetscCall(DMView_ASCII_pforest((PetscObject) dm,viewer)); 14810a96aa3bSJed Brown } else if (isvtk) { 14829566063dSJacob Faibussowitsch PetscCall(DMView_VTK_pforest((PetscObject) dm,viewer)); 14830a96aa3bSJed Brown } else if (ishdf5) { 14849566063dSJacob Faibussowitsch PetscCall(DMView_HDF5_pforest(dm, viewer)); 14850a96aa3bSJed Brown } else if (isglvis) { 14869566063dSJacob Faibussowitsch PetscCall(DMView_GLVis_pforest(dm, viewer)); 14870a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject) dm),PETSC_ERR_SUP,"Viewer not supported (not VTK, HDF5, or GLVis)"); 14880a96aa3bSJed Brown PetscFunctionReturn(0); 14890a96aa3bSJed Brown } 14900a96aa3bSJed Brown 14910a96aa3bSJed Brown static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *conn, PetscInt **tree_face_to_uniq) 14920a96aa3bSJed Brown { 14930a96aa3bSJed Brown PetscInt *ttf, f, t, g, count; 14940a96aa3bSJed Brown PetscInt numFacets; 14950a96aa3bSJed Brown 14960a96aa3bSJed Brown PetscFunctionBegin; 14970a96aa3bSJed Brown numFacets = conn->num_trees * P4EST_FACES; 14989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFacets,&ttf)); 14990a96aa3bSJed Brown for (f = 0; f < numFacets; f++) ttf[f] = -1; 15000a96aa3bSJed Brown for (g = 0, count = 0, t = 0; t < conn->num_trees; t++) { 15010a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++, g++) { 15020a96aa3bSJed Brown if (ttf[g] == -1) { 15030a96aa3bSJed Brown PetscInt ng; 15040a96aa3bSJed Brown 15050a96aa3bSJed Brown ttf[g] = count++; 15060a96aa3bSJed Brown ng = conn->tree_to_tree[g] * P4EST_FACES + (conn->tree_to_face[g] % P4EST_FACES); 15070a96aa3bSJed Brown ttf[ng] = ttf[g]; 15080a96aa3bSJed Brown } 15090a96aa3bSJed Brown } 15100a96aa3bSJed Brown } 15110a96aa3bSJed Brown *tree_face_to_uniq = ttf; 15120a96aa3bSJed Brown PetscFunctionReturn(0); 15130a96aa3bSJed Brown } 15140a96aa3bSJed Brown 15150a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM dm, p4est_connectivity_t **connOut, PetscInt **tree_face_to_uniq) 15160a96aa3bSJed Brown { 15170a96aa3bSJed Brown p4est_topidx_t numTrees, numVerts, numCorns, numCtt; 15180a96aa3bSJed Brown PetscSection ctt; 15190a96aa3bSJed Brown #if defined(P4_TO_P8) 15200a96aa3bSJed Brown p4est_topidx_t numEdges, numEtt; 15210a96aa3bSJed Brown PetscSection ett; 15220a96aa3bSJed Brown PetscInt eStart, eEnd, e, ettSize; 15230a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES + P8EST_EDGES; 15240a96aa3bSJed Brown PetscInt edgeOff = 1 + P4EST_FACES; 15250a96aa3bSJed Brown #else 15260a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES; 15270a96aa3bSJed Brown #endif 15280a96aa3bSJed Brown p4est_connectivity_t *conn; 15290a96aa3bSJed Brown PetscInt cStart, cEnd, c, vStart, vEnd, v, fStart, fEnd, f; 15300a96aa3bSJed Brown PetscInt *star = NULL, *closure = NULL, closureSize, starSize, cttSize; 15310a96aa3bSJed Brown PetscInt *ttf; 15320a96aa3bSJed Brown 15330a96aa3bSJed Brown PetscFunctionBegin; 15340a96aa3bSJed Brown /* 1: count objects, allocate */ 15359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd)); 15369566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cEnd-cStart,&numTrees)); 15370a96aa3bSJed Brown numVerts = P4EST_CHILDREN * numTrees; 15389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,0,&vStart,&vEnd)); 15399566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(vEnd-vStart,&numCorns)); 15409566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,&ctt)); 15419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ctt,vStart,vEnd)); 15420a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 15430a96aa3bSJed Brown PetscInt s; 15440a96aa3bSJed Brown 15459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star)); 15460a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 15470a96aa3bSJed Brown PetscInt p = star[2*s]; 15480a96aa3bSJed Brown 15490a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 15500a96aa3bSJed Brown /* we want to count every time cell p references v, so we see how many times it comes up in the closure. This 15510a96aa3bSJed Brown * only protects against periodicity problems */ 15529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 155363a3b9bcSJacob 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); 15540a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 15550a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 15560a96aa3bSJed Brown 15571dca8a05SBarry Smith PetscCheck(cellVert >= vStart && cellVert < vEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure: vertices"); 15580a96aa3bSJed Brown if (cellVert == v) { 15599566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(ctt,v,1)); 15600a96aa3bSJed Brown } 15610a96aa3bSJed Brown } 15629566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 15630a96aa3bSJed Brown } 15640a96aa3bSJed Brown } 15659566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star)); 15660a96aa3bSJed Brown } 15679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ctt)); 15689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ctt,&cttSize)); 15699566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cttSize,&numCtt)); 15700a96aa3bSJed Brown #if defined(P4_TO_P8) 15719566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,P4EST_DIM-1,&eStart,&eEnd)); 15729566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(eEnd-eStart,&numEdges)); 15739566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,&ett)); 15749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ett,eStart,eEnd)); 15750a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 15760a96aa3bSJed Brown PetscInt s; 15770a96aa3bSJed Brown 15789566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star)); 15790a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 15800a96aa3bSJed Brown PetscInt p = star[2*s]; 15810a96aa3bSJed Brown 15820a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 15830a96aa3bSJed Brown /* we want to count every time cell p references e, so we see how many times it comes up in the closure. This 15840a96aa3bSJed Brown * only protects against periodicity problems */ 15859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 158608401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cell with wrong closure size"); 15870a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 15880a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 15890a96aa3bSJed Brown 15901dca8a05SBarry Smith PetscCheck(cellEdge >= eStart && cellEdge < eEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure: edges"); 15910a96aa3bSJed Brown if (cellEdge == e) { 15929566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(ett,e,1)); 15930a96aa3bSJed Brown } 15940a96aa3bSJed Brown } 15959566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 15960a96aa3bSJed Brown } 15970a96aa3bSJed Brown } 15989566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star)); 15990a96aa3bSJed Brown } 16009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ett)); 16019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ett,&ettSize)); 16029566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(ettSize,&numEtt)); 16030a96aa3bSJed Brown 16040a96aa3bSJed Brown /* This routine allocates space for the arrays, which we fill below */ 1605792fecdfSBarry Smith PetscCallP4estReturn(conn,p8est_connectivity_new,(numVerts,numTrees,numEdges,numEtt,numCorns,numCtt)); 16060a96aa3bSJed Brown #else 1607792fecdfSBarry Smith PetscCallP4estReturn(conn,p4est_connectivity_new,(numVerts,numTrees,numCorns,numCtt)); 16080a96aa3bSJed Brown #endif 16090a96aa3bSJed Brown 16100a96aa3bSJed Brown /* 2: visit every face, determine neighboring cells(trees) */ 16119566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,1,&fStart,&fEnd)); 16129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd-cStart) * P4EST_FACES,&ttf)); 16130a96aa3bSJed Brown for (f = fStart; f < fEnd; f++) { 16140a96aa3bSJed Brown PetscInt numSupp, s; 16150a96aa3bSJed Brown PetscInt myFace[2] = {-1, -1}; 16160a96aa3bSJed Brown PetscInt myOrnt[2] = {PETSC_MIN_INT, PETSC_MIN_INT}; 16170a96aa3bSJed Brown const PetscInt *supp; 16180a96aa3bSJed Brown 16199566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &numSupp)); 16201dca8a05SBarry 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); 16219566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &supp)); 16220a96aa3bSJed Brown 16230a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16240a96aa3bSJed Brown PetscInt p = supp[s]; 16250a96aa3bSJed Brown 16260a96aa3bSJed Brown if (p >= cEnd) { 16270a96aa3bSJed Brown numSupp--; 16280a96aa3bSJed Brown if (s) supp = &supp[1 - s]; 16290a96aa3bSJed Brown break; 16300a96aa3bSJed Brown } 16310a96aa3bSJed Brown } 16320a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16330a96aa3bSJed Brown PetscInt p = supp[s], i; 16340a96aa3bSJed Brown PetscInt numCone; 16350a96aa3bSJed Brown DMPolytopeType ct; 16360a96aa3bSJed Brown const PetscInt *cone; 16370a96aa3bSJed Brown const PetscInt *ornt; 16380a96aa3bSJed Brown PetscInt orient = PETSC_MIN_INT; 16390a96aa3bSJed Brown 16409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &numCone)); 164163a3b9bcSJacob 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); 16429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 16439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[0], &ct)); 16449566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 16450a96aa3bSJed Brown for (i = 0; i < P4EST_FACES; i++) { 16460a96aa3bSJed Brown if (cone[i] == f) { 16470a96aa3bSJed Brown orient = DMPolytopeConvertNewOrientation_Internal(ct, ornt[i]); 16480a96aa3bSJed Brown break; 16490a96aa3bSJed Brown } 16500a96aa3bSJed Brown } 165163a3b9bcSJacob Faibussowitsch PetscCheck(i < P4EST_FACES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"cell %" PetscInt_FMT " faced %" PetscInt_FMT " mismatch",p,f); 16520a96aa3bSJed Brown if (p < cStart || p >= cEnd) { 16530a96aa3bSJed Brown DMPolytopeType ct; 16549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 165563a3b9bcSJacob 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); 16560a96aa3bSJed Brown } 16570a96aa3bSJed Brown ttf[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = f - fStart; 16580a96aa3bSJed Brown if (numSupp == 1) { 16590a96aa3bSJed Brown /* boundary faces indicated by self reference */ 16600a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = p - cStart; 16610a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = (int8_t) PetscFaceToP4estFace[i]; 16620a96aa3bSJed Brown } else { 16630a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16640a96aa3bSJed Brown 16650a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = supp[1 - s] - cStart; 16660a96aa3bSJed Brown myFace[s] = PetscFaceToP4estFace[i]; 16670a96aa3bSJed Brown /* get the orientation of cell p in p4est-type closure to facet f, by composing the p4est-closure to 16680a96aa3bSJed Brown * petsc-closure permutation and the petsc-closure to facet orientation */ 16690a96aa3bSJed Brown myOrnt[s] = DihedralCompose(N,orient,DMPolytopeConvertNewOrientation_Internal(ct, P4estFaceToPetscOrnt[myFace[s]])); 16700a96aa3bSJed Brown } 16710a96aa3bSJed Brown } 16720a96aa3bSJed Brown if (numSupp == 2) { 16730a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16740a96aa3bSJed Brown PetscInt p = supp[s]; 16750a96aa3bSJed Brown PetscInt orntAtoB; 16760a96aa3bSJed Brown PetscInt p4estOrient; 16770a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16780a96aa3bSJed Brown 16790a96aa3bSJed Brown /* composing the forward permutation with the other cell's inverse permutation gives the self-to-neighbor 16800a96aa3bSJed Brown * permutation of this cell-facet's cone */ 16810a96aa3bSJed Brown orntAtoB = DihedralCompose(N,DihedralInvert(N,myOrnt[1-s]),myOrnt[s]); 16820a96aa3bSJed Brown 16830a96aa3bSJed Brown /* convert cone-description permutation (i.e., edges around facet) to cap-description permutation (i.e., 16840a96aa3bSJed Brown * vertices around facet) */ 16850a96aa3bSJed Brown #if !defined(P4_TO_P8) 16860a96aa3bSJed Brown p4estOrient = orntAtoB < 0 ? -(orntAtoB + 1) : orntAtoB; 16870a96aa3bSJed Brown #else 16880a96aa3bSJed Brown { 16890a96aa3bSJed Brown PetscInt firstVert = orntAtoB < 0 ? ((-orntAtoB) % N) : orntAtoB; 16900a96aa3bSJed Brown PetscInt p4estFirstVert = firstVert < 2 ? firstVert : (firstVert ^ 1); 16910a96aa3bSJed Brown 16920a96aa3bSJed Brown /* swap bits */ 16930a96aa3bSJed Brown p4estOrient = ((myFace[s] <= myFace[1 - s]) || (orntAtoB < 0)) ? p4estFirstVert : ((p4estFirstVert >> 1) | ((p4estFirstVert & 1) << 1)); 16940a96aa3bSJed Brown } 16950a96aa3bSJed Brown #endif 16960a96aa3bSJed Brown /* encode neighbor face and orientation in tree_to_face per p4est_connectivity standard (see 16970a96aa3bSJed Brown * p4est_connectivity.h, p8est_connectivity.h) */ 16980a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + myFace[s]] = (int8_t) myFace[1 - s] + p4estOrient * P4EST_FACES; 16990a96aa3bSJed Brown } 17000a96aa3bSJed Brown } 17010a96aa3bSJed Brown } 17020a96aa3bSJed Brown 17030a96aa3bSJed Brown #if defined(P4_TO_P8) 17040a96aa3bSJed Brown /* 3: visit every edge */ 17050a96aa3bSJed Brown conn->ett_offset[0] = 0; 17060a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 17070a96aa3bSJed Brown PetscInt off, s; 17080a96aa3bSJed Brown 17099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ett,e,&off)); 17100a96aa3bSJed Brown conn->ett_offset[e - eStart] = (p4est_topidx_t) off; 17119566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star)); 17120a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 17130a96aa3bSJed Brown PetscInt p = star[2 * s]; 17140a96aa3bSJed Brown 17150a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 17169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 171708401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure"); 17180a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 17190a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 17200a96aa3bSJed Brown PetscInt cellOrnt = closure[2 * (c + edgeOff) + 1]; 17210a96aa3bSJed Brown DMPolytopeType ct; 17220a96aa3bSJed Brown 17239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cellEdge, &ct)); 17240a96aa3bSJed Brown cellOrnt = DMPolytopeConvertNewOrientation_Internal(ct, cellOrnt); 17250a96aa3bSJed Brown if (cellEdge == e) { 17260a96aa3bSJed Brown PetscInt p4estEdge = PetscEdgeToP4estEdge[c]; 17270a96aa3bSJed Brown PetscInt totalOrient; 17280a96aa3bSJed Brown 17290a96aa3bSJed Brown /* compose p4est-closure to petsc-closure permutation and petsc-closure to edge orientation */ 17300a96aa3bSJed Brown totalOrient = DihedralCompose(2,cellOrnt,DMPolytopeConvertNewOrientation_Internal(DM_POLYTOPE_SEGMENT, P4estEdgeToPetscOrnt[p4estEdge])); 17310a96aa3bSJed Brown /* p4est orientations are positive: -2 => 1, -1 => 0 */ 17320a96aa3bSJed Brown totalOrient = (totalOrient < 0) ? -(totalOrient + 1) : totalOrient; 17330a96aa3bSJed Brown conn->edge_to_tree[off] = (p4est_locidx_t) (p - cStart); 17340a96aa3bSJed Brown /* encode cell-edge and orientation in edge_to_edge per p8est_connectivity standart (see 17350a96aa3bSJed Brown * p8est_connectivity.h) */ 17360a96aa3bSJed Brown conn->edge_to_edge[off++] = (int8_t) p4estEdge + P8EST_EDGES * totalOrient; 17370a96aa3bSJed Brown conn->tree_to_edge[P8EST_EDGES * (p - cStart) + p4estEdge] = e - eStart; 17380a96aa3bSJed Brown } 17390a96aa3bSJed Brown } 17409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 17410a96aa3bSJed Brown } 17420a96aa3bSJed Brown } 17439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star)); 17440a96aa3bSJed Brown } 17459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ett)); 17460a96aa3bSJed Brown #endif 17470a96aa3bSJed Brown 17480a96aa3bSJed Brown /* 4: visit every vertex */ 17490a96aa3bSJed Brown conn->ctt_offset[0] = 0; 17500a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 17510a96aa3bSJed Brown PetscInt off, s; 17520a96aa3bSJed Brown 17539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ctt,v,&off)); 17540a96aa3bSJed Brown conn->ctt_offset[v - vStart] = (p4est_topidx_t) off; 17559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star)); 17560a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 17570a96aa3bSJed Brown PetscInt p = star[2 * s]; 17580a96aa3bSJed Brown 17590a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 17609566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 176108401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure"); 17620a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 17630a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 17640a96aa3bSJed Brown 17650a96aa3bSJed Brown if (cellVert == v) { 17660a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[c]; 17670a96aa3bSJed Brown 17680a96aa3bSJed Brown conn->corner_to_tree[off] = (p4est_locidx_t) (p - cStart); 17690a96aa3bSJed Brown conn->corner_to_corner[off++] = (int8_t) p4estVert; 17700a96aa3bSJed Brown conn->tree_to_corner[P4EST_CHILDREN * (p - cStart) + p4estVert] = v - vStart; 17710a96aa3bSJed Brown } 17720a96aa3bSJed Brown } 17739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 17740a96aa3bSJed Brown } 17750a96aa3bSJed Brown } 17769566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star)); 17770a96aa3bSJed Brown } 17789566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ctt)); 17790a96aa3bSJed Brown 17800a96aa3bSJed Brown /* 5: Compute the coordinates */ 17810a96aa3bSJed Brown { 17820a96aa3bSJed Brown PetscInt coordDim; 17830a96aa3bSJed Brown 17849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim)); 17856858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 17860a96aa3bSJed Brown for (c = cStart; c < cEnd; c++) { 17870a96aa3bSJed Brown PetscInt dof; 17886858538eSMatthew G. Knepley PetscBool isDG; 17890a96aa3bSJed Brown PetscScalar *cellCoords = NULL; 17906858538eSMatthew G. Knepley const PetscScalar *array; 17910a96aa3bSJed Brown 17926858538eSMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 17936858538eSMatthew 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); 17940a96aa3bSJed Brown for (v = 0; v < P4EST_CHILDREN; v++) { 17950a96aa3bSJed Brown PetscInt i, lim = PetscMin(3, coordDim); 17960a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[v]; 17970a96aa3bSJed Brown 17980a96aa3bSJed Brown conn->tree_to_vertex[P4EST_CHILDREN * (c - cStart) + v] = P4EST_CHILDREN * (c - cStart) + v; 17990a96aa3bSJed Brown /* p4est vertices are always embedded in R^3 */ 18000a96aa3bSJed Brown for (i = 0; i < 3; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = 0.; 18010a96aa3bSJed Brown for (i = 0; i < lim; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = PetscRealPart(cellCoords[v * coordDim + i]); 18020a96aa3bSJed Brown } 18036858538eSMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 18040a96aa3bSJed Brown } 18050a96aa3bSJed Brown } 18060a96aa3bSJed Brown 18070a96aa3bSJed Brown #if defined(P4EST_ENABLE_DEBUG) 180808401ef6SPierre Jolivet PetscCheck(p4est_connectivity_is_valid(conn),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Plex to p4est conversion failed"); 18090a96aa3bSJed Brown #endif 18100a96aa3bSJed Brown 18110a96aa3bSJed Brown *connOut = conn; 18120a96aa3bSJed Brown 18130a96aa3bSJed Brown *tree_face_to_uniq = ttf; 18140a96aa3bSJed Brown 18150a96aa3bSJed Brown PetscFunctionReturn(0); 18160a96aa3bSJed Brown } 18170a96aa3bSJed Brown 18180a96aa3bSJed Brown static PetscErrorCode locidx_to_PetscInt(sc_array_t * array) 18190a96aa3bSJed Brown { 18200a96aa3bSJed Brown sc_array_t *newarray; 18210a96aa3bSJed Brown size_t zz, count = array->elem_count; 18220a96aa3bSJed Brown 18230a96aa3bSJed Brown PetscFunctionBegin; 182408401ef6SPierre Jolivet PetscCheck(array->elem_size == sizeof(p4est_locidx_t),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong locidx size"); 18250a96aa3bSJed Brown 18260a96aa3bSJed Brown if (sizeof(p4est_locidx_t) == sizeof(PetscInt)) PetscFunctionReturn(0); 18270a96aa3bSJed Brown 18280a96aa3bSJed Brown newarray = sc_array_new_size (sizeof(PetscInt), array->elem_count); 18290a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18300a96aa3bSJed Brown p4est_locidx_t il = *((p4est_locidx_t*) sc_array_index (array, zz)); 18310a96aa3bSJed Brown PetscInt *ip = (PetscInt*) sc_array_index (newarray, zz); 18320a96aa3bSJed Brown 18330a96aa3bSJed Brown *ip = (PetscInt) il; 18340a96aa3bSJed Brown } 18350a96aa3bSJed Brown 18360a96aa3bSJed Brown sc_array_reset (array); 18370a96aa3bSJed Brown sc_array_init_size (array, sizeof(PetscInt), count); 18380a96aa3bSJed Brown sc_array_copy (array, newarray); 18390a96aa3bSJed Brown sc_array_destroy (newarray); 18400a96aa3bSJed Brown PetscFunctionReturn(0); 18410a96aa3bSJed Brown } 18420a96aa3bSJed Brown 18430a96aa3bSJed Brown static PetscErrorCode coords_double_to_PetscScalar(sc_array_t * array, PetscInt dim) 18440a96aa3bSJed Brown { 18450a96aa3bSJed Brown sc_array_t *newarray; 18460a96aa3bSJed Brown size_t zz, count = array->elem_count; 18470a96aa3bSJed Brown 18480a96aa3bSJed Brown PetscFunctionBegin; 18491dca8a05SBarry Smith PetscCheck(array->elem_size == 3 * sizeof(double),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong coordinate size"); 18500a96aa3bSJed Brown #if !defined(PETSC_USE_COMPLEX) 18510a96aa3bSJed Brown if (sizeof(double) == sizeof(PetscScalar) && dim == 3) PetscFunctionReturn(0); 18520a96aa3bSJed Brown #endif 18530a96aa3bSJed Brown 18540a96aa3bSJed Brown newarray = sc_array_new_size (dim * sizeof(PetscScalar), array->elem_count); 18550a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18560a96aa3bSJed Brown int i; 18570a96aa3bSJed Brown double *id = (double*) sc_array_index (array, zz); 18580a96aa3bSJed Brown PetscScalar *ip = (PetscScalar*) sc_array_index (newarray, zz); 18590a96aa3bSJed Brown 18600a96aa3bSJed Brown for (i = 0; i < dim; i++) ip[i] = 0.; 18610a96aa3bSJed Brown for (i = 0; i < PetscMin(dim,3); i++) ip[i] = (PetscScalar) id[i]; 18620a96aa3bSJed Brown } 18630a96aa3bSJed Brown 18640a96aa3bSJed Brown sc_array_reset (array); 18650a96aa3bSJed Brown sc_array_init_size (array, dim * sizeof(PetscScalar), count); 18660a96aa3bSJed Brown sc_array_copy (array, newarray); 18670a96aa3bSJed Brown sc_array_destroy (newarray); 18680a96aa3bSJed Brown PetscFunctionReturn(0); 18690a96aa3bSJed Brown } 18700a96aa3bSJed Brown 18710a96aa3bSJed Brown static PetscErrorCode locidx_pair_to_PetscSFNode(sc_array_t * array) 18720a96aa3bSJed Brown { 18730a96aa3bSJed Brown sc_array_t *newarray; 18740a96aa3bSJed Brown size_t zz, count = array->elem_count; 18750a96aa3bSJed Brown 18760a96aa3bSJed Brown PetscFunctionBegin; 18771dca8a05SBarry Smith PetscCheck(array->elem_size == 2 * sizeof(p4est_locidx_t),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong locidx size"); 18780a96aa3bSJed Brown 18790a96aa3bSJed Brown newarray = sc_array_new_size (sizeof(PetscSFNode), array->elem_count); 18800a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18810a96aa3bSJed Brown p4est_locidx_t *il = (p4est_locidx_t*) sc_array_index (array, zz); 18820a96aa3bSJed Brown PetscSFNode *ip = (PetscSFNode*) sc_array_index (newarray, zz); 18830a96aa3bSJed Brown 18840a96aa3bSJed Brown ip->rank = (PetscInt) il[0]; 18850a96aa3bSJed Brown ip->index = (PetscInt) il[1]; 18860a96aa3bSJed Brown } 18870a96aa3bSJed Brown 18880a96aa3bSJed Brown sc_array_reset (array); 18890a96aa3bSJed Brown sc_array_init_size (array, sizeof(PetscSFNode), count); 18900a96aa3bSJed Brown sc_array_copy (array, newarray); 18910a96aa3bSJed Brown sc_array_destroy (newarray); 18920a96aa3bSJed Brown PetscFunctionReturn(0); 18930a96aa3bSJed Brown } 18940a96aa3bSJed Brown 18950a96aa3bSJed Brown static PetscErrorCode P4estToPlex_Local(p4est_t *p4est, DM * plex) 18960a96aa3bSJed Brown { 18970a96aa3bSJed Brown PetscFunctionBegin; 18980a96aa3bSJed Brown { 18990a96aa3bSJed Brown sc_array_t *points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 19000a96aa3bSJed Brown sc_array_t *cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 19010a96aa3bSJed Brown sc_array_t *cones = sc_array_new(sizeof(p4est_locidx_t)); 19020a96aa3bSJed Brown sc_array_t *cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 19030a96aa3bSJed Brown sc_array_t *coords = sc_array_new(3 * sizeof(double)); 19040a96aa3bSJed Brown sc_array_t *children = sc_array_new(sizeof(p4est_locidx_t)); 19050a96aa3bSJed Brown sc_array_t *parents = sc_array_new(sizeof(p4est_locidx_t)); 19060a96aa3bSJed Brown sc_array_t *childids = sc_array_new(sizeof(p4est_locidx_t)); 19070a96aa3bSJed Brown sc_array_t *leaves = sc_array_new(sizeof(p4est_locidx_t)); 19080a96aa3bSJed Brown sc_array_t *remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 19090a96aa3bSJed Brown p4est_locidx_t first_local_quad; 19100a96aa3bSJed Brown 1911792fecdfSBarry 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)); 19120a96aa3bSJed Brown 19139566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 19149566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 19159566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 19169566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 19179566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, P4EST_DIM)); 19180a96aa3bSJed Brown 19199566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PETSC_COMM_SELF,plex)); 19209566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*plex,P4EST_DIM)); 19219566063dSJacob 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)); 19229566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(*plex)); 19230a96aa3bSJed Brown sc_array_destroy (points_per_dim); 19240a96aa3bSJed Brown sc_array_destroy (cone_sizes); 19250a96aa3bSJed Brown sc_array_destroy (cones); 19260a96aa3bSJed Brown sc_array_destroy (cone_orientations); 19270a96aa3bSJed Brown sc_array_destroy (coords); 19280a96aa3bSJed Brown sc_array_destroy (children); 19290a96aa3bSJed Brown sc_array_destroy (parents); 19300a96aa3bSJed Brown sc_array_destroy (childids); 19310a96aa3bSJed Brown sc_array_destroy (leaves); 19320a96aa3bSJed Brown sc_array_destroy (remotes); 19330a96aa3bSJed Brown } 19340a96aa3bSJed Brown PetscFunctionReturn(0); 19350a96aa3bSJed Brown } 19360a96aa3bSJed Brown 19370a96aa3bSJed Brown #define DMReferenceTreeGetChildSymmetry_pforest _append_pforest(DMReferenceTreeGetChildSymmetry) 19380a96aa3bSJed Brown static PetscErrorCode DMReferenceTreeGetChildSymmetry_pforest(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB,PetscInt *childB) 19390a96aa3bSJed Brown { 19400a96aa3bSJed Brown PetscInt coneSize, dStart, dEnd, vStart, vEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 19410a96aa3bSJed Brown 19420a96aa3bSJed Brown PetscFunctionBegin; 19430a96aa3bSJed Brown if (parentOrientA == parentOrientB) { 19440a96aa3bSJed Brown if (childOrientB) *childOrientB = childOrientA; 19450a96aa3bSJed Brown if (childB) *childB = childA; 19460a96aa3bSJed Brown PetscFunctionReturn(0); 19470a96aa3bSJed Brown } 19489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,0,&vStart,&vEnd)); 19496aad120cSJose E. Roman if (childA >= vStart && childA < vEnd) { /* vertices (always in the middle) are invariant under rotation */ 19500a96aa3bSJed Brown if (childOrientB) *childOrientB = 0; 19510a96aa3bSJed Brown if (childB) *childB = childA; 19520a96aa3bSJed Brown PetscFunctionReturn(0); 19530a96aa3bSJed Brown } 19540a96aa3bSJed Brown for (dim = 0; dim < 3; dim++) { 19559566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd)); 19560a96aa3bSJed Brown if (parent >= dStart && parent <= dEnd) break; 19570a96aa3bSJed Brown } 195863a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %" PetscInt_FMT "-cells",dim); 195928b400f6SJacob Faibussowitsch PetscCheck(dim,PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children"); 19600a96aa3bSJed Brown if (childA < dStart || childA >= dEnd) { /* a 1-cell in a 2-cell */ 19610a96aa3bSJed Brown /* this is a lower-dimensional child: bootstrap */ 19620a96aa3bSJed Brown PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 19630a96aa3bSJed Brown const PetscInt *supp, *coneA, *coneB, *oA, *oB; 19640a96aa3bSJed Brown 19659566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm,childA,&size)); 19669566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm,childA,&supp)); 19670a96aa3bSJed Brown 19680a96aa3bSJed Brown /* find a point sA in supp(childA) that has the same parent */ 19690a96aa3bSJed Brown for (i = 0; i < size; i++) { 19700a96aa3bSJed Brown PetscInt sParent; 19710a96aa3bSJed Brown 19720a96aa3bSJed Brown sA = supp[i]; 19730a96aa3bSJed Brown if (sA == parent) continue; 19749566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,sA,&sParent,NULL)); 19750a96aa3bSJed Brown if (sParent == parent) break; 19760a96aa3bSJed Brown } 197708401ef6SPierre Jolivet PetscCheck(i != size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children"); 19780a96aa3bSJed Brown /* find out which point sB is in an equivalent position to sA under 19790a96aa3bSJed Brown * parentOrientB */ 19809566063dSJacob Faibussowitsch PetscCall(DMReferenceTreeGetChildSymmetry_pforest(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB)); 19819566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,sA,&sConeSize)); 19829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,sA,&coneA)); 19839566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,sB,&coneB)); 19849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm,sA,&oA)); 19859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm,sB,&oB)); 19860a96aa3bSJed Brown /* step through the cone of sA in natural order */ 19870a96aa3bSJed Brown for (i = 0; i < sConeSize; i++) { 19880a96aa3bSJed Brown if (coneA[i] == childA) { 19890a96aa3bSJed Brown /* if childA is at position i in coneA, 19900a96aa3bSJed Brown * then we want the point that is at sOrientB*i in coneB */ 19910a96aa3bSJed Brown PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize); 19920a96aa3bSJed Brown if (childB) *childB = coneB[j]; 19930a96aa3bSJed Brown if (childOrientB) { 19940a96aa3bSJed Brown DMPolytopeType ct; 19950a96aa3bSJed Brown PetscInt oBtrue; 19960a96aa3bSJed Brown 19979566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,childA,&coneSize)); 19980a96aa3bSJed Brown /* compose sOrientB and oB[j] */ 19991dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge"); 20000a96aa3bSJed Brown ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 20010a96aa3bSJed Brown /* we may have to flip an edge */ 20020a96aa3bSJed Brown oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientationInv(ct, -1, oB[j]); 20030a96aa3bSJed Brown oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 20040a96aa3bSJed Brown ABswap = DihedralSwap(coneSize,DMPolytopeConvertNewOrientation_Internal(ct, oA[i]),oBtrue); 20050a96aa3bSJed Brown *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 20060a96aa3bSJed Brown } 20070a96aa3bSJed Brown break; 20080a96aa3bSJed Brown } 20090a96aa3bSJed Brown } 201008401ef6SPierre Jolivet PetscCheck(i != sConeSize,PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch"); 20110a96aa3bSJed Brown PetscFunctionReturn(0); 20120a96aa3bSJed Brown } 20130a96aa3bSJed Brown /* get the cone size and symmetry swap */ 20149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,parent,&coneSize)); 20150a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 20160a96aa3bSJed Brown if (dim == 2) { 20170a96aa3bSJed Brown /* orientations refer to cones: we want them to refer to vertices: 20180a96aa3bSJed Brown * if it's a rotation, they are the same, but if the order is reversed, a 20190a96aa3bSJed Brown * permutation that puts side i first does *not* put vertex i first */ 20200a96aa3bSJed Brown oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 20210a96aa3bSJed Brown oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 20220a96aa3bSJed Brown ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 20230a96aa3bSJed Brown } else { 20240a96aa3bSJed Brown oAvert = parentOrientA; 20250a96aa3bSJed Brown oBvert = parentOrientB; 20260a96aa3bSJed Brown ABswapVert = ABswap; 20270a96aa3bSJed Brown } 20280a96aa3bSJed Brown if (childB) { 20290a96aa3bSJed Brown /* assume that each child corresponds to a vertex, in the same order */ 20300a96aa3bSJed Brown PetscInt p, posA = -1, numChildren, i; 20310a96aa3bSJed Brown const PetscInt *children; 20320a96aa3bSJed Brown 20330a96aa3bSJed Brown /* count which position the child is in */ 20349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,parent,&numChildren,&children)); 20350a96aa3bSJed Brown for (i = 0; i < numChildren; i++) { 20360a96aa3bSJed Brown p = children[i]; 20370a96aa3bSJed Brown if (p == childA) { 20380a96aa3bSJed Brown if (dim == 1) { 20390a96aa3bSJed Brown posA = i; 20400a96aa3bSJed Brown } else { /* 2D Morton to rotation */ 20410a96aa3bSJed Brown posA = (i & 2) ? (i ^ 1) : i; 20420a96aa3bSJed Brown } 20430a96aa3bSJed Brown break; 20440a96aa3bSJed Brown } 20450a96aa3bSJed Brown } 20460a96aa3bSJed Brown if (posA >= coneSize) { 20470a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not find childA in children of parent"); 20480a96aa3bSJed Brown } else { 20490a96aa3bSJed Brown /* figure out position B by applying ABswapVert */ 20500a96aa3bSJed Brown PetscInt posB, childIdB; 20510a96aa3bSJed Brown 20520a96aa3bSJed Brown posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 20530a96aa3bSJed Brown if (dim == 1) { 20540a96aa3bSJed Brown childIdB = posB; 20550a96aa3bSJed Brown } else { /* 2D rotation to Morton */ 20560a96aa3bSJed Brown childIdB = (posB & 2) ? (posB ^ 1) : posB; 20570a96aa3bSJed Brown } 20580a96aa3bSJed Brown if (childB) *childB = children[childIdB]; 20590a96aa3bSJed Brown } 20600a96aa3bSJed Brown } 20610a96aa3bSJed Brown if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 20620a96aa3bSJed Brown PetscFunctionReturn(0); 20630a96aa3bSJed Brown } 20640a96aa3bSJed Brown 20650a96aa3bSJed Brown #define DMCreateReferenceTree_pforest _append_pforest(DMCreateReferenceTree) 20660a96aa3bSJed Brown static PetscErrorCode DMCreateReferenceTree_pforest(MPI_Comm comm, DM *dm) 20670a96aa3bSJed Brown { 20680a96aa3bSJed Brown p4est_connectivity_t *refcube; 20690a96aa3bSJed Brown p4est_t *root, *refined; 20700a96aa3bSJed Brown DM dmRoot, dmRefined; 20710a96aa3bSJed Brown DM_Plex *mesh; 20720a96aa3bSJed Brown PetscMPIInt rank; 207366c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI) 207466c0a4b5SToby Isaac sc_MPI_Comm comm_self = sc_MPI_COMM_SELF; 207566c0a4b5SToby Isaac #else 207666c0a4b5SToby Isaac MPI_Comm comm_self = PETSC_COMM_SELF; 207766c0a4b5SToby Isaac #endif 20780a96aa3bSJed Brown 20790a96aa3bSJed Brown PetscFunctionBegin; 2080792fecdfSBarry Smith PetscCallP4estReturn(refcube,p4est_connectivity_new_byname,("unit")); 20810a96aa3bSJed Brown { /* [-1,1]^d geometry */ 20820a96aa3bSJed Brown PetscInt i, j; 20830a96aa3bSJed Brown 20840a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 20850a96aa3bSJed Brown for (j = 0; j < 3; j++) { 20860a96aa3bSJed Brown refcube->vertices[3 * i + j] *= 2.; 20870a96aa3bSJed Brown refcube->vertices[3 * i + j] -= 1.; 20880a96aa3bSJed Brown } 20890a96aa3bSJed Brown } 20900a96aa3bSJed Brown } 2091792fecdfSBarry Smith PetscCallP4estReturn(root,p4est_new,(comm_self,refcube,0,NULL,NULL)); 2092792fecdfSBarry Smith PetscCallP4estReturn(refined,p4est_new_ext,(comm_self,refcube,0,1,1,0,NULL,NULL)); 20939566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(root,&dmRoot)); 20949566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(refined,&dmRefined)); 20950a96aa3bSJed Brown { 20960a96aa3bSJed Brown #if !defined(P4_TO_P8) 20970a96aa3bSJed Brown PetscInt nPoints = 25; 20980a96aa3bSJed Brown PetscInt perm[25] = {0, 1, 2, 3, 20990a96aa3bSJed Brown 4, 12, 8, 14, 21000a96aa3bSJed Brown 6, 9, 15, 21010a96aa3bSJed Brown 5, 13, 10, 21020a96aa3bSJed Brown 7, 11, 21030a96aa3bSJed Brown 16, 22, 20, 24, 21040a96aa3bSJed Brown 17, 21, 21050a96aa3bSJed Brown 18, 23, 21060a96aa3bSJed Brown 19}; 21070a96aa3bSJed Brown PetscInt ident[25] = {0, 0, 0, 0, 21080a96aa3bSJed Brown 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 0, 21090a96aa3bSJed Brown 5, 6, 7, 8, 1, 2, 3, 4, 0}; 21100a96aa3bSJed Brown #else 21110a96aa3bSJed Brown PetscInt nPoints = 125; 21120a96aa3bSJed Brown PetscInt perm[125] = {0, 1, 2, 3, 4, 5, 6, 7, 21130a96aa3bSJed Brown 8, 32, 16, 36, 24, 40, 21140a96aa3bSJed Brown 12, 17, 37, 25, 41, 21150a96aa3bSJed Brown 9, 33, 20, 26, 42, 21160a96aa3bSJed Brown 13, 21, 27, 43, 21170a96aa3bSJed Brown 10, 34, 18, 38, 28, 21180a96aa3bSJed Brown 14, 19, 39, 29, 21190a96aa3bSJed Brown 11, 35, 22, 30, 21200a96aa3bSJed Brown 15, 23, 31, 21210a96aa3bSJed Brown 44, 84, 76, 92, 52, 86, 68, 94, 60, 78, 70, 96, 21220a96aa3bSJed Brown 45, 85, 77, 93, 54, 72, 62, 74, 21230a96aa3bSJed Brown 46, 80, 53, 87, 69, 95, 64, 82, 21240a96aa3bSJed Brown 47, 81, 55, 73, 66, 21250a96aa3bSJed Brown 48, 88, 56, 90, 61, 79, 71, 97, 21260a96aa3bSJed Brown 49, 89, 58, 63, 75, 21270a96aa3bSJed Brown 50, 57, 91, 65, 83, 21280a96aa3bSJed Brown 51, 59, 67, 21290a96aa3bSJed Brown 98, 106, 110, 122, 114, 120, 118, 124, 21300a96aa3bSJed Brown 99, 111, 115, 119, 21310a96aa3bSJed Brown 100, 107, 116, 121, 21320a96aa3bSJed Brown 101, 117, 21330a96aa3bSJed Brown 102, 108, 112, 123, 21340a96aa3bSJed Brown 103, 113, 21350a96aa3bSJed Brown 104, 109, 21360a96aa3bSJed Brown 105}; 21370a96aa3bSJed Brown PetscInt ident[125] = {0, 0, 0, 0, 0, 0, 0, 0, 21380a96aa3bSJed Brown 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 21390a96aa3bSJed Brown 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21400a96aa3bSJed Brown 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 21410a96aa3bSJed Brown 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 21420a96aa3bSJed Brown 0, 0, 0, 0, 0, 0, 21430a96aa3bSJed Brown 19, 20, 21, 22, 23, 24, 25, 26, 21440a96aa3bSJed Brown 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21450a96aa3bSJed Brown 1, 2, 3, 4, 5, 6, 21460a96aa3bSJed Brown 0}; 21470a96aa3bSJed Brown 21480a96aa3bSJed Brown #endif 21490a96aa3bSJed Brown IS permIS; 21500a96aa3bSJed Brown DM dmPerm; 21510a96aa3bSJed Brown 21529566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,nPoints,perm,PETSC_USE_POINTER,&permIS)); 21539566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dmRefined,permIS,&dmPerm)); 21540a96aa3bSJed Brown if (dmPerm) { 21559566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 21560a96aa3bSJed Brown dmRefined = dmPerm; 21570a96aa3bSJed Brown } 21589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 21590a96aa3bSJed Brown { 21600a96aa3bSJed Brown PetscInt p; 21619566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRoot,"identity")); 21629566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRefined,"identity")); 21630a96aa3bSJed Brown for (p = 0; p < P4EST_INSUL; p++) { 21649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dmRoot,"identity",p,p)); 21650a96aa3bSJed Brown } 21660a96aa3bSJed Brown for (p = 0; p < nPoints; p++) { 21679566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dmRefined,"identity",p,ident[p])); 21680a96aa3bSJed Brown } 21690a96aa3bSJed Brown } 21700a96aa3bSJed Brown } 21719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(dmRoot,dmRefined,"identity",dm)); 21720a96aa3bSJed Brown mesh = (DM_Plex*) (*dm)->data; 21730a96aa3bSJed Brown mesh->getchildsymmetry = DMReferenceTreeGetChildSymmetry_pforest; 21749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 21750a96aa3bSJed Brown if (rank == 0) { 21769566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRoot, NULL,"-dm_p4est_ref_root_view")); 21779566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined,NULL,"-dm_p4est_ref_refined_view")); 21789566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined,NULL,"-dm_p4est_ref_tree_view")); 21790a96aa3bSJed Brown } 21809566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 21819566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRoot)); 2182792fecdfSBarry Smith PetscCallP4est(p4est_destroy,(refined)); 2183792fecdfSBarry Smith PetscCallP4est(p4est_destroy,(root)); 2184792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy,(refcube)); 21850a96aa3bSJed Brown PetscFunctionReturn(0); 21860a96aa3bSJed Brown } 21870a96aa3bSJed Brown 21880a96aa3bSJed Brown static PetscErrorCode DMShareDiscretization(DM dmA, DM dmB) 21890a96aa3bSJed Brown { 21900a96aa3bSJed Brown void *ctx; 21910a96aa3bSJed Brown PetscInt num; 21920a96aa3bSJed Brown PetscReal val; 21930a96aa3bSJed Brown 21940a96aa3bSJed Brown PetscFunctionBegin; 21959566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmA,&ctx)); 21969566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(dmB,ctx)); 21979566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmA,dmB)); 21989566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dmA,&num,&val)); 21999566063dSJacob Faibussowitsch PetscCall(DMSetOutputSequenceNumber(dmB,num,val)); 22000a96aa3bSJed Brown if (dmB->localSection != dmA->localSection || dmB->globalSection != dmA->globalSection) { 22019566063dSJacob Faibussowitsch PetscCall(DMClearLocalVectors(dmB)); 22029566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->localSection)); 22039566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->localSection))); 22040a96aa3bSJed Brown dmB->localSection = dmA->localSection; 22059566063dSJacob Faibussowitsch PetscCall(DMClearGlobalVectors(dmB)); 22069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->globalSection)); 22079566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->globalSection))); 22080a96aa3bSJed Brown dmB->globalSection = dmA->globalSection; 22099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.section)); 22109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->defaultConstraint.section))); 22113b8ba7d1SJed Brown dmB->defaultConstraint.section = dmA->defaultConstraint.section; 22129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.mat)); 22139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(dmB->defaultConstraint.mat))); 22143b8ba7d1SJed Brown dmB->defaultConstraint.mat = dmA->defaultConstraint.mat; 22159566063dSJacob Faibussowitsch if (dmA->map) PetscCall(PetscLayoutReference(dmA->map, &dmB->map)); 22160a96aa3bSJed Brown } 22170a96aa3bSJed Brown if (dmB->sectionSF != dmA->sectionSF) { 22189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->sectionSF)); 22199566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&dmB->sectionSF)); 22200a96aa3bSJed Brown dmB->sectionSF = dmA->sectionSF; 22210a96aa3bSJed Brown } 22220a96aa3bSJed Brown PetscFunctionReturn(0); 22230a96aa3bSJed Brown } 22240a96aa3bSJed Brown 22250a96aa3bSJed Brown /* Get an SF that broadcasts a coarse-cell covering of the local fine cells */ 22260a96aa3bSJed Brown static PetscErrorCode DMPforestGetCellCoveringSF(MPI_Comm comm,p4est_t *p4estC, p4est_t *p4estF, PetscInt cStart, PetscInt cEnd, PetscSF *coveringSF) 22270a96aa3bSJed Brown { 22280a96aa3bSJed Brown PetscInt startF, endF, startC, endC, p, nLeaves; 22290a96aa3bSJed Brown PetscSFNode *leaves; 22300a96aa3bSJed Brown PetscSF sf; 22310a96aa3bSJed Brown PetscInt *recv, *send; 22320a96aa3bSJed Brown PetscMPIInt tag; 22330a96aa3bSJed Brown MPI_Request *recvReqs, *sendReqs; 22340a96aa3bSJed Brown PetscSection section; 22350a96aa3bSJed Brown 22360a96aa3bSJed Brown PetscFunctionBegin; 22379566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize,p4estC->mpirank,p4estF,p4estC,&startC,&endC)); 22389566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2*(endC-startC),&recv,endC-startC,&recvReqs)); 22399566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(comm,&tag)); 22400a96aa3bSJed Brown for (p = startC; p < endC; p++) { 22410a96aa3bSJed Brown recvReqs[p-startC] = MPI_REQUEST_NULL; /* just in case we don't initiate a receive */ 22420a96aa3bSJed Brown if (p4estC->global_first_quadrant[p] == p4estC->global_first_quadrant[p+1]) { /* empty coarse partition */ 22430a96aa3bSJed Brown recv[2*(p-startC)] = 0; 22440a96aa3bSJed Brown recv[2*(p-startC)+1] = 0; 22450a96aa3bSJed Brown continue; 22460a96aa3bSJed Brown } 22470a96aa3bSJed Brown 22489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(&recv[2*(p-startC)],2,MPIU_INT,p,tag,comm,&recvReqs[p-startC])); 22490a96aa3bSJed Brown } 22509566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize,p4estC->mpirank,p4estC,p4estF,&startF,&endF)); 22519566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2*(endF-startF),&send,endF-startF,&sendReqs)); 22520a96aa3bSJed Brown /* count the quadrants rank will send to each of [startF,endF) */ 22530a96aa3bSJed Brown for (p = startF; p < endF; p++) { 22540a96aa3bSJed Brown p4est_quadrant_t *myFineStart = &p4estF->global_first_position[p]; 22550a96aa3bSJed Brown p4est_quadrant_t *myFineEnd = &p4estF->global_first_position[p+1]; 22560a96aa3bSJed Brown PetscInt tStart = (PetscInt) myFineStart->p.which_tree; 22570a96aa3bSJed Brown PetscInt tEnd = (PetscInt) myFineEnd->p.which_tree; 22580a96aa3bSJed Brown PetscInt firstCell = -1, lastCell = -1; 22590a96aa3bSJed Brown p4est_tree_t *treeStart = &(((p4est_tree_t*) p4estC->trees->array)[tStart]); 22600a96aa3bSJed Brown p4est_tree_t *treeEnd = (size_t) tEnd < p4estC->trees->elem_count ? &(((p4est_tree_t*) p4estC->trees->array)[tEnd]) : NULL; 22610a96aa3bSJed Brown ssize_t overlapIndex; 22620a96aa3bSJed Brown 22630a96aa3bSJed Brown sendReqs[p-startF] = MPI_REQUEST_NULL; /* just in case we don't initiate a send */ 22640a96aa3bSJed Brown if (p4estF->global_first_quadrant[p] == p4estF->global_first_quadrant[p+1]) continue; 22650a96aa3bSJed Brown 22660a96aa3bSJed Brown /* locate myFineStart in (or before) a cell */ 22670a96aa3bSJed Brown if (treeStart->quadrants.elem_count) { 2268792fecdfSBarry Smith PetscCallP4estReturn(overlapIndex,sc_array_bsearch,(&(treeStart->quadrants),myFineStart,p4est_quadrant_disjoint)); 22690a96aa3bSJed Brown if (overlapIndex < 0) { 22700a96aa3bSJed Brown firstCell = 0; 22710a96aa3bSJed Brown } else { 22720a96aa3bSJed Brown firstCell = treeStart->quadrants_offset + overlapIndex; 22730a96aa3bSJed Brown } 22740a96aa3bSJed Brown } else { 22750a96aa3bSJed Brown firstCell = 0; 22760a96aa3bSJed Brown } 22770a96aa3bSJed Brown if (treeEnd && treeEnd->quadrants.elem_count) { 2278792fecdfSBarry Smith PetscCallP4estReturn(overlapIndex,sc_array_bsearch,(&(treeEnd->quadrants),myFineEnd,p4est_quadrant_disjoint)); 22790a96aa3bSJed Brown if (overlapIndex < 0) { /* all of this local section is overlapped */ 22800a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 22810a96aa3bSJed Brown } else { 22820a96aa3bSJed Brown p4est_quadrant_t *container = &(((p4est_quadrant_t*) treeEnd->quadrants.array)[overlapIndex]); 22830a96aa3bSJed Brown p4est_quadrant_t first_desc; 22840a96aa3bSJed Brown int equal; 22850a96aa3bSJed Brown 2286792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_first_descendant,(container,&first_desc,P4EST_QMAXLEVEL)); 2287792fecdfSBarry Smith PetscCallP4estReturn(equal,p4est_quadrant_is_equal,(myFineEnd,&first_desc)); 22880a96aa3bSJed Brown if (equal) { 22890a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex; 22900a96aa3bSJed Brown } else { 22910a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex + 1; 22920a96aa3bSJed Brown } 22930a96aa3bSJed Brown } 22940a96aa3bSJed Brown } else { 22950a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 22960a96aa3bSJed Brown } 22970a96aa3bSJed Brown send[2*(p-startF)] = firstCell; 22980a96aa3bSJed Brown send[2*(p-startF)+1] = lastCell - firstCell; 22999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(&send[2*(p-startF)],2,MPIU_INT,p,tag,comm,&sendReqs[p-startF])); 23000a96aa3bSJed Brown } 23019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endC-startC),recvReqs,MPI_STATUSES_IGNORE)); 23029566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,§ion)); 23039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section,startC,endC)); 23040a96aa3bSJed Brown for (p = startC; p < endC; p++) { 23050a96aa3bSJed Brown PetscInt numCells = recv[2*(p-startC)+1]; 23069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section,p,numCells)); 23070a96aa3bSJed Brown } 23089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 23099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section,&nLeaves)); 23109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves,&leaves)); 23110a96aa3bSJed Brown for (p = startC; p < endC; p++) { 23120a96aa3bSJed Brown PetscInt firstCell = recv[2*(p-startC)]; 23130a96aa3bSJed Brown PetscInt numCells = recv[2*(p-startC)+1]; 23140a96aa3bSJed Brown PetscInt off, i; 23150a96aa3bSJed Brown 23169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,p,&off)); 23170a96aa3bSJed Brown for (i = 0; i < numCells; i++) { 23180a96aa3bSJed Brown leaves[off+i].rank = p; 23190a96aa3bSJed Brown leaves[off+i].index = firstCell + i; 23200a96aa3bSJed Brown } 23210a96aa3bSJed Brown } 23229566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&sf)); 23239566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf,cEnd-cStart,nLeaves,NULL,PETSC_OWN_POINTER,leaves,PETSC_OWN_POINTER)); 23249566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 23259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endF-startF),sendReqs,MPI_STATUSES_IGNORE)); 23269566063dSJacob Faibussowitsch PetscCall(PetscFree2(send,sendReqs)); 23279566063dSJacob Faibussowitsch PetscCall(PetscFree2(recv,recvReqs)); 23280a96aa3bSJed Brown *coveringSF = sf; 23290a96aa3bSJed Brown PetscFunctionReturn(0); 23300a96aa3bSJed Brown } 23310a96aa3bSJed Brown 23320a96aa3bSJed Brown /* closure points for locally-owned cells */ 23330a96aa3bSJed Brown static PetscErrorCode DMPforestGetCellSFNodes(DM dm, PetscInt numClosureIndices, PetscInt *numClosurePoints, PetscSFNode **closurePoints,PetscBool redirect) 23340a96aa3bSJed Brown { 23350a96aa3bSJed Brown PetscInt cStart, cEnd; 23360a96aa3bSJed Brown PetscInt count, c; 23370a96aa3bSJed Brown PetscMPIInt rank; 23380a96aa3bSJed Brown PetscInt closureSize = -1; 23390a96aa3bSJed Brown PetscInt *closure = NULL; 23400a96aa3bSJed Brown PetscSF pointSF; 23410a96aa3bSJed Brown PetscInt nleaves, nroots; 23420a96aa3bSJed Brown const PetscInt *ilocal; 23430a96aa3bSJed Brown const PetscSFNode *iremote; 23440a96aa3bSJed Brown DM plex; 23450a96aa3bSJed Brown DM_Forest *forest; 23460a96aa3bSJed Brown DM_Forest_pforest *pforest; 23470a96aa3bSJed Brown 23480a96aa3bSJed Brown PetscFunctionBegin; 23490a96aa3bSJed Brown forest = (DM_Forest *) dm->data; 23500a96aa3bSJed Brown pforest = (DM_Forest_pforest *) forest->data; 23510a96aa3bSJed Brown cStart = pforest->cLocalStart; 23520a96aa3bSJed Brown cEnd = pforest->cLocalEnd; 23539566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 23549566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm,&pointSF)); 23559566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF,&nroots,&nleaves,&ilocal,&iremote)); 23560a96aa3bSJed Brown nleaves = PetscMax(0,nleaves); 23570a96aa3bSJed Brown nroots = PetscMax(0,nroots); 23580a96aa3bSJed Brown *numClosurePoints = numClosureIndices * (cEnd - cStart); 23599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numClosurePoints,closurePoints)); 23609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank)); 23610a96aa3bSJed Brown for (c = cStart, count = 0; c < cEnd; c++) { 23620a96aa3bSJed Brown PetscInt i; 23639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,c,PETSC_TRUE,&closureSize,&closure)); 23640a96aa3bSJed Brown 23650a96aa3bSJed Brown for (i = 0; i < numClosureIndices; i++, count++) { 23660a96aa3bSJed Brown PetscInt p = closure[2 * i]; 23670a96aa3bSJed Brown PetscInt loc = -1; 23680a96aa3bSJed Brown 23699566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p,nleaves,ilocal,&loc)); 23700a96aa3bSJed Brown if (redirect && loc >= 0) { 23710a96aa3bSJed Brown (*closurePoints)[count].rank = iremote[loc].rank; 23720a96aa3bSJed Brown (*closurePoints)[count].index = iremote[loc].index; 23730a96aa3bSJed Brown } else { 23740a96aa3bSJed Brown (*closurePoints)[count].rank = rank; 23750a96aa3bSJed Brown (*closurePoints)[count].index = p; 23760a96aa3bSJed Brown } 23770a96aa3bSJed Brown } 23789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,c,PETSC_TRUE,&closureSize,&closure)); 23790a96aa3bSJed Brown } 23800a96aa3bSJed Brown PetscFunctionReturn(0); 23810a96aa3bSJed Brown } 23820a96aa3bSJed Brown 23830a96aa3bSJed Brown static void MPIAPI DMPforestMaxSFNode(void *a, void *b, PetscMPIInt *len, MPI_Datatype *type) 23840a96aa3bSJed Brown { 23850a96aa3bSJed Brown PetscMPIInt i; 23860a96aa3bSJed Brown 23870a96aa3bSJed Brown for (i = 0; i < *len; i++) { 23880a96aa3bSJed Brown PetscSFNode *A = (PetscSFNode*)a; 23890a96aa3bSJed Brown PetscSFNode *B = (PetscSFNode*)b; 23900a96aa3bSJed Brown 23910a96aa3bSJed Brown if (B->rank < 0) *B = *A; 23920a96aa3bSJed Brown } 23930a96aa3bSJed Brown } 23940a96aa3bSJed Brown 23950a96aa3bSJed Brown static PetscErrorCode DMPforestGetTransferSF_Point(DM coarse, DM fine, PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 23960a96aa3bSJed Brown { 23970a96aa3bSJed Brown MPI_Comm comm; 23980a96aa3bSJed Brown PetscMPIInt rank, size; 23990a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 24000a96aa3bSJed Brown p4est_t *p4estC, *p4estF; 24010a96aa3bSJed Brown PetscInt numClosureIndices; 24020a96aa3bSJed Brown PetscInt numClosurePointsC, numClosurePointsF; 24030a96aa3bSJed Brown PetscSFNode *closurePointsC, *closurePointsF; 24040a96aa3bSJed Brown p4est_quadrant_t *coverQuads = NULL; 24050a96aa3bSJed Brown p4est_quadrant_t **treeQuads; 24060a96aa3bSJed Brown PetscInt *treeQuadCounts; 24070a96aa3bSJed Brown MPI_Datatype nodeType; 24080a96aa3bSJed Brown MPI_Datatype nodeClosureType; 24090a96aa3bSJed Brown MPI_Op sfNodeReduce; 24100a96aa3bSJed Brown p4est_topidx_t fltF, lltF, t; 24110a96aa3bSJed Brown DM plexC, plexF; 24120a96aa3bSJed Brown PetscInt pStartF, pEndF, pStartC, pEndC; 24130a96aa3bSJed Brown PetscBool saveInCoarse = PETSC_FALSE; 24140a96aa3bSJed Brown PetscBool saveInFine = PETSC_FALSE; 24150a96aa3bSJed Brown PetscBool formCids = (childIds != NULL) ? PETSC_TRUE : PETSC_FALSE; 24160a96aa3bSJed Brown PetscInt *cids = NULL; 24170a96aa3bSJed Brown 24180a96aa3bSJed Brown PetscFunctionBegin; 24190a96aa3bSJed Brown pforestC = (DM_Forest_pforest*) ((DM_Forest*) coarse->data)->data; 24200a96aa3bSJed Brown pforestF = (DM_Forest_pforest*) ((DM_Forest*) fine->data)->data; 24210a96aa3bSJed Brown p4estC = pforestC->forest; 24220a96aa3bSJed Brown p4estF = pforestF->forest; 242308401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo,PetscObjectComm((PetscObject)coarse),PETSC_ERR_ARG_INCOMP,"DM's must have the same base DM"); 24240a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 24259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 24269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 24279566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine,&plexF)); 24289566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF,&pStartF,&pEndF)); 24299566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse,&plexC)); 24309566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC,&pStartC,&pEndC)); 24310a96aa3bSJed Brown { /* check if the results have been cached */ 24320a96aa3bSJed Brown DM adaptCoarse, adaptFine; 24330a96aa3bSJed Brown 24349566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(coarse,&adaptCoarse)); 24359566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(fine,&adaptFine)); 24360a96aa3bSJed Brown if (adaptCoarse && adaptCoarse->data == fine->data) { /* coarse is adapted from fine */ 24370a96aa3bSJed Brown if (pforestC->pointSelfToAdaptSF) { 24389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(pforestC->pointSelfToAdaptSF))); 24390a96aa3bSJed Brown *sf = pforestC->pointSelfToAdaptSF; 24400a96aa3bSJed Brown if (childIds) { 24419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&cids)); 24429566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids,pforestC->pointSelfToAdaptCids,pEndF-pStartF)); 24430a96aa3bSJed Brown *childIds = cids; 24440a96aa3bSJed Brown } 24450a96aa3bSJed Brown PetscFunctionReturn(0); 24460a96aa3bSJed Brown } else { 24470a96aa3bSJed Brown saveInCoarse = PETSC_TRUE; 24480a96aa3bSJed Brown formCids = PETSC_TRUE; 24490a96aa3bSJed Brown } 24500a96aa3bSJed Brown } else if (adaptFine && adaptFine->data == coarse->data) { /* fine is adapted from coarse */ 24510a96aa3bSJed Brown if (pforestF->pointAdaptToSelfSF) { 24529566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(pforestF->pointAdaptToSelfSF))); 24530a96aa3bSJed Brown *sf = pforestF->pointAdaptToSelfSF; 24540a96aa3bSJed Brown if (childIds) { 24559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&cids)); 24569566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids,pforestF->pointAdaptToSelfCids,pEndF-pStartF)); 24570a96aa3bSJed Brown *childIds = cids; 24580a96aa3bSJed Brown } 24590a96aa3bSJed Brown PetscFunctionReturn(0); 24600a96aa3bSJed Brown } else { 24610a96aa3bSJed Brown saveInFine = PETSC_TRUE; 24620a96aa3bSJed Brown formCids = PETSC_TRUE; 24630a96aa3bSJed Brown } 24640a96aa3bSJed Brown } 24650a96aa3bSJed Brown } 24660a96aa3bSJed Brown 24670a96aa3bSJed Brown /* count the number of closure points that have dofs and create a list */ 24680a96aa3bSJed Brown numClosureIndices = P4EST_INSUL; 24690a96aa3bSJed Brown /* create the datatype */ 24709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(2,MPIU_INT,&nodeType)); 24719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 24729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(DMPforestMaxSFNode,PETSC_FALSE,&sfNodeReduce)); 24739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(numClosureIndices*2,MPIU_INT,&nodeClosureType)); 24749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeClosureType)); 24750a96aa3bSJed Brown /* everything has to go through cells: for each cell, create a list of the sfnodes in its closure */ 24760a96aa3bSJed Brown /* get lists of closure point SF nodes for every cell */ 24779566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(coarse,numClosureIndices,&numClosurePointsC,&closurePointsC,PETSC_TRUE)); 24789566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(fine ,numClosureIndices,&numClosurePointsF,&closurePointsF,PETSC_FALSE)); 24790a96aa3bSJed Brown /* create pointers for tree lists */ 24800a96aa3bSJed Brown fltF = p4estF->first_local_tree; 24810a96aa3bSJed Brown lltF = p4estF->last_local_tree; 24829566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(lltF + 1 - fltF, &treeQuads, lltF + 1 - fltF, &treeQuadCounts)); 24830a96aa3bSJed Brown /* if the partitions don't match, ship the coarse to cover the fine */ 24840a96aa3bSJed Brown if (size > 1) { 24850a96aa3bSJed Brown PetscInt p; 24860a96aa3bSJed Brown 24870a96aa3bSJed Brown for (p = 0; p < size; p++) { 24880a96aa3bSJed Brown int equal; 24890a96aa3bSJed Brown 2490792fecdfSBarry Smith PetscCallP4estReturn(equal,p4est_quadrant_is_equal_piggy,(&p4estC->global_first_position[p],&p4estF->global_first_position[p])); 24910a96aa3bSJed Brown if (!equal) break; 24920a96aa3bSJed Brown } 24930a96aa3bSJed Brown if (p < size) { /* non-matching distribution: send the coarse to cover the fine */ 24940a96aa3bSJed Brown PetscInt cStartC, cEndC; 24950a96aa3bSJed Brown PetscSF coveringSF; 24960a96aa3bSJed Brown PetscInt nleaves; 24970a96aa3bSJed Brown PetscInt count; 24980a96aa3bSJed Brown PetscSFNode *newClosurePointsC; 24990a96aa3bSJed Brown p4est_quadrant_t *coverQuadsSend; 25000a96aa3bSJed Brown p4est_topidx_t fltC = p4estC->first_local_tree; 25010a96aa3bSJed Brown p4est_topidx_t lltC = p4estC->last_local_tree; 25020a96aa3bSJed Brown p4est_topidx_t t; 25030a96aa3bSJed Brown PetscMPIInt blockSizes[4] = {P4EST_DIM,2,1,1}; 25040a96aa3bSJed Brown MPI_Aint blockOffsets[4] = {offsetof(p4est_quadrant_t,x), 25050a96aa3bSJed Brown offsetof(p4est_quadrant_t,level), 25060a96aa3bSJed Brown offsetof(p4est_quadrant_t,pad16), 25070a96aa3bSJed Brown offsetof(p4est_quadrant_t,p)}; 25080a96aa3bSJed Brown MPI_Datatype blockTypes[4] = {MPI_INT32_T,MPI_INT8_T,MPI_INT16_T,MPI_INT32_T/* p.which_tree */}; 25090a96aa3bSJed Brown MPI_Datatype quadStruct,quadType; 25100a96aa3bSJed Brown 25119566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC,0,&cStartC,&cEndC)); 25129566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellCoveringSF(comm,p4estC,p4estF,pforestC->cLocalStart,pforestC->cLocalEnd,&coveringSF)); 25139566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coveringSF,NULL,&nleaves,NULL,NULL)); 25149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numClosureIndices*nleaves,&newClosurePointsC)); 25159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves,&coverQuads)); 25169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEndC-cStartC,&coverQuadsSend)); 25170a96aa3bSJed Brown count = 0; 25180a96aa3bSJed Brown for (t = fltC; t <= lltC; t++) { /* unfortunately, we need to pack a send array, since quads are not stored packed in p4est */ 25190a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4estC->trees->array)[t]); 25200a96aa3bSJed Brown PetscInt q; 25210a96aa3bSJed Brown 25229566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&coverQuadsSend[count],tree->quadrants.array,tree->quadrants.elem_count * sizeof(p4est_quadrant_t))); 25230a96aa3bSJed Brown for (q = 0; (size_t) q < tree->quadrants.elem_count; q++) coverQuadsSend[count+q].p.which_tree = t; 25240a96aa3bSJed Brown count += tree->quadrants.elem_count; 25250a96aa3bSJed Brown } 25260a96aa3bSJed Brown /* p is of a union type p4est_quadrant_data, but only the p.which_tree field is active at this time. So, we 25270a96aa3bSJed Brown have a simple blockTypes[] to use. Note that quadStruct does not count potential padding in array of 25280a96aa3bSJed Brown p4est_quadrant_t. We have to call MPI_Type_create_resized() to change upper-bound of quadStruct. 25290a96aa3bSJed Brown */ 25309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(4,blockSizes,blockOffsets,blockTypes,&quadStruct)); 25319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_resized(quadStruct,0,sizeof(p4est_quadrant_t),&quadType)); 25329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&quadType)); 25339566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF,nodeClosureType,closurePointsC,newClosurePointsC,MPI_REPLACE)); 25349566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF,quadType,coverQuadsSend,coverQuads,MPI_REPLACE)); 25359566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF,nodeClosureType,closurePointsC,newClosurePointsC,MPI_REPLACE)); 25369566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF,quadType,coverQuadsSend,coverQuads,MPI_REPLACE)); 25379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadStruct)); 25389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadType)); 25399566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuadsSend)); 25409566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 25419566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coveringSF)); 25420a96aa3bSJed Brown closurePointsC = newClosurePointsC; 25430a96aa3bSJed Brown 25440a96aa3bSJed Brown /* assign tree quads based on locations in coverQuads */ 25450a96aa3bSJed Brown { 25460a96aa3bSJed Brown PetscInt q; 25470a96aa3bSJed Brown for (q = 0; q < nleaves; q++) { 25480a96aa3bSJed Brown p4est_locidx_t t = coverQuads[q].p.which_tree; 25490a96aa3bSJed Brown if (!treeQuadCounts[t-fltF]++) treeQuads[t-fltF] = &coverQuads[q]; 25500a96aa3bSJed Brown } 25510a96aa3bSJed Brown } 25520a96aa3bSJed Brown } 25530a96aa3bSJed Brown } 25540a96aa3bSJed Brown if (!coverQuads) { /* matching partitions: assign tree quads based on locations in p4est native arrays */ 25550a96aa3bSJed Brown for (t = fltF; t <= lltF; t++) { 25560a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4estC->trees->array)[t]); 25570a96aa3bSJed Brown 25580a96aa3bSJed Brown treeQuadCounts[t - fltF] = tree->quadrants.elem_count; 25590a96aa3bSJed Brown treeQuads[t - fltF] = (p4est_quadrant_t*) tree->quadrants.array; 25600a96aa3bSJed Brown } 25610a96aa3bSJed Brown } 25620a96aa3bSJed Brown 25630a96aa3bSJed Brown { 25640a96aa3bSJed Brown PetscInt p; 25650a96aa3bSJed Brown PetscInt cLocalStartF; 25660a96aa3bSJed Brown PetscSF pointSF; 25670a96aa3bSJed Brown PetscSFNode *roots; 25680a96aa3bSJed Brown PetscInt *rootType; 25690a96aa3bSJed Brown DM refTree = NULL; 25700a96aa3bSJed Brown DMLabel canonical; 25710a96aa3bSJed Brown PetscInt *childClosures[P4EST_CHILDREN] = {NULL}; 25720a96aa3bSJed Brown PetscInt *rootClosure = NULL; 25730a96aa3bSJed Brown PetscInt coarseOffset; 25740a96aa3bSJed Brown PetscInt numCoarseQuads; 25750a96aa3bSJed Brown 25769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&roots)); 25779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&rootType)); 25789566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(fine,&pointSF)); 25790a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 25800a96aa3bSJed Brown roots[p-pStartF].rank = -1; 25810a96aa3bSJed Brown roots[p-pStartF].index = -1; 25820a96aa3bSJed Brown rootType[p-pStartF] = -1; 25830a96aa3bSJed Brown } 25840a96aa3bSJed Brown if (formCids) { 25850a96aa3bSJed Brown PetscInt child; 25860a96aa3bSJed Brown 25879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&cids)); 25880a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) cids[p - pStartF] = -2; 25899566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF,&refTree)); 25909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree,0,PETSC_TRUE,NULL,&rootClosure)); 25910a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { /* get the closures of the child cells in the reference tree */ 25929566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree,child+1,PETSC_TRUE,NULL,&childClosures[child])); 25930a96aa3bSJed Brown } 25949566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree,"canonical",&canonical)); 25950a96aa3bSJed Brown } 25960a96aa3bSJed Brown cLocalStartF = pforestF->cLocalStart; 25970a96aa3bSJed Brown for (t = fltF, coarseOffset = 0, numCoarseQuads = 0; t <= lltF; t++, coarseOffset += numCoarseQuads) { 25980a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4estF->trees->array)[t]); 25990a96aa3bSJed Brown PetscInt numFineQuads = tree->quadrants.elem_count; 26000a96aa3bSJed Brown p4est_quadrant_t *coarseQuads = treeQuads[t - fltF]; 26010a96aa3bSJed Brown p4est_quadrant_t *fineQuads = (p4est_quadrant_t*) tree->quadrants.array; 26020a96aa3bSJed Brown PetscInt i, coarseCount = 0; 26030a96aa3bSJed Brown PetscInt offset = tree->quadrants_offset; 26040a96aa3bSJed Brown sc_array_t coarseQuadsArray; 26050a96aa3bSJed Brown 26060a96aa3bSJed Brown numCoarseQuads = treeQuadCounts[t - fltF]; 2607792fecdfSBarry Smith PetscCallP4est(sc_array_init_data,(&coarseQuadsArray,coarseQuads,sizeof(p4est_quadrant_t),(size_t) numCoarseQuads)); 26080a96aa3bSJed Brown for (i = 0; i < numFineQuads; i++) { 26090a96aa3bSJed Brown PetscInt c = i + offset; 26100a96aa3bSJed Brown p4est_quadrant_t *quad = &fineQuads[i]; 26110a96aa3bSJed Brown p4est_quadrant_t *quadCoarse = NULL; 26120a96aa3bSJed Brown ssize_t disjoint = -1; 26130a96aa3bSJed Brown 26140a96aa3bSJed Brown while (disjoint < 0 && coarseCount < numCoarseQuads) { 26150a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2616792fecdfSBarry Smith PetscCallP4estReturn(disjoint,p4est_quadrant_disjoint,(quadCoarse,quad)); 26170a96aa3bSJed Brown if (disjoint < 0) coarseCount++; 26180a96aa3bSJed Brown } 261908401ef6SPierre Jolivet PetscCheck(disjoint == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"did not find overlapping coarse quad"); 26200a96aa3bSJed Brown if (quadCoarse->level > quad->level || (quadCoarse->level == quad->level && !transferIdent)) { /* the "coarse" mesh is finer than the fine mesh at the point: continue */ 26210a96aa3bSJed Brown if (transferIdent) { /* find corners */ 26220a96aa3bSJed Brown PetscInt j = 0; 26230a96aa3bSJed Brown 26240a96aa3bSJed Brown do { 26250a96aa3bSJed Brown if (j < P4EST_CHILDREN) { 26260a96aa3bSJed Brown p4est_quadrant_t cornerQuad; 26270a96aa3bSJed Brown int equal; 26280a96aa3bSJed Brown 2629792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_descendant,(quad,&cornerQuad,j,quadCoarse->level)); 2630792fecdfSBarry Smith PetscCallP4estReturn(equal,p4est_quadrant_is_equal,(&cornerQuad,quadCoarse)); 26310a96aa3bSJed Brown if (equal) { 26320a96aa3bSJed Brown PetscInt petscJ = P4estVertToPetscVert[j]; 26330a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + (P4EST_INSUL - P4EST_CHILDREN) + petscJ].index; 26340a96aa3bSJed Brown PetscSFNode q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + (P4EST_INSUL - P4EST_CHILDREN) + petscJ]; 26350a96aa3bSJed Brown 26360a96aa3bSJed Brown roots[p-pStartF] = q; 26370a96aa3bSJed Brown rootType[p-pStartF] = PETSC_MAX_INT; 26380a96aa3bSJed Brown cids[p-pStartF] = -1; 26390a96aa3bSJed Brown j++; 26400a96aa3bSJed Brown } 26410a96aa3bSJed Brown } 26420a96aa3bSJed Brown coarseCount++; 26430a96aa3bSJed Brown disjoint = 1; 26440a96aa3bSJed Brown if (coarseCount < numCoarseQuads) { 26450a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2646792fecdfSBarry Smith PetscCallP4estReturn(disjoint,p4est_quadrant_disjoint,(quadCoarse,quad)); 26470a96aa3bSJed Brown } 26480a96aa3bSJed Brown } while (!disjoint); 26490a96aa3bSJed Brown } 26500a96aa3bSJed Brown continue; 26510a96aa3bSJed Brown } 26520a96aa3bSJed Brown if (quadCoarse->level == quad->level) { /* same quad present in coarse and fine mesh */ 26530a96aa3bSJed Brown PetscInt j; 26540a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 26550a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + j].index; 26560a96aa3bSJed Brown 26570a96aa3bSJed Brown roots[p-pStartF] = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + j]; 26580a96aa3bSJed Brown rootType[p-pStartF] = PETSC_MAX_INT; /* unconditionally accept */ 26590a96aa3bSJed Brown cids[p-pStartF] = -1; 26600a96aa3bSJed Brown } 26610a96aa3bSJed Brown } else { 26620a96aa3bSJed Brown PetscInt levelDiff = quad->level - quadCoarse->level; 26630a96aa3bSJed Brown PetscInt proposedCids[P4EST_INSUL] = {0}; 26640a96aa3bSJed Brown 26650a96aa3bSJed Brown if (formCids) { 26660a96aa3bSJed Brown PetscInt cl; 26670a96aa3bSJed Brown PetscInt *pointClosure = NULL; 26680a96aa3bSJed Brown int cid; 26690a96aa3bSJed Brown 267008401ef6SPierre Jolivet PetscCheck(levelDiff <= 1,PETSC_COMM_SELF,PETSC_ERR_USER,"Recursive child ids not implemented"); 2671792fecdfSBarry Smith PetscCallP4estReturn(cid,p4est_quadrant_child_id,(quad)); 26729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plexF,c + cLocalStartF,PETSC_TRUE,NULL,&pointClosure)); 26730a96aa3bSJed Brown for (cl = 0; cl < P4EST_INSUL; cl++) { 26740a96aa3bSJed Brown PetscInt p = pointClosure[2 * cl]; 26750a96aa3bSJed Brown PetscInt point = childClosures[cid][2 * cl]; 26760a96aa3bSJed Brown PetscInt ornt = childClosures[cid][2 * cl + 1]; 26770a96aa3bSJed Brown PetscInt newcid = -1; 26780a96aa3bSJed Brown DMPolytopeType ct; 26790a96aa3bSJed Brown 26800a96aa3bSJed Brown if (rootType[p-pStartF] == PETSC_MAX_INT) continue; 26819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, point, &ct)); 26820a96aa3bSJed Brown ornt = DMPolytopeConvertNewOrientation_Internal(ct, ornt); 26830a96aa3bSJed Brown if (!cl) { 26840a96aa3bSJed Brown newcid = cid + 1; 26850a96aa3bSJed Brown } else { 26860a96aa3bSJed Brown PetscInt rcl, parent, parentOrnt = 0; 26870a96aa3bSJed Brown 26889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree,point,&parent,NULL)); 26890a96aa3bSJed Brown if (parent == point) { 26900a96aa3bSJed Brown newcid = -1; 26910a96aa3bSJed Brown } else if (!parent) { /* in the root */ 26920a96aa3bSJed Brown newcid = point; 26930a96aa3bSJed Brown } else { 26940a96aa3bSJed Brown DMPolytopeType rct = DM_POLYTOPE_UNKNOWN; 26950a96aa3bSJed Brown 26960a96aa3bSJed Brown for (rcl = 1; rcl < P4EST_INSUL; rcl++) { 26970a96aa3bSJed Brown if (rootClosure[2 * rcl] == parent) { 26989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, parent, &rct)); 26990a96aa3bSJed Brown parentOrnt = DMPolytopeConvertNewOrientation_Internal(rct, rootClosure[2 * rcl + 1]); 27000a96aa3bSJed Brown break; 27010a96aa3bSJed Brown } 27020a96aa3bSJed Brown } 270308401ef6SPierre Jolivet PetscCheck(rcl < P4EST_INSUL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Couldn't find parent in root closure"); 27049566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(refTree,parent,parentOrnt,ornt,point,DMPolytopeConvertNewOrientation_Internal(rct, pointClosure[2 * rcl + 1]),NULL,&newcid)); 27050a96aa3bSJed Brown } 27060a96aa3bSJed Brown } 27070a96aa3bSJed Brown if (newcid >= 0) { 27080a96aa3bSJed Brown 27090a96aa3bSJed Brown if (canonical) { 27109566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical,newcid,&newcid)); 27110a96aa3bSJed Brown } 27120a96aa3bSJed Brown proposedCids[cl] = newcid; 27130a96aa3bSJed Brown } 27140a96aa3bSJed Brown } 27159566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plexF,c + cLocalStartF,PETSC_TRUE,NULL,&pointClosure)); 27160a96aa3bSJed Brown } 27170a96aa3bSJed Brown p4est_qcoord_t coarseBound[2][P4EST_DIM] = {{quadCoarse->x,quadCoarse->y, 27180a96aa3bSJed Brown #if defined(P4_TO_P8) 27190a96aa3bSJed Brown quadCoarse->z 27200a96aa3bSJed Brown #endif 27210a96aa3bSJed Brown },{0}}; 27220a96aa3bSJed Brown p4est_qcoord_t fineBound[2][P4EST_DIM] = {{quad->x,quad->y, 27230a96aa3bSJed Brown #if defined(P4_TO_P8) 27240a96aa3bSJed Brown quad->z 27250a96aa3bSJed Brown #endif 27260a96aa3bSJed Brown },{0}}; 27270a96aa3bSJed Brown PetscInt j; 27280a96aa3bSJed Brown for (j = 0; j < P4EST_DIM; j++) { /* get the coordinates of cell boundaries in each direction */ 27290a96aa3bSJed Brown coarseBound[1][j] = coarseBound[0][j] + P4EST_QUADRANT_LEN(quadCoarse->level); 27300a96aa3bSJed Brown fineBound[1][j] = fineBound[0][j] + P4EST_QUADRANT_LEN(quad->level); 27310a96aa3bSJed Brown } 27320a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 27330a96aa3bSJed Brown PetscInt l, p; 27340a96aa3bSJed Brown PetscSFNode q; 27350a96aa3bSJed Brown 27360a96aa3bSJed Brown p = closurePointsF[numClosureIndices * c + j].index; 27370a96aa3bSJed Brown if (rootType[p-pStartF] == PETSC_MAX_INT) continue; 27380a96aa3bSJed Brown if (j == 0) { /* volume: ancestor is volume */ 27390a96aa3bSJed Brown l = 0; 27400a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES) { /* facet */ 27410a96aa3bSJed Brown PetscInt face = PetscFaceToP4estFace[j - 1]; 27420a96aa3bSJed Brown PetscInt direction = face / 2; 27430a96aa3bSJed Brown PetscInt coarseFace = -1; 27440a96aa3bSJed Brown 27450a96aa3bSJed Brown if (coarseBound[face % 2][direction] == fineBound[face % 2][direction]) { 27460a96aa3bSJed Brown coarseFace = face; 27470a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27480a96aa3bSJed Brown } else { 27490a96aa3bSJed Brown l = 0; 27500a96aa3bSJed Brown } 27510a96aa3bSJed Brown #if defined(P4_TO_P8) 27520a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES + P8EST_EDGES) { 27530a96aa3bSJed Brown PetscInt edge = PetscEdgeToP4estEdge[j - (1 + P4EST_FACES)]; 27540a96aa3bSJed Brown PetscInt direction = edge / 4; 27550a96aa3bSJed Brown PetscInt mod = edge % 4; 27560a96aa3bSJed Brown PetscInt coarseEdge = -1, coarseFace = -1; 27570a96aa3bSJed Brown PetscInt minDir = PetscMin((direction + 1) % 3,(direction + 2) % 3); 27580a96aa3bSJed Brown PetscInt maxDir = PetscMax((direction + 1) % 3,(direction + 2) % 3); 27590a96aa3bSJed Brown PetscBool dirTest[2]; 27600a96aa3bSJed Brown 27610a96aa3bSJed Brown dirTest[0] = (PetscBool) (coarseBound[mod % 2][minDir] == fineBound[mod % 2][minDir]); 27620a96aa3bSJed Brown dirTest[1] = (PetscBool) (coarseBound[mod / 2][maxDir] == fineBound[mod / 2][maxDir]); 27630a96aa3bSJed Brown 27640a96aa3bSJed Brown if (dirTest[0] && dirTest[1]) { /* fine edge falls on coarse edge */ 27650a96aa3bSJed Brown coarseEdge = edge; 27660a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 27670a96aa3bSJed Brown } else if (dirTest[0]) { /* fine edge falls on a coarse face in the minDir direction */ 27680a96aa3bSJed Brown coarseFace = 2 * minDir + (mod % 2); 27690a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27700a96aa3bSJed Brown } else if (dirTest[1]) { /* fine edge falls on a coarse face in the maxDir direction */ 27710a96aa3bSJed Brown coarseFace = 2 * maxDir + (mod / 2); 27720a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27730a96aa3bSJed Brown } else { 27740a96aa3bSJed Brown l = 0; 27750a96aa3bSJed Brown } 27760a96aa3bSJed Brown #endif 27770a96aa3bSJed Brown } else { 27780a96aa3bSJed Brown PetscInt vertex = PetscVertToP4estVert[P4EST_CHILDREN - (P4EST_INSUL - j)]; 27790a96aa3bSJed Brown PetscBool dirTest[P4EST_DIM]; 27800a96aa3bSJed Brown PetscInt m; 27810a96aa3bSJed Brown PetscInt numMatch = 0; 27820a96aa3bSJed Brown PetscInt coarseVertex = -1, coarseFace = -1; 27830a96aa3bSJed Brown #if defined(P4_TO_P8) 27840a96aa3bSJed Brown PetscInt coarseEdge = -1; 27850a96aa3bSJed Brown #endif 27860a96aa3bSJed Brown 27870a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27880a96aa3bSJed Brown dirTest[m] = (PetscBool) (coarseBound[(vertex >> m) & 1][m] == fineBound[(vertex >> m) & 1][m]); 27890a96aa3bSJed Brown if (dirTest[m]) numMatch++; 27900a96aa3bSJed Brown } 27910a96aa3bSJed Brown if (numMatch == P4EST_DIM) { /* vertex on vertex */ 27920a96aa3bSJed Brown coarseVertex = vertex; 27930a96aa3bSJed Brown l = P4EST_INSUL - (P4EST_CHILDREN - P4estVertToPetscVert[coarseVertex]); 27940a96aa3bSJed Brown } else if (numMatch == 1) { /* vertex on face */ 27950a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27960a96aa3bSJed Brown if (dirTest[m]) { 27970a96aa3bSJed Brown coarseFace = 2 * m + ((vertex >> m) & 1); 27980a96aa3bSJed Brown break; 27990a96aa3bSJed Brown } 28000a96aa3bSJed Brown } 28010a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 28020a96aa3bSJed Brown #if defined(P4_TO_P8) 28030a96aa3bSJed Brown } else if (numMatch == 2) { /* vertex on edge */ 28040a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 28050a96aa3bSJed Brown if (!dirTest[m]) { 28060a96aa3bSJed Brown PetscInt otherDir1 = (m + 1) % 3; 28070a96aa3bSJed Brown PetscInt otherDir2 = (m + 2) % 3; 28080a96aa3bSJed Brown PetscInt minDir = PetscMin(otherDir1,otherDir2); 28090a96aa3bSJed Brown PetscInt maxDir = PetscMax(otherDir1,otherDir2); 28100a96aa3bSJed Brown 28110a96aa3bSJed Brown coarseEdge = m * 4 + 2 * ((vertex >> maxDir) & 1) + ((vertex >> minDir) & 1); 28120a96aa3bSJed Brown break; 28130a96aa3bSJed Brown } 28140a96aa3bSJed Brown } 28150a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 28160a96aa3bSJed Brown #endif 28170a96aa3bSJed Brown } else { /* volume */ 28180a96aa3bSJed Brown l = 0; 28190a96aa3bSJed Brown } 28200a96aa3bSJed Brown } 28210a96aa3bSJed Brown q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + l]; 28220a96aa3bSJed Brown if (l > rootType[p-pStartF]) { 28230a96aa3bSJed Brown if (l >= P4EST_INSUL - P4EST_CHILDREN) { /* vertex on vertex: unconditional acceptance */ 28240a96aa3bSJed Brown if (transferIdent) { 28250a96aa3bSJed Brown roots[p-pStartF] = q; 28260a96aa3bSJed Brown rootType[p-pStartF] = PETSC_MAX_INT; 28270a96aa3bSJed Brown if (formCids) cids[p-pStartF] = -1; 28280a96aa3bSJed Brown } 28290a96aa3bSJed Brown } else { 28300a96aa3bSJed Brown PetscInt k, thisp = p, limit; 28310a96aa3bSJed Brown 28320a96aa3bSJed Brown roots[p-pStartF] = q; 28330a96aa3bSJed Brown rootType[p-pStartF] = l; 28340a96aa3bSJed Brown if (formCids) cids[p - pStartF] = proposedCids[j]; 28350a96aa3bSJed Brown limit = transferIdent ? levelDiff : (levelDiff - 1); 28360a96aa3bSJed Brown for (k = 0; k < limit; k++) { 28370a96aa3bSJed Brown PetscInt parent; 28380a96aa3bSJed Brown 28399566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plexF,thisp,&parent,NULL)); 28400a96aa3bSJed Brown if (parent == thisp) break; 28410a96aa3bSJed Brown 28420a96aa3bSJed Brown roots[parent-pStartF] = q; 28430a96aa3bSJed Brown rootType[parent-pStartF] = PETSC_MAX_INT; 28440a96aa3bSJed Brown if (formCids) cids[parent-pStartF] = -1; 28450a96aa3bSJed Brown thisp = parent; 28460a96aa3bSJed Brown } 28470a96aa3bSJed Brown } 28480a96aa3bSJed Brown } 28490a96aa3bSJed Brown } 28500a96aa3bSJed Brown } 28510a96aa3bSJed Brown } 28520a96aa3bSJed Brown } 28530a96aa3bSJed Brown 28540a96aa3bSJed 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 */ 28550a96aa3bSJed Brown if (size > 1) { 28560a96aa3bSJed Brown PetscInt *rootTypeCopy, p; 28570a96aa3bSJed Brown 28589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&rootTypeCopy)); 28599566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(rootTypeCopy,rootType,pEndF-pStartF)); 2860*57168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPI_MAX)); 2861*57168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPI_MAX)); 28629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPI_REPLACE)); 28639566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPI_REPLACE)); 28640a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28650a96aa3bSJed 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 */ 28660a96aa3bSJed Brown roots[p-pStartF].rank = -1; 28670a96aa3bSJed Brown roots[p-pStartF].index = -1; 28680a96aa3bSJed Brown } 28690a96aa3bSJed Brown if (formCids && rootTypeCopy[p-pStartF] == PETSC_MAX_INT) { 28700a96aa3bSJed Brown cids[p-pStartF] = -1; /* we have found an antecedent that is the same: no child id */ 28710a96aa3bSJed Brown } 28720a96aa3bSJed Brown } 28739566063dSJacob Faibussowitsch PetscCall(PetscFree(rootTypeCopy)); 28749566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF,nodeType,roots,roots,sfNodeReduce)); 28759566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF,nodeType,roots,roots,sfNodeReduce)); 28769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF,nodeType,roots,roots,MPI_REPLACE)); 28779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF,nodeType,roots,roots,MPI_REPLACE)); 28780a96aa3bSJed Brown } 28799566063dSJacob Faibussowitsch PetscCall(PetscFree(rootType)); 28800a96aa3bSJed Brown 28810a96aa3bSJed Brown { 28820a96aa3bSJed Brown PetscInt numRoots; 28830a96aa3bSJed Brown PetscInt numLeaves; 28840a96aa3bSJed Brown PetscInt *leaves; 28850a96aa3bSJed Brown PetscSFNode *iremote; 28860a96aa3bSJed Brown /* count leaves */ 28870a96aa3bSJed Brown 28880a96aa3bSJed Brown numRoots = pEndC - pStartC; 28890a96aa3bSJed Brown 28900a96aa3bSJed Brown numLeaves = 0; 28910a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28920a96aa3bSJed Brown if (roots[p-pStartF].index >= 0) numLeaves++; 28930a96aa3bSJed Brown } 28949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves,&leaves)); 28959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves,&iremote)); 28960a96aa3bSJed Brown numLeaves = 0; 28970a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28980a96aa3bSJed Brown if (roots[p-pStartF].index >= 0) { 28990a96aa3bSJed Brown leaves[numLeaves] = p-pStartF; 29000a96aa3bSJed Brown iremote[numLeaves] = roots[p-pStartF]; 29010a96aa3bSJed Brown numLeaves++; 29020a96aa3bSJed Brown } 29030a96aa3bSJed Brown } 29049566063dSJacob Faibussowitsch PetscCall(PetscFree(roots)); 29059566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,sf)); 29060a96aa3bSJed Brown if (numLeaves == (pEndF-pStartF)) { 29079566063dSJacob Faibussowitsch PetscCall(PetscFree(leaves)); 29089566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf,numRoots,numLeaves,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER)); 29090a96aa3bSJed Brown } else { 29109566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf,numRoots,numLeaves,leaves,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER)); 29110a96aa3bSJed Brown } 29120a96aa3bSJed Brown } 29130a96aa3bSJed Brown if (formCids) { 29140a96aa3bSJed Brown PetscSF pointSF; 29150a96aa3bSJed Brown PetscInt child; 29160a96aa3bSJed Brown 29179566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF,&refTree)); 29189566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plexF,&pointSF)); 2919*57168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF,MPIU_INT,cids,cids,MPI_MAX)); 2920*57168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF,MPIU_INT,cids,cids,MPI_MAX)); 29210a96aa3bSJed Brown if (childIds) *childIds = cids; 29220a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { 29239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree,child+1,PETSC_TRUE,NULL,&childClosures[child])); 29240a96aa3bSJed Brown } 29259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree,0,PETSC_TRUE,NULL,&rootClosure)); 29260a96aa3bSJed Brown } 29270a96aa3bSJed Brown } 29280a96aa3bSJed Brown if (saveInCoarse) { /* cache results */ 29299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 29300a96aa3bSJed Brown pforestC->pointSelfToAdaptSF = *sf; 29310a96aa3bSJed Brown if (!childIds) { 29320a96aa3bSJed Brown pforestC->pointSelfToAdaptCids = cids; 29330a96aa3bSJed Brown } else { 29349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&pforestC->pointSelfToAdaptCids)); 29359566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestC->pointSelfToAdaptCids,cids,pEndF-pStartF)); 29360a96aa3bSJed Brown } 29370a96aa3bSJed Brown } else if (saveInFine) { 29389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 29390a96aa3bSJed Brown pforestF->pointAdaptToSelfSF = *sf; 29400a96aa3bSJed Brown if (!childIds) { 29410a96aa3bSJed Brown pforestF->pointAdaptToSelfCids = cids; 29420a96aa3bSJed Brown } else { 29439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&pforestF->pointAdaptToSelfCids)); 29449566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestF->pointAdaptToSelfCids,cids,pEndF-pStartF)); 29450a96aa3bSJed Brown } 29460a96aa3bSJed Brown } 29479566063dSJacob Faibussowitsch PetscCall(PetscFree2(treeQuads,treeQuadCounts)); 29489566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuads)); 29499566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 29509566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsF)); 29519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeClosureType)); 29529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&sfNodeReduce)); 29539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 29540a96aa3bSJed Brown PetscFunctionReturn(0); 29550a96aa3bSJed Brown } 29560a96aa3bSJed Brown 29570a96aa3bSJed Brown /* children are sf leaves of parents */ 29580a96aa3bSJed Brown static PetscErrorCode DMPforestGetTransferSF_Internal(DM coarse, DM fine, const PetscInt dofPerDim[], PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 29590a96aa3bSJed Brown { 29600a96aa3bSJed Brown MPI_Comm comm; 2961d70f29a3SPierre Jolivet PetscMPIInt rank; 29620a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 29630a96aa3bSJed Brown DM plexC, plexF; 29640a96aa3bSJed Brown PetscInt pStartC, pEndC, pStartF, pEndF; 29650a96aa3bSJed Brown PetscSF pointTransferSF; 29660a96aa3bSJed Brown PetscBool allOnes = PETSC_TRUE; 29670a96aa3bSJed Brown 29680a96aa3bSJed Brown PetscFunctionBegin; 29690a96aa3bSJed Brown pforestC = (DM_Forest_pforest*) ((DM_Forest*) coarse->data)->data; 29700a96aa3bSJed Brown pforestF = (DM_Forest_pforest*) ((DM_Forest*) fine->data)->data; 297108401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo,PetscObjectComm((PetscObject)coarse),PETSC_ERR_ARG_INCOMP,"DM's must have the same base DM"); 29720a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 29739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 29740a96aa3bSJed Brown 29750a96aa3bSJed Brown { 29760a96aa3bSJed Brown PetscInt i; 29770a96aa3bSJed Brown for (i = 0; i <= P4EST_DIM; i++) { 29780a96aa3bSJed Brown if (dofPerDim[i] != 1) { 29790a96aa3bSJed Brown allOnes = PETSC_FALSE; 29800a96aa3bSJed Brown break; 29810a96aa3bSJed Brown } 29820a96aa3bSJed Brown } 29830a96aa3bSJed Brown } 29849566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Point(coarse,fine,&pointTransferSF,transferIdent,childIds)); 29850a96aa3bSJed Brown if (allOnes) { 29860a96aa3bSJed Brown *sf = pointTransferSF; 29870a96aa3bSJed Brown PetscFunctionReturn(0); 29880a96aa3bSJed Brown } 29890a96aa3bSJed Brown 29909566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine,&plexF)); 29919566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF,&pStartF,&pEndF)); 29929566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse,&plexC)); 29939566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC,&pStartC,&pEndC)); 29940a96aa3bSJed Brown { 29950a96aa3bSJed Brown PetscInt numRoots; 29960a96aa3bSJed Brown PetscInt numLeaves; 29970a96aa3bSJed Brown const PetscInt *leaves; 29980a96aa3bSJed Brown const PetscSFNode *iremote; 29990a96aa3bSJed Brown PetscInt d; 30000a96aa3bSJed Brown PetscSection leafSection, rootSection; 30010a96aa3bSJed Brown /* count leaves */ 30020a96aa3bSJed Brown 30039566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointTransferSF,&numRoots,&numLeaves,&leaves,&iremote)); 30049566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,&rootSection)); 30059566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,&leafSection)); 30069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection,pStartC,pEndC)); 30079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafSection,pStartF,pEndF)); 30080a96aa3bSJed Brown 30090a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 30100a96aa3bSJed Brown PetscInt startC, endC, e; 30110a96aa3bSJed Brown 30129566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC,P4EST_DIM-d,&startC,&endC)); 30130a96aa3bSJed Brown for (e = startC; e < endC; e++) { 30149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootSection,e,dofPerDim[d])); 30150a96aa3bSJed Brown } 30160a96aa3bSJed Brown } 30170a96aa3bSJed Brown 30180a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 30190a96aa3bSJed Brown PetscInt startF, endF, e; 30200a96aa3bSJed Brown 30219566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexF,P4EST_DIM-d,&startF,&endF)); 30220a96aa3bSJed Brown for (e = startF; e < endF; e++) { 30239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(leafSection,e,dofPerDim[d])); 30240a96aa3bSJed Brown } 30250a96aa3bSJed Brown } 30260a96aa3bSJed Brown 30279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 30289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSection)); 30290a96aa3bSJed Brown { 30300a96aa3bSJed Brown PetscInt nroots, nleaves; 30310a96aa3bSJed Brown PetscInt *mine, i, p; 30320a96aa3bSJed Brown PetscInt *offsets, *offsetsRoot; 30330a96aa3bSJed Brown PetscSFNode *remote; 30340a96aa3bSJed Brown 30359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&offsets)); 30369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC-pStartC,&offsetsRoot)); 30370a96aa3bSJed Brown for (p = pStartC; p < pEndC; p++) { 30389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection,p,&offsetsRoot[p-pStartC])); 30390a96aa3bSJed Brown } 30409566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointTransferSF,MPIU_INT,offsetsRoot,offsets,MPI_REPLACE)); 30419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointTransferSF,MPIU_INT,offsetsRoot,offsets,MPI_REPLACE)); 30429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection,&nroots)); 30430a96aa3bSJed Brown nleaves = 0; 30440a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 30450a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 30460a96aa3bSJed Brown PetscInt dof; 30470a96aa3bSJed Brown 30489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection,leaf,&dof)); 30490a96aa3bSJed Brown nleaves += dof; 30500a96aa3bSJed Brown } 30519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves,&mine)); 30529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves,&remote)); 30530a96aa3bSJed Brown nleaves = 0; 30540a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 30550a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 30560a96aa3bSJed Brown PetscInt dof; 30570a96aa3bSJed Brown PetscInt off, j; 30580a96aa3bSJed Brown 30599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection,leaf,&dof)); 30609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection,leaf,&off)); 30610a96aa3bSJed Brown for (j = 0; j < dof; j++) { 30620a96aa3bSJed Brown remote[nleaves].rank = iremote[i].rank; 30630a96aa3bSJed Brown remote[nleaves].index = offsets[leaf] + j; 30640a96aa3bSJed Brown mine[nleaves++] = off + j; 30650a96aa3bSJed Brown } 30660a96aa3bSJed Brown } 30679566063dSJacob Faibussowitsch PetscCall(PetscFree(offsetsRoot)); 30689566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 30699566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,sf)); 30709566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf,nroots,nleaves,mine,PETSC_OWN_POINTER,remote,PETSC_OWN_POINTER)); 30710a96aa3bSJed Brown } 30729566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 30739566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 30749566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointTransferSF)); 30750a96aa3bSJed Brown } 30760a96aa3bSJed Brown PetscFunctionReturn(0); 30770a96aa3bSJed Brown } 30780a96aa3bSJed Brown 30790a96aa3bSJed Brown static PetscErrorCode DMPforestGetTransferSF(DM dmA, DM dmB, const PetscInt dofPerDim[], PetscSF *sfAtoB, PetscSF *sfBtoA) 30800a96aa3bSJed Brown { 30810a96aa3bSJed Brown DM adaptA, adaptB; 30820a96aa3bSJed Brown DMAdaptFlag purpose; 30830a96aa3bSJed Brown 30840a96aa3bSJed Brown PetscFunctionBegin; 30859566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmA,&adaptA)); 30869566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmB,&adaptB)); 30870a96aa3bSJed Brown /* it is more efficient when the coarser mesh is the first argument: reorder if we know one is coarser than the other */ 30880a96aa3bSJed Brown if (adaptA && adaptA->data == dmB->data) { /* dmA was adapted from dmB */ 30899566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmA,&purpose)); 30900a96aa3bSJed Brown if (purpose == DM_ADAPT_REFINE) { 30919566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 30920a96aa3bSJed Brown PetscFunctionReturn(0); 30930a96aa3bSJed Brown } 30940a96aa3bSJed Brown } else if (adaptB && adaptB->data == dmA->data) { /* dmB was adapted from dmA */ 30959566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmB,&purpose)); 30960a96aa3bSJed Brown if (purpose == DM_ADAPT_COARSEN) { 30979566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 30980a96aa3bSJed Brown PetscFunctionReturn(0); 30990a96aa3bSJed Brown } 31000a96aa3bSJed Brown } 31011baa6e33SBarry Smith if (sfAtoB) PetscCall(DMPforestGetTransferSF_Internal(dmA,dmB,dofPerDim,sfAtoB,PETSC_TRUE,NULL)); 31021baa6e33SBarry Smith if (sfBtoA) PetscCall(DMPforestGetTransferSF_Internal(dmB,dmA,dofPerDim,sfBtoA,(PetscBool) (sfAtoB == NULL),NULL)); 31030a96aa3bSJed Brown PetscFunctionReturn(0); 31040a96aa3bSJed Brown } 31050a96aa3bSJed Brown 31060a96aa3bSJed Brown static PetscErrorCode DMPforestLabelsInitialize(DM dm, DM plex) 31070a96aa3bSJed Brown { 31080a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 31090a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 31100a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, cStart, cEnd, fStart, fEnd, eStart, eEnd, vStart, vEnd; 31110a96aa3bSJed Brown PetscInt cStartBase, cEndBase, fStartBase, fEndBase, vStartBase, vEndBase, eStartBase, eEndBase; 31120a96aa3bSJed Brown PetscInt pStart, pEnd, pStartBase, pEndBase, p; 31130a96aa3bSJed Brown DM base; 31140a96aa3bSJed Brown PetscInt *star = NULL, starSize; 31150a96aa3bSJed Brown DMLabelLink next = dm->labels; 31160a96aa3bSJed Brown PetscInt guess = 0; 31170a96aa3bSJed Brown p4est_topidx_t num_trees = pforest->topo->conn->num_trees; 31180a96aa3bSJed Brown 31190a96aa3bSJed Brown PetscFunctionBegin; 31200a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 31210a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 31220a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 31239566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 31240a96aa3bSJed Brown if (!base) { 31250a96aa3bSJed Brown if (pforest->ghostName) { /* insert a label to make the boundaries, with stratum values denoting which face of the element touches the boundary */ 31260a96aa3bSJed Brown p4est_connectivity_t *conn = pforest->topo->conn; 31270a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 31280a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t*) p4est->trees->array; 31290a96aa3bSJed Brown p4est_topidx_t t, flt = p4est->first_local_tree; 31300a96aa3bSJed Brown p4est_topidx_t llt = pforest->forest->last_local_tree; 31310a96aa3bSJed Brown DMLabel ghostLabel; 31320a96aa3bSJed Brown PetscInt c; 31330a96aa3bSJed Brown 31349566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(plex,pforest->ghostName)); 31359566063dSJacob Faibussowitsch PetscCall(DMGetLabel(plex,pforest->ghostName,&ghostLabel)); 31360a96aa3bSJed Brown for (c = cLocalStart, t = flt; t <= llt; t++) { 31370a96aa3bSJed Brown p4est_tree_t *tree = &trees[t]; 31380a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t*) tree->quadrants.array; 31390a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 31400a96aa3bSJed Brown PetscInt q; 31410a96aa3bSJed Brown 31420a96aa3bSJed Brown for (q = 0; q < numQuads; q++, c++) { 31430a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[q]; 31440a96aa3bSJed Brown PetscInt f; 31450a96aa3bSJed Brown 31460a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++) { 31470a96aa3bSJed Brown p4est_quadrant_t neigh; 31480a96aa3bSJed Brown int isOutside; 31490a96aa3bSJed Brown 3150792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor,(quad,f,&neigh)); 3151792fecdfSBarry Smith PetscCallP4estReturn(isOutside,p4est_quadrant_is_outside_face,(&neigh)); 31520a96aa3bSJed Brown if (isOutside) { 31530a96aa3bSJed Brown p4est_topidx_t nt; 31540a96aa3bSJed Brown PetscInt nf; 31550a96aa3bSJed Brown 31560a96aa3bSJed Brown nt = conn->tree_to_tree[t * P4EST_FACES + f]; 31570a96aa3bSJed Brown nf = (PetscInt) conn->tree_to_face[t * P4EST_FACES + f]; 31580a96aa3bSJed Brown nf = nf % P4EST_FACES; 31590a96aa3bSJed Brown if (nt == t && nf == f) { 31600a96aa3bSJed Brown PetscInt plexF = P4estFaceToPetscFace[f]; 31610a96aa3bSJed Brown const PetscInt *cone; 31620a96aa3bSJed Brown 31639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(plex,c,&cone)); 31649566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ghostLabel,cone[plexF],plexF+1)); 31650a96aa3bSJed Brown } 31660a96aa3bSJed Brown } 31670a96aa3bSJed Brown } 31680a96aa3bSJed Brown } 31690a96aa3bSJed Brown } 31700a96aa3bSJed Brown } 31710a96aa3bSJed Brown PetscFunctionReturn(0); 31720a96aa3bSJed Brown } 31739566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base,0,&cStartBase,&cEndBase)); 31749566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base,1,&fStartBase,&fEndBase)); 31759566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base,P4EST_DIM-1,&eStartBase,&eEndBase)); 31769566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(base,0,&vStartBase,&vEndBase)); 31770a96aa3bSJed Brown 31789566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex,0,&cStart,&cEnd)); 31799566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex,1,&fStart,&fEnd)); 31809566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex,P4EST_DIM-1,&eStart,&eEnd)); 31819566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex,0,&vStart,&vEnd)); 31820a96aa3bSJed Brown 31839566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex,&pStart,&pEnd)); 31849566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(base,&pStartBase,&pEndBase)); 31850a96aa3bSJed Brown /* go through the mesh: use star to find a quadrant that borders a point. Use the closure to determine the 31860a96aa3bSJed Brown * orientation of the quadrant relative to that point. Use that to relate the point to the numbering in the base 31870a96aa3bSJed Brown * mesh, and extract a label value (since the base mesh is redundantly distributed, can be found locally). */ 31880a96aa3bSJed Brown while (next) { 31890a96aa3bSJed Brown DMLabel baseLabel; 31900a96aa3bSJed Brown DMLabel label = next->label; 31910a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK, isSpmap; 31920a96aa3bSJed Brown const char *name; 31930a96aa3bSJed Brown 31949566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) label, &name)); 31959566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"depth",&isDepth)); 31960a96aa3bSJed Brown if (isDepth) { 31970a96aa3bSJed Brown next = next->next; 31980a96aa3bSJed Brown continue; 31990a96aa3bSJed Brown } 32009566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"celltype",&isCellType)); 32010a96aa3bSJed Brown if (isCellType) { 32020a96aa3bSJed Brown next = next->next; 32030a96aa3bSJed Brown continue; 32040a96aa3bSJed Brown } 32059566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"ghost",&isGhost)); 32060a96aa3bSJed Brown if (isGhost) { 32070a96aa3bSJed Brown next = next->next; 32080a96aa3bSJed Brown continue; 32090a96aa3bSJed Brown } 32109566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"vtk",&isVTK)); 32110a96aa3bSJed Brown if (isVTK) { 32120a96aa3bSJed Brown next = next->next; 32130a96aa3bSJed Brown continue; 32140a96aa3bSJed Brown } 32159566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"_forest_base_subpoint_map",&isSpmap)); 32160a96aa3bSJed Brown if (!isSpmap) { 32179566063dSJacob Faibussowitsch PetscCall(DMGetLabel(base,name,&baseLabel)); 32180a96aa3bSJed Brown if (!baseLabel) { 32190a96aa3bSJed Brown next = next->next; 32200a96aa3bSJed Brown continue; 32210a96aa3bSJed Brown } 32229566063dSJacob Faibussowitsch PetscCall(DMLabelCreateIndex(baseLabel,pStartBase,pEndBase)); 32230a96aa3bSJed Brown } else baseLabel = NULL; 32240a96aa3bSJed Brown 32250a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 32260a96aa3bSJed Brown PetscInt s, c = -1, l; 32270a96aa3bSJed Brown PetscInt *closure = NULL, closureSize; 32280a96aa3bSJed Brown p4est_quadrant_t * ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 32290a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t*) pforest->forest->trees->array; 32300a96aa3bSJed Brown p4est_quadrant_t * q; 32310a96aa3bSJed Brown PetscInt t, val; 32320a96aa3bSJed Brown PetscBool zerosupportpoint = PETSC_FALSE; 32330a96aa3bSJed Brown 32349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,p,PETSC_FALSE,&starSize,&star)); 32350a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 32360a96aa3bSJed Brown PetscInt point = star[2*s]; 32370a96aa3bSJed Brown 32380a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 32399566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,point,PETSC_TRUE,&closureSize,&closure)); 32400a96aa3bSJed Brown for (l = 0; l < closureSize; l++) { 32410a96aa3bSJed Brown PetscInt qParent = closure[2 * l], q, pp = p, pParent = p; 32420a96aa3bSJed Brown do { /* check parents of q */ 32430a96aa3bSJed Brown q = qParent; 32440a96aa3bSJed Brown if (q == p) { 32450a96aa3bSJed Brown c = point; 32460a96aa3bSJed Brown break; 32470a96aa3bSJed Brown } 32489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&qParent,NULL)); 32490a96aa3bSJed Brown } while (qParent != q); 32500a96aa3bSJed Brown if (c != -1) break; 32519566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,pp,&pParent,NULL)); 32520a96aa3bSJed Brown q = closure[2 * l]; 32530a96aa3bSJed Brown while (pParent != pp) { /* check parents of p */ 32540a96aa3bSJed Brown pp = pParent; 32550a96aa3bSJed Brown if (pp == q) { 32560a96aa3bSJed Brown c = point; 32570a96aa3bSJed Brown break; 32580a96aa3bSJed Brown } 32599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,pp,&pParent,NULL)); 32600a96aa3bSJed Brown } 32610a96aa3bSJed Brown if (c != -1) break; 32620a96aa3bSJed Brown } 32639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,point,PETSC_TRUE,NULL,&closure)); 32640a96aa3bSJed Brown if (l < closureSize) break; 32650a96aa3bSJed Brown } else { 32660a96aa3bSJed Brown PetscInt supportSize; 32670a96aa3bSJed Brown 32689566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(plex,point,&supportSize)); 32690a96aa3bSJed Brown zerosupportpoint = (PetscBool) (zerosupportpoint || !supportSize); 32700a96aa3bSJed Brown } 32710a96aa3bSJed Brown } 32720a96aa3bSJed Brown if (c < 0) { 32730a96aa3bSJed Brown const char* prefix; 32740a96aa3bSJed Brown PetscBool print = PETSC_FALSE; 32750a96aa3bSJed Brown 32769566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix)); 32779566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options,prefix,"-dm_forest_print_label_error",&print,NULL)); 32780a96aa3bSJed Brown if (print) { 32790a96aa3bSJed Brown PetscInt i; 32800a96aa3bSJed Brown 328163a3b9bcSJacob 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)); 328263a3b9bcSJacob 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])); 32830a96aa3bSJed Brown } 32849566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,p,PETSC_FALSE,NULL,&star)); 32850a96aa3bSJed Brown if (zerosupportpoint) continue; 328663a3b9bcSJacob Faibussowitsch else 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"); 32870a96aa3bSJed Brown } 32889566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,p,PETSC_FALSE,NULL,&star)); 32890a96aa3bSJed Brown 32900a96aa3bSJed Brown if (c < cLocalStart) { 32910a96aa3bSJed Brown /* get from the beginning of the ghost layer */ 32920a96aa3bSJed Brown q = &(ghosts[c]); 32930a96aa3bSJed Brown t = (PetscInt) q->p.which_tree; 32940a96aa3bSJed Brown } else if (c < cLocalEnd) { 32950a96aa3bSJed Brown PetscInt lo = 0, hi = num_trees; 32960a96aa3bSJed Brown /* get from local quadrants: have to find the right tree */ 32970a96aa3bSJed Brown 32980a96aa3bSJed Brown c -= cLocalStart; 32990a96aa3bSJed Brown 33000a96aa3bSJed Brown do { 33010a96aa3bSJed Brown p4est_tree_t *tree; 33020a96aa3bSJed Brown 33031dca8a05SBarry Smith PetscCheck(guess >= lo && guess < num_trees && lo < hi,PETSC_COMM_SELF,PETSC_ERR_PLIB,"failed binary search"); 33040a96aa3bSJed Brown tree = &trees[guess]; 33050a96aa3bSJed Brown if (c < tree->quadrants_offset) { 33060a96aa3bSJed Brown hi = guess; 33070a96aa3bSJed Brown } else if (c < tree->quadrants_offset + (PetscInt) tree->quadrants.elem_count) { 33080a96aa3bSJed Brown q = &((p4est_quadrant_t *)tree->quadrants.array)[c - (PetscInt) tree->quadrants_offset]; 33090a96aa3bSJed Brown t = guess; 33100a96aa3bSJed Brown break; 33110a96aa3bSJed Brown } else { 33120a96aa3bSJed Brown lo = guess + 1; 33130a96aa3bSJed Brown } 33140a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 33150a96aa3bSJed Brown } while (1); 33160a96aa3bSJed Brown } else { 33170a96aa3bSJed Brown /* get from the end of the ghost layer */ 33180a96aa3bSJed Brown c -= (cLocalEnd - cLocalStart); 33190a96aa3bSJed Brown 33200a96aa3bSJed Brown q = &(ghosts[c]); 33210a96aa3bSJed Brown t = (PetscInt) q->p.which_tree; 33220a96aa3bSJed Brown } 33230a96aa3bSJed Brown 33240a96aa3bSJed Brown if (l == 0) { /* cell */ 33250a96aa3bSJed Brown if (baseLabel) { 33269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,t+cStartBase,&val)); 33270a96aa3bSJed Brown } else { 33280a96aa3bSJed Brown val = t+cStartBase; 33290a96aa3bSJed Brown } 33309566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33310a96aa3bSJed Brown } else if (l >= 1 && l < 1 + P4EST_FACES) { /* facet */ 33320a96aa3bSJed Brown p4est_quadrant_t nq; 33330a96aa3bSJed Brown int isInside; 33340a96aa3bSJed Brown 33350a96aa3bSJed Brown l = PetscFaceToP4estFace[l - 1]; 3336792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor,(q,l,&nq)); 3337792fecdfSBarry Smith PetscCallP4estReturn(isInside,p4est_quadrant_is_inside_root,(&nq)); 33380a96aa3bSJed Brown if (isInside) { 33390a96aa3bSJed Brown /* this facet is in the interior of a tree, so it inherits the label of the tree */ 33400a96aa3bSJed Brown if (baseLabel) { 33419566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,t+cStartBase,&val)); 33420a96aa3bSJed Brown } else { 33430a96aa3bSJed Brown val = t+cStartBase; 33440a96aa3bSJed Brown } 33459566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33460a96aa3bSJed Brown } else { 33470a96aa3bSJed Brown PetscInt f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + l]; 33480a96aa3bSJed Brown 33490a96aa3bSJed Brown if (baseLabel) { 33509566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,f+fStartBase,&val)); 33510a96aa3bSJed Brown } else { 33520a96aa3bSJed Brown val = f+fStartBase; 33530a96aa3bSJed Brown } 33549566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33550a96aa3bSJed Brown } 33560a96aa3bSJed Brown #if defined(P4_TO_P8) 33570a96aa3bSJed Brown } else if (l >= 1 + P4EST_FACES && l < 1 + P4EST_FACES + P8EST_EDGES) { /* edge */ 33580a96aa3bSJed Brown p4est_quadrant_t nq; 33590a96aa3bSJed Brown int isInside; 33600a96aa3bSJed Brown 33610a96aa3bSJed Brown l = PetscEdgeToP4estEdge[l - (1 + P4EST_FACES)]; 3362792fecdfSBarry Smith PetscCallP4est(p8est_quadrant_edge_neighbor,(q,l,&nq)); 3363792fecdfSBarry Smith PetscCallP4estReturn(isInside,p4est_quadrant_is_inside_root,(&nq)); 33640a96aa3bSJed Brown if (isInside) { 33650a96aa3bSJed Brown /* this edge is in the interior of a tree, so it inherits the label of the tree */ 33660a96aa3bSJed Brown if (baseLabel) { 33679566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,t+cStartBase,&val)); 33680a96aa3bSJed Brown } else { 33690a96aa3bSJed Brown val = t+cStartBase; 33700a96aa3bSJed Brown } 33719566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33720a96aa3bSJed Brown } else { 33730a96aa3bSJed Brown int isOutsideFace; 33740a96aa3bSJed Brown 3375792fecdfSBarry Smith PetscCallP4estReturn(isOutsideFace,p4est_quadrant_is_outside_face,(&nq)); 33760a96aa3bSJed Brown if (isOutsideFace) { 33770a96aa3bSJed Brown PetscInt f; 33780a96aa3bSJed Brown 33790a96aa3bSJed Brown if (nq.x < 0) { 33800a96aa3bSJed Brown f = 0; 33810a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 33820a96aa3bSJed Brown f = 1; 33830a96aa3bSJed Brown } else if (nq.y < 0) { 33840a96aa3bSJed Brown f = 2; 33850a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 33860a96aa3bSJed Brown f = 3; 33870a96aa3bSJed Brown } else if (nq.z < 0) { 33880a96aa3bSJed Brown f = 4; 33890a96aa3bSJed Brown } else { 33900a96aa3bSJed Brown f = 5; 33910a96aa3bSJed Brown } 33920a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 33930a96aa3bSJed Brown if (baseLabel) { 33949566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,f+fStartBase,&val)); 33950a96aa3bSJed Brown } else { 33960a96aa3bSJed Brown val = f+fStartBase; 33970a96aa3bSJed Brown } 33989566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33990a96aa3bSJed Brown } else { /* the quadrant edge corresponds to the tree edge */ 34000a96aa3bSJed Brown PetscInt e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + l]; 34010a96aa3bSJed Brown 34020a96aa3bSJed Brown if (baseLabel) { 34039566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,e+eStartBase,&val)); 34040a96aa3bSJed Brown } else { 34050a96aa3bSJed Brown val = e+eStartBase; 34060a96aa3bSJed Brown } 34079566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 34080a96aa3bSJed Brown } 34090a96aa3bSJed Brown } 34100a96aa3bSJed Brown #endif 34110a96aa3bSJed Brown } else { /* vertex */ 34120a96aa3bSJed Brown p4est_quadrant_t nq; 34130a96aa3bSJed Brown int isInside; 34140a96aa3bSJed Brown 34150a96aa3bSJed Brown #if defined(P4_TO_P8) 34160a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES + P8EST_EDGES)]; 34170a96aa3bSJed Brown #else 34180a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES)]; 34190a96aa3bSJed Brown #endif 3420792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_neighbor,(q,l,&nq)); 3421792fecdfSBarry Smith PetscCallP4estReturn(isInside,p4est_quadrant_is_inside_root,(&nq)); 34220a96aa3bSJed Brown if (isInside) { 34230a96aa3bSJed Brown if (baseLabel) { 34249566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,t+cStartBase,&val)); 34250a96aa3bSJed Brown } else { 34260a96aa3bSJed Brown val = t+cStartBase; 34270a96aa3bSJed Brown } 34289566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 34290a96aa3bSJed Brown } else { 34300a96aa3bSJed Brown int isOutside; 34310a96aa3bSJed Brown 3432792fecdfSBarry Smith PetscCallP4estReturn(isOutside,p4est_quadrant_is_outside_face,(&nq)); 34330a96aa3bSJed Brown if (isOutside) { 34340a96aa3bSJed Brown PetscInt f = -1; 34350a96aa3bSJed Brown 34360a96aa3bSJed Brown if (nq.x < 0) { 34370a96aa3bSJed Brown f = 0; 34380a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 34390a96aa3bSJed Brown f = 1; 34400a96aa3bSJed Brown } else if (nq.y < 0) { 34410a96aa3bSJed Brown f = 2; 34420a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 34430a96aa3bSJed Brown f = 3; 34440a96aa3bSJed Brown #if defined(P4_TO_P8) 34450a96aa3bSJed Brown } else if (nq.z < 0) { 34460a96aa3bSJed Brown f = 4; 34470a96aa3bSJed Brown } else { 34480a96aa3bSJed Brown f = 5; 34490a96aa3bSJed Brown #endif 34500a96aa3bSJed Brown } 34510a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 34520a96aa3bSJed Brown if (baseLabel) { 34539566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,f+fStartBase,&val)); 34540a96aa3bSJed Brown } else { 34550a96aa3bSJed Brown val = f+fStartBase; 34560a96aa3bSJed Brown } 34579566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 34580a96aa3bSJed Brown continue; 34590a96aa3bSJed Brown } 34600a96aa3bSJed Brown #if defined(P4_TO_P8) 3461792fecdfSBarry Smith PetscCallP4estReturn(isOutside,p8est_quadrant_is_outside_edge,(&nq)); 34620a96aa3bSJed Brown if (isOutside) { 34630a96aa3bSJed Brown /* outside edge */ 34640a96aa3bSJed Brown PetscInt e = -1; 34650a96aa3bSJed Brown 34660a96aa3bSJed Brown if (nq.x >= 0 && nq.x < P4EST_ROOT_LEN) { 34670a96aa3bSJed Brown if (nq.z < 0) { 34680a96aa3bSJed Brown if (nq.y < 0) { 34690a96aa3bSJed Brown e = 0; 34700a96aa3bSJed Brown } else { 34710a96aa3bSJed Brown e = 1; 34720a96aa3bSJed Brown } 34730a96aa3bSJed Brown } else { 34740a96aa3bSJed Brown if (nq.y < 0) { 34750a96aa3bSJed Brown e = 2; 34760a96aa3bSJed Brown } else { 34770a96aa3bSJed Brown e = 3; 34780a96aa3bSJed Brown } 34790a96aa3bSJed Brown } 34800a96aa3bSJed Brown } else if (nq.y >= 0 && nq.y < P4EST_ROOT_LEN) { 34810a96aa3bSJed Brown if (nq.z < 0) { 34820a96aa3bSJed Brown if (nq.x < 0) { 34830a96aa3bSJed Brown e = 4; 34840a96aa3bSJed Brown } else { 34850a96aa3bSJed Brown e = 5; 34860a96aa3bSJed Brown } 34870a96aa3bSJed Brown } else { 34880a96aa3bSJed Brown if (nq.x < 0) { 34890a96aa3bSJed Brown e = 6; 34900a96aa3bSJed Brown } else { 34910a96aa3bSJed Brown e = 7; 34920a96aa3bSJed Brown } 34930a96aa3bSJed Brown } 34940a96aa3bSJed Brown } else { 34950a96aa3bSJed Brown if (nq.y < 0) { 34960a96aa3bSJed Brown if (nq.x < 0) { 34970a96aa3bSJed Brown e = 8; 34980a96aa3bSJed Brown } else { 34990a96aa3bSJed Brown e = 9; 35000a96aa3bSJed Brown } 35010a96aa3bSJed Brown } else { 35020a96aa3bSJed Brown if (nq.x < 0) { 35030a96aa3bSJed Brown e = 10; 35040a96aa3bSJed Brown } else { 35050a96aa3bSJed Brown e = 11; 35060a96aa3bSJed Brown } 35070a96aa3bSJed Brown } 35080a96aa3bSJed Brown } 35090a96aa3bSJed Brown 35100a96aa3bSJed Brown e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + e]; 35110a96aa3bSJed Brown if (baseLabel) { 35129566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,e+eStartBase,&val)); 35130a96aa3bSJed Brown } else { 35140a96aa3bSJed Brown val = e+eStartBase; 35150a96aa3bSJed Brown } 35169566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 35170a96aa3bSJed Brown continue; 35180a96aa3bSJed Brown } 35190a96aa3bSJed Brown #endif 35200a96aa3bSJed Brown { 35210a96aa3bSJed Brown /* outside vertex: same corner as quadrant corner */ 35220a96aa3bSJed Brown PetscInt v = pforest->topo->conn->tree_to_corner[P4EST_CHILDREN * t + l]; 35230a96aa3bSJed Brown 35240a96aa3bSJed Brown if (baseLabel) { 35259566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,v+vStartBase,&val)); 35260a96aa3bSJed Brown } else { 35270a96aa3bSJed Brown val = v+vStartBase; 35280a96aa3bSJed Brown } 35299566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 35300a96aa3bSJed Brown } 35310a96aa3bSJed Brown } 35320a96aa3bSJed Brown } 35330a96aa3bSJed Brown } 35340a96aa3bSJed Brown next = next->next; 35350a96aa3bSJed Brown } 35360a96aa3bSJed Brown PetscFunctionReturn(0); 35370a96aa3bSJed Brown } 35380a96aa3bSJed Brown 35390a96aa3bSJed Brown static PetscErrorCode DMPforestLabelsFinalize(DM dm, DM plex) 35400a96aa3bSJed Brown { 35410a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 35420a96aa3bSJed Brown DM adapt; 35430a96aa3bSJed Brown 35440a96aa3bSJed Brown PetscFunctionBegin; 35450a96aa3bSJed Brown if (pforest->labelsFinalized) PetscFunctionReturn(0); 35460a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 35479566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm,&adapt)); 35480a96aa3bSJed Brown if (!adapt) { 35490a96aa3bSJed Brown /* Initialize labels from the base dm */ 35509566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsInitialize(dm,plex)); 35510a96aa3bSJed Brown } else { 35520a96aa3bSJed Brown PetscInt dofPerDim[4]={1, 1, 1, 1}; 35530a96aa3bSJed Brown PetscSF transferForward, transferBackward, pointSF; 35540a96aa3bSJed Brown PetscInt pStart, pEnd, pStartA, pEndA; 35550a96aa3bSJed Brown PetscInt *values, *adaptValues; 35560a96aa3bSJed Brown DMLabelLink next = adapt->labels; 35570a96aa3bSJed Brown DMLabel adaptLabel; 35580a96aa3bSJed Brown DM adaptPlex; 35590a96aa3bSJed Brown 35609566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm,&adaptLabel)); 35619566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(adapt,&adaptPlex)); 35629566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(adapt,dm,dofPerDim,&transferForward,&transferBackward)); 35639566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex,&pStart,&pEnd)); 35649566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(adaptPlex,&pStartA,&pEndA)); 35659566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd-pStart,&values,pEndA-pStartA,&adaptValues)); 35669566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plex,&pointSF)); 35670a96aa3bSJed Brown if (PetscDefined(USE_DEBUG)) { 35680a96aa3bSJed Brown PetscInt p; 35690a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) adaptValues[p-pStartA] = -1; 35700a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p-pStart] = -2; 35710a96aa3bSJed Brown if (transferForward) { 35729566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE)); 35739566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE)); 35740a96aa3bSJed Brown } 35750a96aa3bSJed Brown if (transferBackward) { 3576*57168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(transferBackward,MPIU_INT,adaptValues,values,MPI_MAX)); 3577*57168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(transferBackward,MPIU_INT,adaptValues,values,MPI_MAX)); 35780a96aa3bSJed Brown } 35790a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 35800a96aa3bSJed Brown PetscInt q = p, parent; 35810a96aa3bSJed Brown 35829566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&parent,NULL)); 35830a96aa3bSJed Brown while (parent != q) { 35840a96aa3bSJed Brown if (values[parent] == -2) values[parent] = values[q]; 35850a96aa3bSJed Brown q = parent; 35869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&parent,NULL)); 35870a96aa3bSJed Brown } 35880a96aa3bSJed Brown } 3589*57168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF,MPIU_INT,values,values,MPI_MAX)); 3590*57168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF,MPIU_INT,values,values,MPI_MAX)); 35919566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF,MPIU_INT,values,values,MPI_REPLACE)); 35929566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF,MPIU_INT,values,values,MPI_REPLACE)); 35930a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 359463a3b9bcSJacob Faibussowitsch PetscCheck(values[p-pStart] != -2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"uncovered point %" PetscInt_FMT,p); 35950a96aa3bSJed Brown } 35960a96aa3bSJed Brown } 35970a96aa3bSJed Brown while (next) { 35980a96aa3bSJed Brown DMLabel nextLabel = next->label; 35990a96aa3bSJed Brown const char *name; 36000a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 36010a96aa3bSJed Brown DMLabel label; 36020a96aa3bSJed Brown PetscInt p; 36030a96aa3bSJed Brown 36049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) nextLabel, &name)); 36059566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"depth",&isDepth)); 36060a96aa3bSJed Brown if (isDepth) { 36070a96aa3bSJed Brown next = next->next; 36080a96aa3bSJed Brown continue; 36090a96aa3bSJed Brown } 36109566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"celltype",&isCellType)); 36110a96aa3bSJed Brown if (isCellType) { 36120a96aa3bSJed Brown next = next->next; 36130a96aa3bSJed Brown continue; 36140a96aa3bSJed Brown } 36159566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"ghost",&isGhost)); 36160a96aa3bSJed Brown if (isGhost) { 36170a96aa3bSJed Brown next = next->next; 36180a96aa3bSJed Brown continue; 36190a96aa3bSJed Brown } 36209566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"vtk",&isVTK)); 36210a96aa3bSJed Brown if (isVTK) { 36220a96aa3bSJed Brown next = next->next; 36230a96aa3bSJed Brown continue; 36240a96aa3bSJed Brown } 36250a96aa3bSJed Brown if (nextLabel == adaptLabel) { 36260a96aa3bSJed Brown next = next->next; 36270a96aa3bSJed Brown continue; 36280a96aa3bSJed Brown } 36290a96aa3bSJed Brown /* label was created earlier */ 36309566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm,name,&label)); 36310a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) { 36329566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(nextLabel,p,&adaptValues[p])); 36330a96aa3bSJed Brown } 36340a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p] = PETSC_MIN_INT; 36350a96aa3bSJed Brown 36361baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastBegin(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE)); 3637*57168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceBegin(transferBackward,MPIU_INT,adaptValues,values,MPI_MAX)); 36381baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastEnd(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE)); 3639*57168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceEnd(transferBackward,MPIU_INT,adaptValues,values,MPI_MAX)); 36400a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 36410a96aa3bSJed Brown PetscInt q = p, parent; 36420a96aa3bSJed Brown 36439566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&parent,NULL)); 36440a96aa3bSJed Brown while (parent != q) { 36450a96aa3bSJed Brown if (values[parent] == PETSC_MIN_INT) values[parent] = values[q]; 36460a96aa3bSJed Brown q = parent; 36479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&parent,NULL)); 36480a96aa3bSJed Brown } 36490a96aa3bSJed Brown } 3650*57168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF,MPIU_INT,values,values,MPI_MAX)); 3651*57168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF,MPIU_INT,values,values,MPI_MAX)); 36529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF,MPIU_INT,values,values,MPI_REPLACE)); 36539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF,MPIU_INT,values,values,MPI_REPLACE)); 36540a96aa3bSJed Brown 36550a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 36569566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,values[p])); 36570a96aa3bSJed Brown } 36580a96aa3bSJed Brown next = next->next; 36590a96aa3bSJed Brown } 36609566063dSJacob Faibussowitsch PetscCall(PetscFree2(values,adaptValues)); 36619566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferForward)); 36629566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferBackward)); 36630a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 36640a96aa3bSJed Brown } 36650a96aa3bSJed Brown PetscFunctionReturn(0); 36660a96aa3bSJed Brown } 36670a96aa3bSJed Brown 36680a96aa3bSJed Brown 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) 36690a96aa3bSJed Brown { 36700a96aa3bSJed Brown PetscInt closureSize, c, coordStart, coordEnd, coordDim; 36710a96aa3bSJed Brown PetscInt *closure = NULL; 36720a96aa3bSJed Brown PetscSection coordSec; 36730a96aa3bSJed Brown 36740a96aa3bSJed Brown PetscFunctionBegin; 36759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex,&coordSec)); 36769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec,&coordStart,&coordEnd)); 36779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex,&coordDim)); 36789566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,cell,PETSC_TRUE,&closureSize,&closure)); 36790a96aa3bSJed Brown for (c = 0; c < closureSize; c++) { 36800a96aa3bSJed Brown PetscInt point = closure[2 * c]; 36810a96aa3bSJed Brown 36820a96aa3bSJed Brown if (point >= coordStart && point < coordEnd) { 36830a96aa3bSJed Brown PetscInt dof, off; 36840a96aa3bSJed Brown PetscInt nCoords, i; 36859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec,point,&dof)); 368608401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Did not understand coordinate layout"); 36870a96aa3bSJed Brown nCoords = dof / coordDim; 36889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec,point,&off)); 36890a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 36900a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 36910a96aa3bSJed Brown double coordP4est[3] = {0.}; 36920a96aa3bSJed Brown double coordP4estMapped[3] = {0.}; 36930a96aa3bSJed Brown PetscInt j; 36940a96aa3bSJed Brown PetscReal treeCoords[P4EST_CHILDREN][3] = {{0.}}; 36950a96aa3bSJed Brown PetscReal eta[3] = {0.}; 36960a96aa3bSJed Brown PetscInt numRounds = 10; 36970a96aa3bSJed Brown PetscReal coordGuess[3] = {0.}; 36980a96aa3bSJed Brown 36990a96aa3bSJed Brown eta[0] = (PetscReal) q->x / (PetscReal) P4EST_ROOT_LEN; 37000a96aa3bSJed Brown eta[1] = (PetscReal) q->y / (PetscReal) P4EST_ROOT_LEN; 37010a96aa3bSJed Brown #if defined(P4_TO_P8) 37020a96aa3bSJed Brown eta[2] = (PetscReal) q->z / (PetscReal) P4EST_ROOT_LEN; 37030a96aa3bSJed Brown #endif 37040a96aa3bSJed Brown 37050a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 37060a96aa3bSJed Brown PetscInt k; 37070a96aa3bSJed Brown 37080a96aa3bSJed Brown for (k = 0; k < 3; k++) treeCoords[j][k] = conn->vertices[3 * conn->tree_to_vertex[P4EST_CHILDREN * t + j] + k]; 37090a96aa3bSJed Brown } 37100a96aa3bSJed Brown 37110a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 37120a96aa3bSJed Brown PetscInt k; 37130a96aa3bSJed Brown PetscReal prod = 1.; 37140a96aa3bSJed Brown 37150a96aa3bSJed Brown for (k = 0; k < P4EST_DIM; k++) prod *= (j & (1 << k)) ? eta[k] : (1. - eta[k]); 37160a96aa3bSJed Brown for (k = 0; k < 3; k++) coordGuess[k] += prod * treeCoords[j][k]; 37170a96aa3bSJed Brown } 37180a96aa3bSJed Brown 37190a96aa3bSJed Brown for (j = 0; j < numRounds; j++) { 37200a96aa3bSJed Brown PetscInt dir; 37210a96aa3bSJed Brown 37220a96aa3bSJed Brown for (dir = 0; dir < P4EST_DIM; dir++) { 37230a96aa3bSJed Brown PetscInt k; 37240a96aa3bSJed Brown PetscReal diff[3]; 37250a96aa3bSJed Brown PetscReal dXdeta[3] = {0.}; 37260a96aa3bSJed Brown PetscReal rhs, scale, update; 37270a96aa3bSJed Brown 37280a96aa3bSJed Brown for (k = 0; k < 3; k++) diff[k] = coordP4est[k] - coordGuess[k]; 37290a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 37300a96aa3bSJed Brown PetscInt l; 37310a96aa3bSJed Brown PetscReal prod = 1.; 37320a96aa3bSJed Brown 37330a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) { 37340a96aa3bSJed Brown if (l == dir) { 37350a96aa3bSJed Brown prod *= (k & (1 << l)) ? 1. : -1.; 37360a96aa3bSJed Brown } else { 37370a96aa3bSJed Brown prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 37380a96aa3bSJed Brown } 37390a96aa3bSJed Brown } 37400a96aa3bSJed Brown for (l = 0; l < 3; l++) dXdeta[l] += prod * treeCoords[k][l]; 37410a96aa3bSJed Brown } 37420a96aa3bSJed Brown rhs = 0.; 37430a96aa3bSJed Brown scale = 0; 37440a96aa3bSJed Brown for (k = 0; k < 3; k++) { 37450a96aa3bSJed Brown rhs += diff[k] * dXdeta[k]; 37460a96aa3bSJed Brown scale += dXdeta[k] * dXdeta[k]; 37470a96aa3bSJed Brown } 37480a96aa3bSJed Brown update = rhs / scale; 37490a96aa3bSJed Brown eta[dir] += update; 37500a96aa3bSJed Brown eta[dir] = PetscMin(eta[dir],1.); 37510a96aa3bSJed Brown eta[dir] = PetscMax(eta[dir],0.); 37520a96aa3bSJed Brown 37530a96aa3bSJed Brown coordGuess[0] = coordGuess[1] = coordGuess[2] = 0.; 37540a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 37550a96aa3bSJed Brown PetscInt l; 37560a96aa3bSJed Brown PetscReal prod = 1.; 37570a96aa3bSJed Brown 37580a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 37590a96aa3bSJed Brown for (l = 0; l < 3; l++) coordGuess[l] += prod * treeCoords[k][l]; 37600a96aa3bSJed Brown } 37610a96aa3bSJed Brown } 37620a96aa3bSJed Brown } 37630a96aa3bSJed Brown for (j = 0; j < 3; j++) coordP4est[j] = (double) eta[j]; 37640a96aa3bSJed Brown 37650a96aa3bSJed Brown if (geom) { 37660a96aa3bSJed Brown (geom->X)(geom,t,coordP4est,coordP4estMapped); 37670a96aa3bSJed Brown for (j = 0; j < coordDim; j++) coord[j] = (PetscScalar) coordP4estMapped[j]; 37680a96aa3bSJed Brown } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not coded"); 37690a96aa3bSJed Brown } 37700a96aa3bSJed Brown } 37710a96aa3bSJed Brown } 37729566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,cell,PETSC_TRUE,&closureSize,&closure)); 37730a96aa3bSJed Brown PetscFunctionReturn(0); 37740a96aa3bSJed Brown } 37750a96aa3bSJed Brown 37760a96aa3bSJed Brown static PetscErrorCode DMPforestMapCoordinates(DM dm, DM plex) 37770a96aa3bSJed Brown { 37780a96aa3bSJed Brown DM_Forest *forest; 37790a96aa3bSJed Brown DM_Forest_pforest *pforest; 37800a96aa3bSJed Brown p4est_geometry_t *geom; 37810a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd; 37820a96aa3bSJed Brown Vec coordLocalVec; 37830a96aa3bSJed Brown PetscScalar *coords; 37840a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 37850a96aa3bSJed Brown p4est_tree_t *trees; 37860a96aa3bSJed Brown PetscErrorCode (*map)(DM,PetscInt, PetscInt, const PetscReal [], PetscReal [], void*); 37870a96aa3bSJed Brown void *mapCtx; 37880a96aa3bSJed Brown 37890a96aa3bSJed Brown PetscFunctionBegin; 37900a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 37910a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 37920a96aa3bSJed Brown geom = pforest->topo->geom; 37939566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx)); 37940a96aa3bSJed Brown if (!geom && !map) PetscFunctionReturn(0); 37959566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(plex,&coordLocalVec)); 37969566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordLocalVec,&coords)); 37970a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 37980a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 37990a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 38000a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 38010a96aa3bSJed Brown trees = (p4est_tree_t*) pforest->forest->trees->array; 38020a96aa3bSJed Brown if (map) { /* apply the map directly to the existing coordinates */ 38030a96aa3bSJed Brown PetscSection coordSec; 38040a96aa3bSJed Brown PetscInt coordStart, coordEnd, p, coordDim, p4estCoordDim, cStart, cEnd, cEndInterior; 38050a96aa3bSJed Brown DM base; 38060a96aa3bSJed Brown 38079566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex,0,&cStart,&cEnd)); 38089566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(plex,&cEndInterior,NULL)); 38090a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 38109566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 38119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex,&coordSec)); 38129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec,&coordStart,&coordEnd)); 38139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex,&coordDim)); 38140a96aa3bSJed Brown p4estCoordDim = PetscMin(coordDim,3); 38150a96aa3bSJed Brown for (p = coordStart; p < coordEnd; p++) { 38160a96aa3bSJed Brown PetscInt *star = NULL, starSize; 38170a96aa3bSJed Brown PetscInt dof, off, cell = -1, coarsePoint = -1; 38180a96aa3bSJed Brown PetscInt nCoords, i; 38199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec,p,&dof)); 382008401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Did not understand coordinate layout"); 38210a96aa3bSJed Brown nCoords = dof / coordDim; 38229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec,p,&off)); 38239566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,p,PETSC_FALSE,&starSize,&star)); 38240a96aa3bSJed Brown for (i = 0; i < starSize; i++) { 38250a96aa3bSJed Brown PetscInt point = star[2 * i]; 38260a96aa3bSJed Brown 38270a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 38280a96aa3bSJed Brown cell = point; 38290a96aa3bSJed Brown break; 38300a96aa3bSJed Brown } 38310a96aa3bSJed Brown } 38329566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,p,PETSC_FALSE,&starSize,&star)); 38330a96aa3bSJed Brown if (cell >= 0) { 38340a96aa3bSJed Brown if (cell < cLocalStart) { 38350a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 38360a96aa3bSJed Brown 38370a96aa3bSJed Brown coarsePoint = ghosts[cell].p.which_tree; 38380a96aa3bSJed Brown } else if (cell < cLocalEnd) { 38390a96aa3bSJed Brown cell -= cLocalStart; 38400a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 38410a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 38420a96aa3bSJed Brown 38430a96aa3bSJed Brown if (cell >= tree->quadrants_offset && (size_t) cell < tree->quadrants_offset + tree->quadrants.elem_count) { 38440a96aa3bSJed Brown coarsePoint = t; 38450a96aa3bSJed Brown break; 38460a96aa3bSJed Brown } 38470a96aa3bSJed Brown } 38480a96aa3bSJed Brown } else { 38490a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 38500a96aa3bSJed Brown 38510a96aa3bSJed Brown coarsePoint = ghosts[cell - cLocalEnd].p.which_tree; 38520a96aa3bSJed Brown } 38530a96aa3bSJed Brown } 38540a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 38550a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 38560a96aa3bSJed Brown PetscReal coordP4est[3] = {0.}; 38570a96aa3bSJed Brown PetscReal coordP4estMapped[3] = {0.}; 38580a96aa3bSJed Brown PetscInt j; 38590a96aa3bSJed Brown 38600a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coordP4est[j] = PetscRealPart(coord[j]); 38619566063dSJacob Faibussowitsch PetscCall((map)(base,coarsePoint,p4estCoordDim,coordP4est,coordP4estMapped,mapCtx)); 38620a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coord[j] = (PetscScalar) coordP4estMapped[j]; 38630a96aa3bSJed Brown } 38640a96aa3bSJed Brown } 38650a96aa3bSJed Brown } else { /* we have to transform coordinates back to the unit cube (where geom is defined), and then apply geom */ 38660a96aa3bSJed Brown PetscInt cStart, cEnd, cEndInterior; 38670a96aa3bSJed Brown 38689566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex,0,&cStart,&cEnd)); 38699566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(plex,&cEndInterior,NULL)); 38700a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 38710a96aa3bSJed Brown if (cLocalStart > 0) { 38720a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 38730a96aa3bSJed Brown PetscInt count; 38740a96aa3bSJed Brown 38750a96aa3bSJed Brown for (count = 0; count < cLocalStart; count++) { 38760a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count]; 38770a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 38780a96aa3bSJed Brown 38799566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex,geom,count,quad,t,pforest->topo->conn,coords)); 38800a96aa3bSJed Brown } 38810a96aa3bSJed Brown } 38820a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 38830a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 38840a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset, i; 38850a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 38860a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t*) tree->quadrants.array; 38870a96aa3bSJed Brown 38880a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 38890a96aa3bSJed Brown PetscInt count = i + offset; 38900a96aa3bSJed Brown 38919566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex,geom,count,&quads[i],t,pforest->topo->conn,coords)); 38920a96aa3bSJed Brown } 38930a96aa3bSJed Brown } 38940a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 38950a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 38960a96aa3bSJed Brown PetscInt numGhosts = (PetscInt) pforest->ghost->ghosts.elem_count; 38970a96aa3bSJed Brown PetscInt count; 38980a96aa3bSJed Brown 38990a96aa3bSJed Brown for (count = 0; count < numGhosts - cLocalStart; count++) { 39000a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 39010a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 39020a96aa3bSJed Brown 39039566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex,geom,count + cLocalEnd,quad,t,pforest->topo->conn,coords)); 39040a96aa3bSJed Brown } 39050a96aa3bSJed Brown } 39060a96aa3bSJed Brown } 39079566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordLocalVec,&coords)); 39080a96aa3bSJed Brown PetscFunctionReturn(0); 39090a96aa3bSJed Brown } 39100a96aa3bSJed Brown 3911852b71a7SToby Isaac static PetscErrorCode PforestQuadrantIsInterior (p4est_quadrant_t *quad, PetscBool *is_interior) 3912852b71a7SToby Isaac { 3913852b71a7SToby Isaac PetscFunctionBegin; 3914852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN (quad->level); 3915852b71a7SToby Isaac if ((quad->x > 0) && (quad->x + h < P4EST_ROOT_LEN) 3916852b71a7SToby Isaac #ifdef P4_TO_P8 3917852b71a7SToby Isaac && (quad->z > 0) && (quad->z + h < P4EST_ROOT_LEN) 3918852b71a7SToby Isaac #endif 3919852b71a7SToby Isaac && (quad->y > 0) && (quad->y + h < P4EST_ROOT_LEN)) { 3920852b71a7SToby Isaac *is_interior = PETSC_TRUE; 3921852b71a7SToby Isaac } else { 3922852b71a7SToby Isaac *is_interior = PETSC_FALSE; 3923852b71a7SToby Isaac } 3924852b71a7SToby Isaac PetscFunctionReturn(0); 3925852b71a7SToby Isaac } 3926852b71a7SToby Isaac 3927852b71a7SToby Isaac /* We always use DG coordinates with p4est: if they do not match the vertex 3928852b71a7SToby Isaac coordinates, add space for them in the section */ 3929852b71a7SToby Isaac 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) 3930852b71a7SToby Isaac { 3931852b71a7SToby Isaac PetscBool is_interior; 3932852b71a7SToby Isaac 3933852b71a7SToby Isaac PetscFunctionBegin; 3934852b71a7SToby Isaac PetscCall(PforestQuadrantIsInterior(quad, &is_interior)); 3935852b71a7SToby Isaac if (is_interior) { // quads in the interior of a coarse cell can't touch periodic interfaces 3936852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3937852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3938852b71a7SToby Isaac } else { 3939852b71a7SToby Isaac PetscInt cSize; 3940852b71a7SToby Isaac PetscScalar *values = NULL; 3941852b71a7SToby Isaac PetscBool same_coords = PETSC_TRUE; 3942852b71a7SToby Isaac 3943852b71a7SToby Isaac PetscCall(DMPlexVecGetClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3944852b71a7SToby Isaac PetscAssert(cSize == cDim * P4EST_CHILDREN, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected closure size"); 3945852b71a7SToby Isaac for (int c = 0; c < P4EST_CHILDREN; c++) { 3946852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3947852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN (quad->level); 3948852b71a7SToby Isaac double corner_coords[3]; 3949852b71a7SToby Isaac double vert_coords[3]; 3950852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 3951852b71a7SToby Isaac 3952852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) { 3953852b71a7SToby Isaac vert_coords[d] = PetscRealPart(values[c * cDim + d]); 3954852b71a7SToby Isaac } 3955852b71a7SToby Isaac 3956852b71a7SToby Isaac quad_coords[0] = quad->x; 3957852b71a7SToby Isaac quad_coords[1] = quad->y; 3958852b71a7SToby Isaac #ifdef P4_TO_P8 3959852b71a7SToby Isaac quad_coords[2] = quad->z; 3960852b71a7SToby Isaac #endif 3961852b71a7SToby Isaac for (int d = 0; d < 3; d++) { 3962852b71a7SToby Isaac quad_coords[d] += (corner & (1 << d)) ? h : 0; 3963852b71a7SToby Isaac } 3964852b71a7SToby Isaac #ifndef P4_TO_P8 3965648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex,(pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 3966852b71a7SToby Isaac #else 3967648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex,(pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 3968852b71a7SToby Isaac #endif 3969852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) { 3970852b71a7SToby Isaac if (fabs (vert_coords[d] - corner_coords[d]) > PETSC_SMALL) { 3971852b71a7SToby Isaac same_coords = PETSC_FALSE; 3972852b71a7SToby Isaac break; 3973852b71a7SToby Isaac } 3974852b71a7SToby Isaac } 3975852b71a7SToby Isaac } 3976852b71a7SToby Isaac if (same_coords) { 3977852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3978852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3979852b71a7SToby Isaac } else { 3980852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, cSize)); 3981852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, cSize)); 3982852b71a7SToby Isaac } 3983852b71a7SToby Isaac PetscCall(DMPlexVecRestoreClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3984852b71a7SToby Isaac } 3985852b71a7SToby Isaac PetscFunctionReturn(0); 3986852b71a7SToby Isaac } 3987852b71a7SToby Isaac 3988852b71a7SToby Isaac static PetscErrorCode PforestLocalizeCell(DM plex, PetscInt cDim, DM_Forest_pforest *pforest, PetscSection newSection, PetscInt cell, PetscInt coarsePoint, p4est_quadrant_t *quad, PetscScalar coords[]) 3989852b71a7SToby Isaac { 3990852b71a7SToby Isaac PetscInt cdof, off; 3991852b71a7SToby Isaac 3992852b71a7SToby Isaac PetscFunctionBegin; 3993852b71a7SToby Isaac PetscCall(PetscSectionGetDof(newSection, cell, &cdof)); 3994852b71a7SToby Isaac if (!cdof) PetscFunctionReturn(0); 3995852b71a7SToby Isaac 3996852b71a7SToby Isaac PetscCall(PetscSectionGetOffset(newSection, cell, &off)); 3997852b71a7SToby Isaac for (PetscInt c = 0, pos = off; c < P4EST_CHILDREN; c++) { 3998852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3999852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN (quad->level); 4000852b71a7SToby Isaac double corner_coords[3]; 4001852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 4002852b71a7SToby Isaac 4003852b71a7SToby Isaac quad_coords[0] = quad->x; 4004852b71a7SToby Isaac quad_coords[1] = quad->y; 4005852b71a7SToby Isaac #ifdef P4_TO_P8 4006852b71a7SToby Isaac quad_coords[2] = quad->z; 4007852b71a7SToby Isaac #endif 4008852b71a7SToby Isaac for (int d = 0; d < 3; d++) { 4009852b71a7SToby Isaac quad_coords[d] += (corner & (1 << d)) ? h : 0; 4010852b71a7SToby Isaac } 4011852b71a7SToby Isaac #ifndef P4_TO_P8 4012648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex,(pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 4013852b71a7SToby Isaac #else 4014648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex,(pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 4015852b71a7SToby Isaac #endif 4016852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) { 4017852b71a7SToby Isaac coords[pos++] = corner_coords[d]; 4018852b71a7SToby Isaac } 4019852b71a7SToby Isaac for (PetscInt d = PetscMin(cDim, 3); d < cDim; d++) { 4020852b71a7SToby Isaac coords[pos++] = 0.; 4021852b71a7SToby Isaac } 4022852b71a7SToby Isaac } 4023852b71a7SToby Isaac PetscFunctionReturn(0); 4024852b71a7SToby Isaac } 4025852b71a7SToby Isaac 40260a96aa3bSJed Brown static PetscErrorCode DMPforestLocalizeCoordinates(DM dm, DM plex) 40270a96aa3bSJed Brown { 40280a96aa3bSJed Brown DM_Forest *forest; 40290a96aa3bSJed Brown DM_Forest_pforest *pforest; 40306858538eSMatthew G. Knepley DM base, cdm, cdmCell; 4031852b71a7SToby Isaac Vec cVec, cVecOld; 4032852b71a7SToby Isaac PetscSection oldSection, newSection; 40330a96aa3bSJed Brown PetscScalar *coords2; 40346858538eSMatthew G. Knepley const PetscReal *L; 40350a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, coarsePoint; 4036852b71a7SToby Isaac PetscInt cDim, newStart, newEnd; 4037852b71a7SToby Isaac PetscInt v, vStart, vEnd, cp, cStart, cEnd, cEndInterior; 40380a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 40390a96aa3bSJed Brown p4est_tree_t *trees; 40406858538eSMatthew G. Knepley PetscBool baseLocalized = PETSC_FALSE; 40410a96aa3bSJed Brown 40420a96aa3bSJed Brown PetscFunctionBegin; 40434fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm,NULL,NULL,&L)); 40440a96aa3bSJed Brown /* we localize on all cells if we don't have a base DM or the base DM coordinates have not been localized */ 40459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cDim)); 40469566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 40476858538eSMatthew G. Knepley if (base) PetscCall(DMGetCoordinatesLocalized(base,&baseLocalized)); 40480a96aa3bSJed Brown if (!baseLocalized) base = NULL; 40496858538eSMatthew G. Knepley if (!baseLocalized && !L) PetscFunctionReturn(0); 40509566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &newStart, &newEnd)); 40510a96aa3bSJed Brown 40529566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) dm), &newSection)); 40539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(newSection, 1)); 40549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(newSection, 0, cDim)); 40559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSection, newStart, newEnd)); 40560a96aa3bSJed Brown 40579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &oldSection)); 40589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd)); 4059852b71a7SToby Isaac PetscCall(DMGetCoordinatesLocal(plex, &cVecOld)); 40600a96aa3bSJed Brown 40610a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 40620a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 40630a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 40640a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 40650a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 40660a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 40670a96aa3bSJed Brown trees = (p4est_tree_t*) pforest->forest->trees->array; 40680a96aa3bSJed Brown 40699566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 40709566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(plex, &cEndInterior, NULL)); 40710a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 4072852b71a7SToby Isaac cp = 0; 40730a96aa3bSJed Brown if (cLocalStart > 0) { 40740a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 4075852b71a7SToby Isaac PetscInt cell; 40760a96aa3bSJed Brown 4077852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 4078852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 4079852b71a7SToby Isaac 40800a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 4081852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 40820a96aa3bSJed Brown } 40830a96aa3bSJed Brown } 40840a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 40850a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 40860a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 40870a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 4088852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 40890a96aa3bSJed Brown PetscInt i; 40900a96aa3bSJed Brown 40910a96aa3bSJed Brown if (!numQuads) continue; 40920a96aa3bSJed Brown coarsePoint = t; 4093852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 4094852b71a7SToby Isaac PetscInt cell = i + offset; 4095852b71a7SToby Isaac p4est_quadrant_t * quad = &quads[i]; 40960a96aa3bSJed Brown 4097852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 40980a96aa3bSJed Brown } 40990a96aa3bSJed Brown } 41000a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 41010a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 41020a96aa3bSJed Brown PetscInt numGhosts = (PetscInt) pforest->ghost->ghosts.elem_count; 41030a96aa3bSJed Brown PetscInt count; 41040a96aa3bSJed Brown 4105852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 41060a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 41070a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 4108852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 41090a96aa3bSJed Brown 4110852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 41110a96aa3bSJed Brown } 41120a96aa3bSJed Brown } 4113852b71a7SToby Isaac PetscAssert(cp == cEnd - cStart,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of fine cells %" PetscInt_FMT " != %" PetscInt_FMT,cp,cEnd-cStart); 41140a96aa3bSJed Brown 41159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSection)); 41166858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(plex, &cdm)); 41176858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 41186858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(plex, cdmCell)); 41196858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 41206858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(plex, cDim, newSection)); 41219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &v)); 41229566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &cVec)); 41239566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) cVec, "coordinates")); 41249566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(cVec, cDim)); 41259566063dSJacob Faibussowitsch PetscCall(VecSetSizes(cVec, v, PETSC_DETERMINE)); 41269566063dSJacob Faibussowitsch PetscCall(VecSetType(cVec, VECSTANDARD)); 41279566063dSJacob Faibussowitsch PetscCall(VecSet(cVec, PETSC_MIN_REAL)); 41280a96aa3bSJed Brown 41290a96aa3bSJed Brown /* Localize coordinates on cells if needed */ 41306858538eSMatthew G. Knepley PetscCall(VecGetArray(cVec, &coords2)); 4131852b71a7SToby Isaac cp = 0; 4132852b71a7SToby Isaac if (cLocalStart > 0) { 4133852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 4134852b71a7SToby Isaac PetscInt cell; 4135852b71a7SToby Isaac 4136852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 4137852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 4138852b71a7SToby Isaac 4139852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 4140852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 4141852b71a7SToby Isaac } 4142852b71a7SToby Isaac } 41430a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 41440a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 41450a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 41460a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 4147852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 4148852b71a7SToby Isaac PetscInt i; 41490a96aa3bSJed Brown 41500a96aa3bSJed Brown if (!numQuads) continue; 4151852b71a7SToby Isaac coarsePoint = t; 4152852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 4153852b71a7SToby Isaac PetscInt cell = i + offset; 41540a96aa3bSJed Brown p4est_quadrant_t * quad = &quads[i]; 41550a96aa3bSJed Brown 4156852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 4157852b71a7SToby Isaac } 4158852b71a7SToby Isaac } 4159852b71a7SToby Isaac if (cLocalEnd - cLocalStart < cEnd - cStart) { 4160852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 4161852b71a7SToby Isaac PetscInt numGhosts = (PetscInt) pforest->ghost->ghosts.elem_count; 4162852b71a7SToby Isaac PetscInt count; 41630a96aa3bSJed Brown 4164852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 4165852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 4166852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 4167852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 41680a96aa3bSJed Brown 4169852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 41700a96aa3bSJed Brown } 41710a96aa3bSJed Brown } 41729566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cVec, &coords2)); 41736858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(plex, cVec)); 41749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cVec)); 41759566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newSection)); 41760a96aa3bSJed Brown PetscFunctionReturn(0); 41770a96aa3bSJed Brown } 41780a96aa3bSJed Brown 41790a96aa3bSJed Brown #define DMForestClearAdaptivityForest_pforest _append_pforest(DMForestClearAdaptivityForest) 41800a96aa3bSJed Brown static PetscErrorCode DMForestClearAdaptivityForest_pforest(DM dm) 41810a96aa3bSJed Brown { 41820a96aa3bSJed Brown DM_Forest *forest; 41830a96aa3bSJed Brown DM_Forest_pforest *pforest; 41840a96aa3bSJed Brown 41850a96aa3bSJed Brown PetscFunctionBegin; 41860a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 41870a96aa3bSJed Brown pforest = (DM_Forest_pforest *) forest->data; 41889566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&(pforest->pointAdaptToSelfSF))); 41899566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&(pforest->pointSelfToAdaptSF))); 41909566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 41919566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 41920a96aa3bSJed Brown PetscFunctionReturn(0); 41930a96aa3bSJed Brown } 41940a96aa3bSJed Brown 41950a96aa3bSJed Brown static PetscErrorCode DMConvert_pforest_plex(DM dm, DMType newtype, DM *plex) 41960a96aa3bSJed Brown { 41970a96aa3bSJed Brown DM_Forest *forest; 41980a96aa3bSJed Brown DM_Forest_pforest *pforest; 41990a96aa3bSJed Brown DM refTree, newPlex, base; 42000a96aa3bSJed Brown PetscInt adjDim, adjCodim, coordDim; 42010a96aa3bSJed Brown MPI_Comm comm; 42020a96aa3bSJed Brown PetscBool isPforest; 42030a96aa3bSJed Brown PetscInt dim; 42040a96aa3bSJed Brown PetscInt overlap; 42050a96aa3bSJed Brown p4est_connect_type_t ctype; 42060a96aa3bSJed Brown p4est_locidx_t first_local_quad = -1; 42070a96aa3bSJed Brown sc_array_t *points_per_dim, *cone_sizes, *cones, *cone_orientations, *coords, *children, *parents, *childids, *leaves, *remotes; 42080a96aa3bSJed Brown PetscSection parentSection; 42090a96aa3bSJed Brown PetscSF pointSF; 42100a96aa3bSJed Brown size_t zz, count; 42110a96aa3bSJed Brown PetscInt pStart, pEnd; 42120a96aa3bSJed Brown DMLabel ghostLabelBase = NULL; 42130a96aa3bSJed Brown 42140a96aa3bSJed Brown PetscFunctionBegin; 42150a96aa3bSJed Brown 42160a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 42170a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 42189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMPFOREST,&isPforest)); 421928b400f6SJacob Faibussowitsch PetscCheck(isPforest,comm,PETSC_ERR_ARG_WRONG,"Expected DM type %s, got %s",DMPFOREST,((PetscObject)dm)->type_name); 42209566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm,&dim)); 422163a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM,comm,PETSC_ERR_ARG_WRONG,"Expected DM dimension %d, got %" PetscInt_FMT,P4EST_DIM,dim); 42220a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 42230a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 42249566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 42250a96aa3bSJed Brown if (base) { 42269566063dSJacob Faibussowitsch PetscCall(DMGetLabel(base,"ghost",&ghostLabelBase)); 42270a96aa3bSJed Brown } 42280a96aa3bSJed Brown if (!pforest->plex) { 42290a96aa3bSJed Brown PetscMPIInt size; 42300a96aa3bSJed Brown 42319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 42329566063dSJacob Faibussowitsch PetscCall(DMCreate(comm,&newPlex)); 42339566063dSJacob Faibussowitsch PetscCall(DMSetType(newPlex,DMPLEX)); 42349566063dSJacob Faibussowitsch PetscCall(DMSetMatType(newPlex,dm->mattype)); 42350a96aa3bSJed Brown /* share labels */ 42369566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, newPlex, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 42379566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyDimension(dm,&adjDim)); 42389566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyCodimension(dm,&adjCodim)); 42399566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm,&coordDim)); 42400a96aa3bSJed Brown if (adjDim == 0) { 42410a96aa3bSJed Brown ctype = P4EST_CONNECT_FULL; 42420a96aa3bSJed Brown } else if (adjCodim == 1) { 42430a96aa3bSJed Brown ctype = P4EST_CONNECT_FACE; 42440a96aa3bSJed Brown #if defined(P4_TO_P8) 42450a96aa3bSJed Brown } else if (adjDim == 1) { 42460a96aa3bSJed Brown ctype = P8EST_CONNECT_EDGE; 42470a96aa3bSJed Brown #endif 42480a96aa3bSJed Brown } else { 424963a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONG,"Invalid adjacency dimension %" PetscInt_FMT,adjDim); 42500a96aa3bSJed Brown } 425163a3b9bcSJacob 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); 42529566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm,&overlap)); 425360667520SVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(newPlex,NULL,overlap)); 42540a96aa3bSJed Brown 42550a96aa3bSJed Brown points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 42560a96aa3bSJed Brown cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 42570a96aa3bSJed Brown cones = sc_array_new(sizeof(p4est_locidx_t)); 42580a96aa3bSJed Brown cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 42590a96aa3bSJed Brown coords = sc_array_new(3 * sizeof(double)); 42600a96aa3bSJed Brown children = sc_array_new(sizeof(p4est_locidx_t)); 42610a96aa3bSJed Brown parents = sc_array_new(sizeof(p4est_locidx_t)); 42620a96aa3bSJed Brown childids = sc_array_new(sizeof(p4est_locidx_t)); 42630a96aa3bSJed Brown leaves = sc_array_new(sizeof(p4est_locidx_t)); 42640a96aa3bSJed Brown remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 42650a96aa3bSJed Brown 4266792fecdfSBarry 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)); 42670a96aa3bSJed Brown 42680a96aa3bSJed Brown pforest->cLocalStart = (PetscInt) first_local_quad; 42690a96aa3bSJed Brown pforest->cLocalEnd = pforest->cLocalStart + (PetscInt) pforest->forest->local_num_quadrants; 42709566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 42719566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 42729566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 42739566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 42749566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, coordDim)); 42759566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(children)); 42769566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(parents)); 42779566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(childids)); 42789566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(leaves)); 42799566063dSJacob Faibussowitsch PetscCall(locidx_pair_to_PetscSFNode(remotes)); 42800a96aa3bSJed Brown 42819566063dSJacob Faibussowitsch PetscCall(DMSetDimension(newPlex,P4EST_DIM)); 42829566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(newPlex,coordDim)); 42839566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(newPlex,P4EST_DIM - 1)); 42849566063dSJacob 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)); 42859566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(newPlex)); 42869566063dSJacob Faibussowitsch PetscCall(DMCreateReferenceTree_pforest(comm,&refTree)); 42879566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlex,refTree)); 42889566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm,&parentSection)); 42899566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(newPlex,&pStart,&pEnd)); 42909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection,pStart,pEnd)); 42910a96aa3bSJed Brown count = children->elem_count; 42920a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 42930a96aa3bSJed Brown PetscInt child = *((PetscInt*) sc_array_index(children,zz)); 42940a96aa3bSJed Brown 42959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(parentSection,child,1)); 42960a96aa3bSJed Brown } 42979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 42989566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(newPlex,parentSection,(PetscInt*)parents->array,(PetscInt*)childids->array)); 42999566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 43009566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&pointSF)); 43010a96aa3bSJed Brown /* 43020a96aa3bSJed Brown These arrays defining the sf are from the p4est library, but the code there shows the leaves being populated in increasing order. 43030a96aa3bSJed Brown https://gitlab.com/petsc/petsc/merge_requests/2248#note_240186391 43040a96aa3bSJed Brown */ 43059566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(pointSF,pEnd - pStart,(PetscInt)leaves->elem_count,(PetscInt*)leaves->array,PETSC_COPY_VALUES,(PetscSFNode*)remotes->array,PETSC_COPY_VALUES)); 43069566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(newPlex,pointSF)); 43079566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm,pointSF)); 43080a96aa3bSJed Brown { 43090a96aa3bSJed Brown DM coordDM; 43100a96aa3bSJed Brown 43119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM)); 43129566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(coordDM,pointSF)); 43130a96aa3bSJed Brown } 43149566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointSF)); 43150a96aa3bSJed Brown sc_array_destroy (points_per_dim); 43160a96aa3bSJed Brown sc_array_destroy (cone_sizes); 43170a96aa3bSJed Brown sc_array_destroy (cones); 43180a96aa3bSJed Brown sc_array_destroy (cone_orientations); 43190a96aa3bSJed Brown sc_array_destroy (coords); 43200a96aa3bSJed Brown sc_array_destroy (children); 43210a96aa3bSJed Brown sc_array_destroy (parents); 43220a96aa3bSJed Brown sc_array_destroy (childids); 43230a96aa3bSJed Brown sc_array_destroy (leaves); 43240a96aa3bSJed Brown sc_array_destroy (remotes); 43250a96aa3bSJed Brown 43260a96aa3bSJed Brown { 43274fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 43280a96aa3bSJed Brown 43294fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm,&maxCell,&Lstart,&L)); 43304fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(newPlex,maxCell,Lstart,L)); 43319566063dSJacob Faibussowitsch PetscCall(DMPforestLocalizeCoordinates(dm,newPlex)); 43320a96aa3bSJed Brown } 43330a96aa3bSJed Brown 43340a96aa3bSJed Brown if (overlap > 0) { /* the p4est routine can't set all of the coordinates in its routine if there is overlap */ 43350a96aa3bSJed Brown Vec coordsGlobal, coordsLocal; 43360a96aa3bSJed Brown const PetscScalar *globalArray; 43370a96aa3bSJed Brown PetscScalar *localArray; 43380a96aa3bSJed Brown PetscSF coordSF; 43390a96aa3bSJed Brown DM coordDM; 43400a96aa3bSJed Brown 43419566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM)); 43429566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(coordDM,&coordSF)); 43439566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(newPlex, &coordsGlobal)); 43449566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coordsLocal)); 43459566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordsGlobal, &globalArray)); 43469566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordsLocal, &localArray)); 43479566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coordSF,MPIU_SCALAR,globalArray,localArray,MPI_REPLACE)); 43489566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coordSF,MPIU_SCALAR,globalArray,localArray,MPI_REPLACE)); 43499566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordsLocal, &localArray)); 43509566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordsGlobal, &globalArray)); 43519566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(newPlex, coordsLocal)); 43520a96aa3bSJed Brown } 43539566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates(dm,newPlex)); 43540a96aa3bSJed Brown 43550a96aa3bSJed Brown pforest->plex = newPlex; 43560a96aa3bSJed Brown 43570a96aa3bSJed Brown /* copy labels */ 43589566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsFinalize(dm,newPlex)); 43590a96aa3bSJed Brown 43600a96aa3bSJed Brown if (ghostLabelBase || pforest->ghostName) { /* we have to do this after copying labels because the labels drive the construction of ghost cells */ 43610a96aa3bSJed Brown PetscInt numAdded; 43620a96aa3bSJed Brown DM newPlexGhosted; 43630a96aa3bSJed Brown void *ctx; 43640a96aa3bSJed Brown 43659566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(newPlex,pforest->ghostName,&numAdded,&newPlexGhosted)); 43669566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(newPlex,&ctx)); 43679566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(newPlexGhosted,ctx)); 43680a96aa3bSJed Brown /* we want the sf for the ghost dm to be the one for the p4est dm as well */ 43699566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(newPlexGhosted,&pointSF)); 43709566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm,pointSF)); 43719566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newPlex)); 43729566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlexGhosted,refTree)); 43739566063dSJacob Faibussowitsch PetscCall(DMForestClearAdaptivityForest_pforest(dm)); 43740a96aa3bSJed Brown newPlex = newPlexGhosted; 43750a96aa3bSJed Brown 43760a96aa3bSJed Brown /* share the labels back */ 43779566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 43789566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(newPlex, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 43790a96aa3bSJed Brown pforest->plex = newPlex; 43800a96aa3bSJed Brown } 43819566063dSJacob Faibussowitsch PetscCall(DMDestroy(&refTree)); 43820a96aa3bSJed Brown if (dm->setfromoptionscalled) { 43835f80ce2aSJacob Faibussowitsch 4384d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)newPlex); 43859566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject,newPlex)); 43869566063dSJacob Faibussowitsch PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)newPlex)); 4387d0609cedSBarry Smith PetscOptionsEnd(); 43880a96aa3bSJed Brown } 43899566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(newPlex,NULL,"-dm_p4est_plex_view")); 43900a96aa3bSJed Brown { 43916858538eSMatthew G. Knepley DM cdm; 43920a96aa3bSJed Brown PetscSection coordsSec; 43930a96aa3bSJed Brown Vec coords; 43940a96aa3bSJed Brown PetscInt cDim; 43950a96aa3bSJed Brown 43969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(newPlex, &cDim)); 43979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(newPlex, &coordsSec)); 43989566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dm,cDim, coordsSec)); 43999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coords)); 44009566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 44016858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex, &cdm)); 44026858538eSMatthew G. Knepley if (cdm) PetscCall(DMSetCellCoordinateDM(dm, cdm)); 44036858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(newPlex, &coordsSec)); 44046858538eSMatthew G. Knepley if (coordsSec) PetscCall(DMSetCellCoordinateSection(dm, cDim, coordsSec)); 44056858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(newPlex, &coords)); 44066858538eSMatthew G. Knepley if (coords) PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 44070a96aa3bSJed Brown } 44080a96aa3bSJed Brown } 44090a96aa3bSJed Brown newPlex = pforest->plex; 44100a96aa3bSJed Brown if (plex) { 44119566063dSJacob Faibussowitsch PetscCall(DMClone(newPlex,plex)); 44126858538eSMatthew G. Knepley #if 0 44139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM)); 44149566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(*plex,coordDM)); 44156858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex,&coordDM)); 44166858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*plex,coordDM)); 44176858538eSMatthew G. Knepley #endif 44189566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm,*plex)); 44190a96aa3bSJed Brown } 44200a96aa3bSJed Brown PetscFunctionReturn(0); 44210a96aa3bSJed Brown } 44220a96aa3bSJed Brown 44230a96aa3bSJed Brown static PetscErrorCode DMSetFromOptions_pforest(PetscOptionItems *PetscOptionsObject,DM dm) 44240a96aa3bSJed Brown { 44250a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 44260a96aa3bSJed Brown char stringBuffer[256]; 44270a96aa3bSJed Brown PetscBool flg; 44280a96aa3bSJed Brown 44290a96aa3bSJed Brown PetscFunctionBegin; 44309566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions_Forest(PetscOptionsObject,dm)); 4431d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject,"DM" P4EST_STRING " options"); 44329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_p4est_partition_for_coarsening","partition forest to allow for coarsening","DMP4estSetPartitionForCoarsening",pforest->partition_for_coarsening,&(pforest->partition_for_coarsening),NULL)); 44339566063dSJacob 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)); 4434d0609cedSBarry Smith PetscOptionsHeadEnd(); 44350a96aa3bSJed Brown if (flg) { 44369566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName)); 44379566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(stringBuffer,&pforest->ghostName)); 44380a96aa3bSJed Brown } 44390a96aa3bSJed Brown PetscFunctionReturn(0); 44400a96aa3bSJed Brown } 44410a96aa3bSJed Brown 44420a96aa3bSJed Brown #if !defined(P4_TO_P8) 44430a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP4estGetPartitionForCoarsening 44440a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP4estSetPartitionForCoarsening 44450a96aa3bSJed Brown #else 44460a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP8estGetPartitionForCoarsening 44470a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP8estSetPartitionForCoarsening 44480a96aa3bSJed Brown #endif 44490a96aa3bSJed Brown 44500a96aa3bSJed Brown PETSC_EXTERN PetscErrorCode DMPforestGetPartitionForCoarsening(DM dm, PetscBool *flg) 44510a96aa3bSJed Brown { 44520a96aa3bSJed Brown DM_Forest_pforest *pforest; 44530a96aa3bSJed Brown 44540a96aa3bSJed Brown PetscFunctionBegin; 44550a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 44560a96aa3bSJed Brown pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 44570a96aa3bSJed Brown *flg = pforest->partition_for_coarsening; 44580a96aa3bSJed Brown PetscFunctionReturn(0); 44590a96aa3bSJed Brown } 44600a96aa3bSJed Brown 44610a96aa3bSJed Brown PETSC_EXTERN PetscErrorCode DMPforestSetPartitionForCoarsening(DM dm, PetscBool flg) 44620a96aa3bSJed Brown { 44630a96aa3bSJed Brown DM_Forest_pforest *pforest; 44640a96aa3bSJed Brown 44650a96aa3bSJed Brown PetscFunctionBegin; 44660a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 44670a96aa3bSJed Brown pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 44680a96aa3bSJed Brown pforest->partition_for_coarsening = flg; 44690a96aa3bSJed Brown PetscFunctionReturn(0); 44700a96aa3bSJed Brown } 44710a96aa3bSJed Brown 44720a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM dm,DM *plex) 44730a96aa3bSJed Brown { 44740a96aa3bSJed Brown DM_Forest_pforest *pforest; 44750a96aa3bSJed Brown 44760a96aa3bSJed Brown PetscFunctionBegin; 44770a96aa3bSJed Brown if (plex) *plex = NULL; 44789566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 44790a96aa3bSJed Brown pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 44800a96aa3bSJed Brown if (!pforest->plex) { 44819566063dSJacob Faibussowitsch PetscCall(DMConvert_pforest_plex(dm,DMPLEX,NULL)); 44820a96aa3bSJed Brown } 44839566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm,pforest->plex)); 44840a96aa3bSJed Brown if (plex) *plex = pforest->plex; 44850a96aa3bSJed Brown PetscFunctionReturn(0); 44860a96aa3bSJed Brown } 44870a96aa3bSJed Brown 44880a96aa3bSJed Brown #define DMCreateInterpolation_pforest _append_pforest(DMCreateInterpolation) 44890a96aa3bSJed Brown static PetscErrorCode DMCreateInterpolation_pforest(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 44900a96aa3bSJed Brown { 44910a96aa3bSJed Brown PetscSection gsc, gsf; 44920a96aa3bSJed Brown PetscInt m, n; 44930a96aa3bSJed Brown DM cdm; 44940a96aa3bSJed Brown 44950a96aa3bSJed Brown PetscFunctionBegin; 44969566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 44979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 44989566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 44999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 45000a96aa3bSJed Brown 45019566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmFine), interpolation)); 45029566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 45039566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, MATAIJ)); 45040a96aa3bSJed Brown 45059566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 450608401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse,PetscObjectComm((PetscObject)dmFine),PETSC_ERR_SUP,"Only interpolation from coarse DM for now"); 45070a96aa3bSJed Brown 45080a96aa3bSJed Brown { 45090a96aa3bSJed Brown DM plexF, plexC; 45100a96aa3bSJed Brown PetscSF sf; 45110a96aa3bSJed Brown PetscInt *cids; 45120a96aa3bSJed Brown PetscInt dofPerDim[4] = {1,1,1,1}; 45130a96aa3bSJed Brown 45149566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse,&plexC)); 45159566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine,&plexF)); 45169566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 45179566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 45189566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInterpolatorTree(plexC, plexF, sf, cids, *interpolation)); 45199566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 45209566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 45210a96aa3bSJed Brown } 45229566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 45230a96aa3bSJed Brown /* Use naive scaling */ 45249566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 45250a96aa3bSJed Brown PetscFunctionReturn(0); 45260a96aa3bSJed Brown } 45270a96aa3bSJed Brown 45280a96aa3bSJed Brown #define DMCreateInjection_pforest _append_pforest(DMCreateInjection) 45290a96aa3bSJed Brown static PetscErrorCode DMCreateInjection_pforest(DM dmCoarse, DM dmFine, Mat *injection) 45300a96aa3bSJed Brown { 45310a96aa3bSJed Brown PetscSection gsc, gsf; 45320a96aa3bSJed Brown PetscInt m, n; 45330a96aa3bSJed Brown DM cdm; 45340a96aa3bSJed Brown 45350a96aa3bSJed Brown PetscFunctionBegin; 45369566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 45379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &n)); 45389566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 45399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &m)); 45400a96aa3bSJed Brown 45419566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmFine), injection)); 45429566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*injection, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 45439566063dSJacob Faibussowitsch PetscCall(MatSetType(*injection, MATAIJ)); 45440a96aa3bSJed Brown 45459566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 454608401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse,PetscObjectComm((PetscObject)dmFine),PETSC_ERR_SUP,"Only injection to coarse DM for now"); 45470a96aa3bSJed Brown 45480a96aa3bSJed Brown { 45490a96aa3bSJed Brown DM plexF, plexC; 45500a96aa3bSJed Brown PetscSF sf; 45510a96aa3bSJed Brown PetscInt *cids; 45520a96aa3bSJed Brown PetscInt dofPerDim[4] = {1,1,1,1}; 45530a96aa3bSJed Brown 45549566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse,&plexC)); 45559566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine,&plexF)); 45569566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 45579566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 45589566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorTree(plexC, plexF, sf, cids, *injection)); 45599566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 45609566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 45610a96aa3bSJed Brown } 45629566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*injection, NULL, "-inject_mat_view")); 45630a96aa3bSJed Brown /* Use naive scaling */ 45640a96aa3bSJed Brown PetscFunctionReturn(0); 45650a96aa3bSJed Brown } 45660a96aa3bSJed Brown 45670a96aa3bSJed Brown #define DMForestTransferVecFromBase_pforest _append_pforest(DMForestTransferVecFromBase) 45680a96aa3bSJed Brown static PetscErrorCode DMForestTransferVecFromBase_pforest(DM dm, Vec vecIn, Vec vecOut) 45690a96aa3bSJed Brown { 45700a96aa3bSJed Brown DM dmIn, dmVecIn, base, basec, plex, coarseDM; 45710a96aa3bSJed Brown DM *hierarchy; 45720a96aa3bSJed Brown PetscSF sfRed = NULL; 45730a96aa3bSJed Brown PetscDS ds; 45740a96aa3bSJed Brown Vec vecInLocal, vecOutLocal; 45750a96aa3bSJed Brown DMLabel subpointMap; 45760a96aa3bSJed Brown PetscInt minLevel, mh, n_hi, i; 45770a96aa3bSJed Brown PetscBool hiforest, *hierarchy_forest; 45780a96aa3bSJed Brown 45790a96aa3bSJed Brown PetscFunctionBegin; 45809566063dSJacob Faibussowitsch PetscCall(VecGetDM(vecIn,&dmVecIn)); 45819566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmVecIn,&ds)); 458228b400f6SJacob Faibussowitsch PetscCheck(ds,PetscObjectComm((PetscObject)dmVecIn),PETSC_ERR_SUP,"Cannot transfer without a PetscDS object"); 45830a96aa3bSJed Brown { /* we cannot stick user contexts into function callbacks for DMProjectFieldLocal! */ 45840a96aa3bSJed Brown PetscSection section; 45850a96aa3bSJed Brown PetscInt Nf; 45860a96aa3bSJed Brown 45879566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn,§ion)); 45889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&Nf)); 458963a3b9bcSJacob 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); 45900a96aa3bSJed Brown } 45919566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&minLevel)); 459263a3b9bcSJacob Faibussowitsch PetscCheck(!minLevel,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot transfer with minimum refinement set to %" PetscInt_FMT ". Rerun with DMForestSetMinimumRefinement(dm,0)",minLevel); 45939566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 459428b400f6SJacob Faibussowitsch PetscCheck(base,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing base DM"); 45950a96aa3bSJed Brown 45969566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut,0.0)); 45970a96aa3bSJed Brown if (dmVecIn == base) { /* sequential runs */ 45989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 45990a96aa3bSJed Brown } else { 46000a96aa3bSJed Brown PetscSection secIn, secInRed; 46010a96aa3bSJed Brown Vec vecInRed, vecInLocal; 46020a96aa3bSJed Brown 46039566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)base,"_base_migration_sf",(PetscObject*)&sfRed)); 460428b400f6SJacob Faibussowitsch PetscCheck(sfRed,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not the DM set with DMForestSetBaseDM()"); 46059566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmVecIn),&secInRed)); 46069566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF,&vecInRed)); 46079566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn,&secIn)); 46089566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmVecIn,&vecInLocal)); 46099566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmVecIn,vecIn,INSERT_VALUES,vecInLocal)); 46109566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmVecIn,vecIn,INSERT_VALUES,vecInLocal)); 46119566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dmVecIn,sfRed,secIn,vecInLocal,secInRed,vecInRed)); 46129566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmVecIn,&vecInLocal)); 46139566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secInRed)); 46140a96aa3bSJed Brown vecIn = vecInRed; 46150a96aa3bSJed Brown } 46160a96aa3bSJed Brown 46170a96aa3bSJed Brown /* we first search through the AdaptivityForest hierarchy 46180a96aa3bSJed Brown once we found the first disconnected forest, we upsweep the DM hierarchy */ 46190a96aa3bSJed Brown hiforest = PETSC_TRUE; 46200a96aa3bSJed Brown 46210a96aa3bSJed Brown /* upsweep to the coarsest DM */ 46220a96aa3bSJed Brown n_hi = 0; 46230a96aa3bSJed Brown coarseDM = dm; 46240a96aa3bSJed Brown do { 46250a96aa3bSJed Brown PetscBool isforest; 46260a96aa3bSJed Brown 46270a96aa3bSJed Brown dmIn = coarseDM; 46280a96aa3bSJed Brown /* need to call DMSetUp to have the hierarchy recursively setup */ 46299566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmIn)); 46309566063dSJacob Faibussowitsch PetscCall(DMIsForest(dmIn,&isforest)); 463128b400f6SJacob Faibussowitsch PetscCheck(isforest,PetscObjectComm((PetscObject)dmIn),PETSC_ERR_SUP,"Cannot currently transfer through a mixed hierarchy! Found DM type %s",((PetscObject)dmIn)->type_name); 46320a96aa3bSJed Brown coarseDM = NULL; 46330a96aa3bSJed Brown if (hiforest) { 46349566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn,&coarseDM)); 46350a96aa3bSJed Brown } 46360a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 46370a96aa3bSJed Brown hiforest = PETSC_FALSE; 46389566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn,&coarseDM)); 46390a96aa3bSJed Brown } 46400a96aa3bSJed Brown n_hi++; 46410a96aa3bSJed Brown } while (coarseDM); 46420a96aa3bSJed Brown 46439566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n_hi,&hierarchy,n_hi,&hierarchy_forest)); 46440a96aa3bSJed Brown 46450a96aa3bSJed Brown i = 0; 46460a96aa3bSJed Brown hiforest = PETSC_TRUE; 46470a96aa3bSJed Brown coarseDM = dm; 46480a96aa3bSJed Brown do { 46490a96aa3bSJed Brown dmIn = coarseDM; 46500a96aa3bSJed Brown coarseDM = NULL; 46510a96aa3bSJed Brown if (hiforest) { 46529566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn,&coarseDM)); 46530a96aa3bSJed Brown } 46540a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 46550a96aa3bSJed Brown hiforest = PETSC_FALSE; 46569566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn,&coarseDM)); 46570a96aa3bSJed Brown } 46580a96aa3bSJed Brown i++; 46590a96aa3bSJed Brown hierarchy[n_hi - i] = dmIn; 46600a96aa3bSJed Brown } while (coarseDM); 46610a96aa3bSJed Brown 46620a96aa3bSJed Brown /* project base vector on the coarsest forest (minimum refinement = 0) */ 46639566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn,&plex)); 46640a96aa3bSJed Brown 46650a96aa3bSJed Brown /* Check this plex is compatible with the base */ 46660a96aa3bSJed Brown { 46670a96aa3bSJed Brown IS gnum[2]; 46680a96aa3bSJed Brown PetscInt ncells[2],gncells[2]; 46690a96aa3bSJed Brown 46709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(base,&gnum[0])); 46719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(plex,&gnum[1])); 46729566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[0],NULL,&ncells[0])); 46739566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[1],NULL,&ncells[1])); 46741c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(ncells,gncells,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm))); 467563a3b9bcSJacob 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); 46760a96aa3bSJed Brown } 46770a96aa3bSJed Brown 46789566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmIn,"_forest_base_subpoint_map",&subpointMap)); 467928b400f6SJacob Faibussowitsch PetscCheck(subpointMap,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing _forest_base_subpoint_map label"); 46800a96aa3bSJed Brown 46819566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(base,&mh)); 46829566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(plex,mh)); 46830a96aa3bSJed Brown 46849566063dSJacob Faibussowitsch PetscCall(DMClone(base,&basec)); 46859566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmVecIn,basec)); 46860a96aa3bSJed Brown if (sfRed) { 46879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 46880a96aa3bSJed Brown vecInLocal = vecIn; 46890a96aa3bSJed Brown } else { 46909566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(basec,&vecInLocal)); 46919566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(basec,vecIn,INSERT_VALUES,vecInLocal)); 46929566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(basec,vecIn,INSERT_VALUES,vecInLocal)); 46930a96aa3bSJed Brown } 46940a96aa3bSJed Brown 46959566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn,&vecOutLocal)); 46960a96aa3bSJed Brown { /* get degrees of freedom ordered onto dmIn */ 46970a96aa3bSJed Brown PetscSF basetocoarse; 46980a96aa3bSJed Brown PetscInt bStart, bEnd, nroots; 46990a96aa3bSJed Brown PetscInt iStart, iEnd, nleaves, leaf; 47000a96aa3bSJed Brown PetscMPIInt rank; 47010a96aa3bSJed Brown PetscSFNode *remotes; 47020a96aa3bSJed Brown PetscSection secIn, secOut; 47030a96aa3bSJed Brown PetscInt *remoteOffsets; 47040a96aa3bSJed Brown PetscSF transferSF; 47050a96aa3bSJed Brown const PetscScalar *inArray; 47060a96aa3bSJed Brown PetscScalar *outArray; 47070a96aa3bSJed Brown 47089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)basec), &rank)); 47099566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(basec, &bStart, &bEnd)); 47100a96aa3bSJed Brown nroots = PetscMax(bEnd - bStart, 0); 47119566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &iStart, &iEnd)); 47120a96aa3bSJed Brown nleaves = PetscMax(iEnd - iStart, 0); 47130a96aa3bSJed Brown 47149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotes)); 47150a96aa3bSJed Brown for (leaf = iStart; leaf < iEnd; leaf++) { 47160a96aa3bSJed Brown PetscInt index; 47170a96aa3bSJed Brown 47180a96aa3bSJed Brown remotes[leaf - iStart].rank = rank; 47199566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, leaf, &index)); 47200a96aa3bSJed Brown remotes[leaf - iStart].index = index; 47210a96aa3bSJed Brown } 47220a96aa3bSJed Brown 47239566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)basec), &basetocoarse)); 47249566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(basetocoarse, nroots, nleaves, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 47259566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(basetocoarse)); 47269566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(basec,&secIn)); 47279566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmIn),&secOut)); 47289566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(basetocoarse, secIn, &remoteOffsets, secOut)); 47299566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(basetocoarse, secIn, remoteOffsets, secOut, &transferSF)); 47309566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 47319566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(vecOutLocal, &outArray)); 47329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecInLocal, &inArray)); 47339566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferSF, MPIU_SCALAR, inArray, outArray,MPI_REPLACE)); 47349566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferSF, MPIU_SCALAR, inArray, outArray,MPI_REPLACE)); 47359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecInLocal, &inArray)); 47369566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(vecOutLocal, &outArray)); 47379566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferSF)); 47389566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secOut)); 47399566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&basetocoarse)); 47400a96aa3bSJed Brown } 47419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecInLocal)); 47429566063dSJacob Faibussowitsch PetscCall(DMDestroy(&basec)); 47439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecIn)); 47440a96aa3bSJed Brown 47450a96aa3bSJed Brown /* output */ 47460a96aa3bSJed Brown if (n_hi > 1) { /* downsweep the stored hierarchy */ 47470a96aa3bSJed Brown Vec vecOut1, vecOut2; 47480a96aa3bSJed Brown DM fineDM; 47490a96aa3bSJed Brown 47509566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmIn,&vecOut1)); 47519566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn,vecOutLocal,INSERT_VALUES,vecOut1)); 47529566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn,&vecOutLocal)); 47530a96aa3bSJed Brown for (i = 1; i < n_hi-1; i++) { 47540a96aa3bSJed Brown fineDM = hierarchy[i]; 47559566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(fineDM,&vecOut2)); 47569566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn,vecOut1,fineDM,vecOut2,PETSC_TRUE,0.0)); 47579566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn,&vecOut1)); 47580a96aa3bSJed Brown vecOut1 = vecOut2; 47590a96aa3bSJed Brown dmIn = fineDM; 47600a96aa3bSJed Brown } 47619566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn,vecOut1,dm,vecOut,PETSC_TRUE,0.0)); 47629566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn,&vecOut1)); 47630a96aa3bSJed Brown } else { 47649566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn,vecOutLocal,INSERT_VALUES,vecOut)); 47659566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn,&vecOutLocal)); 47660a96aa3bSJed Brown } 47679566063dSJacob Faibussowitsch PetscCall(PetscFree2(hierarchy,hierarchy_forest)); 47680a96aa3bSJed Brown PetscFunctionReturn(0); 47690a96aa3bSJed Brown } 47700a96aa3bSJed Brown 47710a96aa3bSJed Brown #define DMForestTransferVec_pforest _append_pforest(DMForestTransferVec) 47720a96aa3bSJed Brown static PetscErrorCode DMForestTransferVec_pforest(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time) 47730a96aa3bSJed Brown { 47740a96aa3bSJed Brown DM adaptIn, adaptOut, plexIn, plexOut; 47750a96aa3bSJed Brown DM_Forest *forestIn, *forestOut, *forestAdaptIn, *forestAdaptOut; 47760a96aa3bSJed Brown PetscInt dofPerDim[] = {1, 1, 1, 1}; 47770a96aa3bSJed Brown PetscSF inSF = NULL, outSF = NULL; 47780a96aa3bSJed Brown PetscInt *inCids = NULL, *outCids = NULL; 47790a96aa3bSJed Brown DMAdaptFlag purposeIn, purposeOut; 47800a96aa3bSJed Brown 47810a96aa3bSJed Brown PetscFunctionBegin; 47820a96aa3bSJed Brown forestOut = (DM_Forest *) dmOut->data; 47830a96aa3bSJed Brown forestIn = (DM_Forest *) dmIn->data; 47840a96aa3bSJed Brown 47859566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmOut,&adaptOut)); 47869566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmOut,&purposeOut)); 47870a96aa3bSJed Brown forestAdaptOut = adaptOut ? (DM_Forest *) adaptOut->data : NULL; 47880a96aa3bSJed Brown 47899566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn,&adaptIn)); 47909566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmIn,&purposeIn)); 47910a96aa3bSJed Brown forestAdaptIn = adaptIn ? (DM_Forest *) adaptIn->data : NULL; 47920a96aa3bSJed Brown 47930a96aa3bSJed Brown if (forestAdaptOut == forestIn) { 47940a96aa3bSJed Brown switch (purposeOut) { 47950a96aa3bSJed Brown case DM_ADAPT_REFINE: 47969566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids)); 47979566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47980a96aa3bSJed Brown break; 47990a96aa3bSJed Brown case DM_ADAPT_COARSEN: 48000a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 48019566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_TRUE,&outCids)); 48029566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 48030a96aa3bSJed Brown break; 48040a96aa3bSJed Brown default: 48059566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids)); 48069566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_FALSE,&outCids)); 48079566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 48089566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 48090a96aa3bSJed Brown } 48100a96aa3bSJed Brown } else if (forestAdaptIn == forestOut) { 48110a96aa3bSJed Brown switch (purposeIn) { 48120a96aa3bSJed Brown case DM_ADAPT_REFINE: 48139566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_TRUE,&inCids)); 48149566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 48150a96aa3bSJed Brown break; 48160a96aa3bSJed Brown case DM_ADAPT_COARSEN: 48170a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 48189566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids)); 48199566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 48200a96aa3bSJed Brown break; 48210a96aa3bSJed Brown default: 48229566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids)); 48239566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_FALSE,&outCids)); 48249566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 48259566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 48260a96aa3bSJed Brown } 48270a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dmIn),PETSC_ERR_SUP,"Only support transfer from pre-adaptivity to post-adaptivity right now"); 48289566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn,&plexIn)); 48299566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmOut,&plexOut)); 48300a96aa3bSJed Brown 48319566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree(plexIn,vecIn,plexOut,vecOut,inSF,outSF,inCids,outCids,useBCs,time)); 48329566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 48339566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 48349566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&inSF)); 48359566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&outSF)); 48369566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 48379566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 48380a96aa3bSJed Brown PetscFunctionReturn(0); 48390a96aa3bSJed Brown } 48400a96aa3bSJed Brown 48410a96aa3bSJed Brown #define DMCreateCoordinateDM_pforest _append_pforest(DMCreateCoordinateDM) 48420a96aa3bSJed Brown static PetscErrorCode DMCreateCoordinateDM_pforest(DM dm,DM *cdm) 48430a96aa3bSJed Brown { 48440a96aa3bSJed Brown DM plex; 48450a96aa3bSJed Brown 48460a96aa3bSJed Brown PetscFunctionBegin; 48470a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 48489566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 48499566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(plex,cdm)); 48509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*cdm)); 48510a96aa3bSJed Brown PetscFunctionReturn(0); 48520a96aa3bSJed Brown } 48530a96aa3bSJed Brown 48540a96aa3bSJed Brown #define VecViewLocal_pforest _append_pforest(VecViewLocal) 48550a96aa3bSJed Brown static PetscErrorCode VecViewLocal_pforest(Vec vec,PetscViewer viewer) 48560a96aa3bSJed Brown { 48570a96aa3bSJed Brown DM dm, plex; 48580a96aa3bSJed Brown 48590a96aa3bSJed Brown PetscFunctionBegin; 48609566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 48619566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 48629566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 48639566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(vec,viewer)); 48649566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 48650a96aa3bSJed Brown PetscFunctionReturn(0); 48660a96aa3bSJed Brown } 48670a96aa3bSJed Brown 48680a96aa3bSJed Brown #define VecView_pforest _append_pforest(VecView) 48690a96aa3bSJed Brown static PetscErrorCode VecView_pforest(Vec vec,PetscViewer viewer) 48700a96aa3bSJed Brown { 48710a96aa3bSJed Brown DM dm, plex; 48720a96aa3bSJed Brown 48730a96aa3bSJed Brown PetscFunctionBegin; 48749566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 48759566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 48769566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 48779566063dSJacob Faibussowitsch PetscCall(VecView_Plex(vec,viewer)); 48789566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 48790a96aa3bSJed Brown PetscFunctionReturn(0); 48800a96aa3bSJed Brown } 48810a96aa3bSJed Brown 48820a96aa3bSJed Brown #define VecView_pforest_Native _infix_pforest(VecView,_Native) 48830a96aa3bSJed Brown static PetscErrorCode VecView_pforest_Native(Vec vec,PetscViewer viewer) 48840a96aa3bSJed Brown { 48850a96aa3bSJed Brown DM dm, plex; 48860a96aa3bSJed Brown 48870a96aa3bSJed Brown PetscFunctionBegin; 48889566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 48899566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 48909566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 48919566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Native(vec,viewer)); 48929566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 48930a96aa3bSJed Brown PetscFunctionReturn(0); 48940a96aa3bSJed Brown } 48950a96aa3bSJed Brown 48960a96aa3bSJed Brown #define VecLoad_pforest _append_pforest(VecLoad) 48970a96aa3bSJed Brown static PetscErrorCode VecLoad_pforest(Vec vec,PetscViewer viewer) 48980a96aa3bSJed Brown { 48990a96aa3bSJed Brown DM dm, plex; 49000a96aa3bSJed Brown 49010a96aa3bSJed Brown PetscFunctionBegin; 49029566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 49039566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49049566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 49059566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex(vec,viewer)); 49069566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 49070a96aa3bSJed Brown PetscFunctionReturn(0); 49080a96aa3bSJed Brown } 49090a96aa3bSJed Brown 49100a96aa3bSJed Brown #define VecLoad_pforest_Native _infix_pforest(VecLoad,_Native) 49110a96aa3bSJed Brown static PetscErrorCode VecLoad_pforest_Native(Vec vec,PetscViewer viewer) 49120a96aa3bSJed Brown { 49130a96aa3bSJed Brown DM dm, plex; 49140a96aa3bSJed Brown 49150a96aa3bSJed Brown PetscFunctionBegin; 49169566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 49179566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49189566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 49199566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_Native(vec,viewer)); 49209566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 49210a96aa3bSJed Brown PetscFunctionReturn(0); 49220a96aa3bSJed Brown } 49230a96aa3bSJed Brown 49240a96aa3bSJed Brown #define DMCreateGlobalVector_pforest _append_pforest(DMCreateGlobalVector) 49250a96aa3bSJed Brown static PetscErrorCode DMCreateGlobalVector_pforest(DM dm,Vec *vec) 49260a96aa3bSJed Brown { 49270a96aa3bSJed Brown PetscFunctionBegin; 49289566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm,vec)); 49299566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 49309566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_pforest)); 49319566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_pforest_Native)); 49329566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_pforest)); 49339566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_pforest_Native)); 49340a96aa3bSJed Brown PetscFunctionReturn(0); 49350a96aa3bSJed Brown } 49360a96aa3bSJed Brown 49370a96aa3bSJed Brown #define DMCreateLocalVector_pforest _append_pforest(DMCreateLocalVector) 49380a96aa3bSJed Brown static PetscErrorCode DMCreateLocalVector_pforest(DM dm,Vec *vec) 49390a96aa3bSJed Brown { 49400a96aa3bSJed Brown PetscFunctionBegin; 49419566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm,vec)); 49429566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecViewLocal_pforest)); 49430a96aa3bSJed Brown PetscFunctionReturn(0); 49440a96aa3bSJed Brown } 49450a96aa3bSJed Brown 49460a96aa3bSJed Brown #define DMCreateMatrix_pforest _append_pforest(DMCreateMatrix) 49470a96aa3bSJed Brown static PetscErrorCode DMCreateMatrix_pforest(DM dm,Mat *mat) 49480a96aa3bSJed Brown { 49490a96aa3bSJed Brown DM plex; 49500a96aa3bSJed Brown 49510a96aa3bSJed Brown PetscFunctionBegin; 49520a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49539566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49540a96aa3bSJed Brown if (plex->prealloc_only != dm->prealloc_only) plex->prealloc_only = dm->prealloc_only; /* maybe this should go into forest->plex */ 49559566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(plex,mat)); 49569566063dSJacob Faibussowitsch PetscCall(MatSetDM(*mat,dm)); 49570a96aa3bSJed Brown PetscFunctionReturn(0); 49580a96aa3bSJed Brown } 49590a96aa3bSJed Brown 49600a96aa3bSJed Brown #define DMProjectFunctionLocal_pforest _append_pforest(DMProjectFunctionLocal) 49610a96aa3bSJed Brown static PetscErrorCode DMProjectFunctionLocal_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs) (PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void*), void **ctxs, InsertMode mode, Vec localX) 49620a96aa3bSJed Brown { 49630a96aa3bSJed Brown DM plex; 49640a96aa3bSJed Brown 49650a96aa3bSJed Brown PetscFunctionBegin; 49660a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49679566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49689566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLocal(plex,time,funcs,ctxs,mode,localX)); 49690a96aa3bSJed Brown PetscFunctionReturn(0); 49700a96aa3bSJed Brown } 49710a96aa3bSJed Brown 49720a96aa3bSJed Brown #define DMProjectFunctionLabelLocal_pforest _append_pforest(DMProjectFunctionLabelLocal) 49730a96aa3bSJed Brown 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) 49740a96aa3bSJed Brown { 49750a96aa3bSJed Brown DM plex; 49760a96aa3bSJed Brown 49770a96aa3bSJed Brown PetscFunctionBegin; 49780a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49799566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49809566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLabelLocal(plex,time,label,numIds,ids,Ncc,comps,funcs,ctxs,mode,localX)); 49810a96aa3bSJed Brown PetscFunctionReturn(0); 49820a96aa3bSJed Brown } 49830a96aa3bSJed Brown 49840a96aa3bSJed Brown #define DMProjectFieldLocal_pforest _append_pforest(DMProjectFieldLocal) 49850a96aa3bSJed Brown PetscErrorCode DMProjectFieldLocal_pforest(DM dm, PetscReal time, Vec localU,void (**funcs) (PetscInt, PetscInt, PetscInt, 49860a96aa3bSJed Brown const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 49870a96aa3bSJed Brown const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 49880a96aa3bSJed Brown PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),InsertMode mode, Vec localX) 49890a96aa3bSJed Brown { 49900a96aa3bSJed Brown DM plex; 49910a96aa3bSJed Brown 49920a96aa3bSJed Brown PetscFunctionBegin; 49930a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49949566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49959566063dSJacob Faibussowitsch PetscCall(DMProjectFieldLocal(plex,time,localU,funcs,mode,localX)); 49960a96aa3bSJed Brown PetscFunctionReturn(0); 49970a96aa3bSJed Brown } 49980a96aa3bSJed Brown 49990a96aa3bSJed Brown #define DMComputeL2Diff_pforest _append_pforest(DMComputeL2Diff) 50000a96aa3bSJed Brown PetscErrorCode DMComputeL2Diff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs) (PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void*), void **ctxs, Vec X, PetscReal *diff) 50010a96aa3bSJed Brown { 50020a96aa3bSJed Brown DM plex; 50030a96aa3bSJed Brown 50040a96aa3bSJed Brown PetscFunctionBegin; 50050a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 50069566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 50079566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(plex,time,funcs,ctxs,X,diff)); 50080a96aa3bSJed Brown PetscFunctionReturn(0); 50090a96aa3bSJed Brown } 50100a96aa3bSJed Brown 50110a96aa3bSJed Brown #define DMComputeL2FieldDiff_pforest _append_pforest(DMComputeL2FieldDiff) 50120a96aa3bSJed Brown PetscErrorCode DMComputeL2FieldDiff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs) (PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void*), void **ctxs, Vec X, PetscReal diff[]) 50130a96aa3bSJed Brown { 50140a96aa3bSJed Brown DM plex; 50150a96aa3bSJed Brown 50160a96aa3bSJed Brown PetscFunctionBegin; 50170a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 50189566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 50199566063dSJacob Faibussowitsch PetscCall(DMComputeL2FieldDiff(plex,time,funcs,ctxs,X,diff)); 50200a96aa3bSJed Brown PetscFunctionReturn(0); 50210a96aa3bSJed Brown } 50220a96aa3bSJed Brown 50230a96aa3bSJed Brown #define DMCreatelocalsection_pforest _append_pforest(DMCreatelocalsection) 50240a96aa3bSJed Brown static PetscErrorCode DMCreatelocalsection_pforest(DM dm) 50250a96aa3bSJed Brown { 50260a96aa3bSJed Brown DM plex; 50270a96aa3bSJed Brown PetscSection section; 50280a96aa3bSJed Brown 50290a96aa3bSJed Brown PetscFunctionBegin; 50300a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 50319566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 50329566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(plex,§ion)); 50339566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(dm,section)); 50340a96aa3bSJed Brown PetscFunctionReturn(0); 50350a96aa3bSJed Brown } 50360a96aa3bSJed Brown 50370a96aa3bSJed Brown #define DMCreateDefaultConstraints_pforest _append_pforest(DMCreateDefaultConstraints) 50380a96aa3bSJed Brown static PetscErrorCode DMCreateDefaultConstraints_pforest(DM dm) 50390a96aa3bSJed Brown { 50400a96aa3bSJed Brown DM plex; 50410a96aa3bSJed Brown Mat mat; 504279769bd5SJed Brown Vec bias; 50430a96aa3bSJed Brown PetscSection section; 50440a96aa3bSJed Brown 50450a96aa3bSJed Brown PetscFunctionBegin; 50460a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 50479566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 50489566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(plex,§ion,&mat,&bias)); 50499566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,section,mat,bias)); 50500a96aa3bSJed Brown PetscFunctionReturn(0); 50510a96aa3bSJed Brown } 50520a96aa3bSJed Brown 50530a96aa3bSJed Brown #define DMGetDimPoints_pforest _append_pforest(DMGetDimPoints) 50540a96aa3bSJed Brown static PetscErrorCode DMGetDimPoints_pforest(DM dm, PetscInt dim, PetscInt *cStart, PetscInt *cEnd) 50550a96aa3bSJed Brown { 50560a96aa3bSJed Brown DM plex; 50570a96aa3bSJed Brown 50580a96aa3bSJed Brown PetscFunctionBegin; 50590a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 50609566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 50619566063dSJacob Faibussowitsch PetscCall(DMGetDimPoints(plex,dim,cStart,cEnd)); 50620a96aa3bSJed Brown PetscFunctionReturn(0); 50630a96aa3bSJed Brown } 50640a96aa3bSJed Brown 50650a96aa3bSJed Brown /* Need to forward declare */ 50660a96aa3bSJed Brown #define DMInitialize_pforest _append_pforest(DMInitialize) 50670a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm); 50680a96aa3bSJed Brown 50690a96aa3bSJed Brown #define DMClone_pforest _append_pforest(DMClone) 50700a96aa3bSJed Brown static PetscErrorCode DMClone_pforest(DM dm, DM *newdm) 50710a96aa3bSJed Brown { 50720a96aa3bSJed Brown PetscFunctionBegin; 50739566063dSJacob Faibussowitsch PetscCall(DMClone_Forest(dm,newdm)); 50749566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(*newdm)); 50750a96aa3bSJed Brown PetscFunctionReturn(0); 50760a96aa3bSJed Brown } 50770a96aa3bSJed Brown 50780a96aa3bSJed Brown #define DMForestCreateCellChart_pforest _append_pforest(DMForestCreateCellChart) 50790a96aa3bSJed Brown static PetscErrorCode DMForestCreateCellChart_pforest(DM dm, PetscInt *cStart, PetscInt *cEnd) 50800a96aa3bSJed Brown { 50810a96aa3bSJed Brown DM_Forest *forest; 50820a96aa3bSJed Brown DM_Forest_pforest *pforest; 50830a96aa3bSJed Brown PetscInt overlap; 50840a96aa3bSJed Brown 50850a96aa3bSJed Brown PetscFunctionBegin; 50869566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 50870a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 50880a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 50890a96aa3bSJed Brown *cStart = 0; 50909566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm,&overlap)); 50910a96aa3bSJed Brown if (overlap && pforest->ghost) { 50920a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[pforest->forest->mpisize]; 50930a96aa3bSJed Brown } else { 50940a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants; 50950a96aa3bSJed Brown } 50960a96aa3bSJed Brown PetscFunctionReturn(0); 50970a96aa3bSJed Brown } 50980a96aa3bSJed Brown 50990a96aa3bSJed Brown #define DMForestCreateCellSF_pforest _append_pforest(DMForestCreateCellSF) 51000a96aa3bSJed Brown static PetscErrorCode DMForestCreateCellSF_pforest(DM dm, PetscSF *cellSF) 51010a96aa3bSJed Brown { 51020a96aa3bSJed Brown DM_Forest *forest; 51030a96aa3bSJed Brown DM_Forest_pforest *pforest; 51040a96aa3bSJed Brown PetscMPIInt rank; 51050a96aa3bSJed Brown PetscInt overlap; 51060a96aa3bSJed Brown PetscInt cStart, cEnd, cLocalStart, cLocalEnd; 51070a96aa3bSJed Brown PetscInt nRoots, nLeaves, *mine = NULL; 51080a96aa3bSJed Brown PetscSFNode *remote = NULL; 51090a96aa3bSJed Brown PetscSF sf; 51100a96aa3bSJed Brown 51110a96aa3bSJed Brown PetscFunctionBegin; 51129566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(dm,&cStart,&cEnd)); 51130a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 51140a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 51150a96aa3bSJed Brown nRoots = cEnd - cStart; 51160a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 51170a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 51180a96aa3bSJed Brown nLeaves = 0; 51199566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm,&overlap)); 51209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank)); 51210a96aa3bSJed Brown if (overlap && pforest->ghost) { 51220a96aa3bSJed Brown PetscSFNode *mirror; 51230a96aa3bSJed Brown p4est_quadrant_t *mirror_array; 51240a96aa3bSJed Brown PetscInt nMirror, nGhostPre, nSelf, q; 51250a96aa3bSJed Brown void **mirrorPtrs; 51260a96aa3bSJed Brown 51270a96aa3bSJed Brown nMirror = (PetscInt) pforest->ghost->mirrors.elem_count; 51280a96aa3bSJed Brown nSelf = cLocalEnd - cLocalStart; 51290a96aa3bSJed Brown nLeaves = nRoots - nSelf; 51300a96aa3bSJed Brown nGhostPre = (PetscInt) pforest->ghost->proc_offsets[rank]; 51319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves,&mine)); 51329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves,&remote)); 51339566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nMirror,&mirror,nMirror,&mirrorPtrs)); 51340a96aa3bSJed Brown mirror_array = (p4est_quadrant_t*) pforest->ghost->mirrors.array; 51350a96aa3bSJed Brown for (q = 0; q < nMirror; q++) { 51360a96aa3bSJed Brown p4est_quadrant_t *mir = &(mirror_array[q]); 51370a96aa3bSJed Brown 51380a96aa3bSJed Brown mirror[q].rank = rank; 51390a96aa3bSJed Brown mirror[q].index = (PetscInt) mir->p.piggy3.local_num + cLocalStart; 51400a96aa3bSJed Brown mirrorPtrs[q] = (void*) &(mirror[q]); 51410a96aa3bSJed Brown } 5142792fecdfSBarry Smith PetscCallP4est(p4est_ghost_exchange_custom,(pforest->forest,pforest->ghost,sizeof(PetscSFNode),mirrorPtrs,remote)); 51439566063dSJacob Faibussowitsch PetscCall(PetscFree2(mirror,mirrorPtrs)); 51440a96aa3bSJed Brown for (q = 0; q < nGhostPre; q++) mine[q] = q; 51450a96aa3bSJed Brown for (; q < nLeaves; q++) mine[q] = (q - nGhostPre) + cLocalEnd; 51460a96aa3bSJed Brown } 51479566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&sf)); 51489566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf,nRoots,nLeaves,mine,PETSC_OWN_POINTER,remote,PETSC_OWN_POINTER)); 51490a96aa3bSJed Brown *cellSF = sf; 51500a96aa3bSJed Brown PetscFunctionReturn(0); 51510a96aa3bSJed Brown } 51520a96aa3bSJed Brown 51530a96aa3bSJed Brown static PetscErrorCode DMCreateNeumannOverlap_pforest(DM dm, IS* ovl, Mat *J, PetscErrorCode (**setup)(Mat, PetscReal, Vec, Vec, PetscReal, IS, void*), void **setup_ctx) 51540a96aa3bSJed Brown { 51550a96aa3bSJed Brown DM plex; 51560a96aa3bSJed Brown 51570a96aa3bSJed Brown PetscFunctionBegin; 51589566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 51599566063dSJacob Faibussowitsch PetscCall(DMCreateNeumannOverlap_Plex(plex,ovl,J,setup,setup_ctx)); 51600a96aa3bSJed Brown if (!*setup) { 51619566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", setup)); 51620a96aa3bSJed Brown if (*setup) { 51639566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*ovl, "_DM_Original_HPDDM", (PetscObject)dm)); 51640a96aa3bSJed Brown } 51650a96aa3bSJed Brown } 51660a96aa3bSJed Brown PetscFunctionReturn(0); 51670a96aa3bSJed Brown } 51680a96aa3bSJed Brown 51690a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm) 51700a96aa3bSJed Brown { 51710a96aa3bSJed Brown PetscFunctionBegin; 51720a96aa3bSJed Brown dm->ops->setup = DMSetUp_pforest; 51730a96aa3bSJed Brown dm->ops->view = DMView_pforest; 51740a96aa3bSJed Brown dm->ops->clone = DMClone_pforest; 51750a96aa3bSJed Brown dm->ops->createinterpolation = DMCreateInterpolation_pforest; 51760a96aa3bSJed Brown dm->ops->createinjection = DMCreateInjection_pforest; 51770a96aa3bSJed Brown dm->ops->setfromoptions = DMSetFromOptions_pforest; 51780a96aa3bSJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_pforest; 51790a96aa3bSJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_pforest; 51800a96aa3bSJed Brown dm->ops->createlocalvector = DMCreateLocalVector_pforest; 51810a96aa3bSJed Brown dm->ops->creatematrix = DMCreateMatrix_pforest; 51820a96aa3bSJed Brown dm->ops->projectfunctionlocal = DMProjectFunctionLocal_pforest; 51830a96aa3bSJed Brown dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_pforest; 51840a96aa3bSJed Brown dm->ops->projectfieldlocal = DMProjectFieldLocal_pforest; 51850a96aa3bSJed Brown dm->ops->createlocalsection = DMCreatelocalsection_pforest; 51860a96aa3bSJed Brown dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_pforest; 51870a96aa3bSJed Brown dm->ops->computel2diff = DMComputeL2Diff_pforest; 51880a96aa3bSJed Brown dm->ops->computel2fielddiff = DMComputeL2FieldDiff_pforest; 51890a96aa3bSJed Brown dm->ops->getdimpoints = DMGetDimPoints_pforest; 51900a96aa3bSJed Brown 51919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_plex_pforest) "_C",DMConvert_plex_pforest)); 51929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_pforest_plex) "_C",DMConvert_pforest_plex)); 51939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",DMCreateNeumannOverlap_pforest)); 51949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",DMForestGetPartitionOverlap)); 51950a96aa3bSJed Brown PetscFunctionReturn(0); 51960a96aa3bSJed Brown } 51970a96aa3bSJed Brown 51980a96aa3bSJed Brown #define DMCreate_pforest _append_pforest(DMCreate) 51990a96aa3bSJed Brown PETSC_EXTERN PetscErrorCode DMCreate_pforest(DM dm) 52000a96aa3bSJed Brown { 52010a96aa3bSJed Brown DM_Forest *forest; 52020a96aa3bSJed Brown DM_Forest_pforest *pforest; 52030a96aa3bSJed Brown 52040a96aa3bSJed Brown PetscFunctionBegin; 52059566063dSJacob Faibussowitsch PetscCall(PetscP4estInitialize()); 52069566063dSJacob Faibussowitsch PetscCall(DMCreate_Forest(dm)); 52079566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(dm)); 52089566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm,P4EST_DIM)); 52090a96aa3bSJed Brown 52100a96aa3bSJed Brown /* set forest defaults */ 52119566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm,"unit")); 52129566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(dm,0)); 52139566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(dm,0)); 52149566063dSJacob Faibussowitsch PetscCall(DMForestSetMaximumRefinement(dm,P4EST_QMAXLEVEL)); 52159566063dSJacob Faibussowitsch PetscCall(DMForestSetGradeFactor(dm,2)); 52169566063dSJacob Faibussowitsch PetscCall(DMForestSetAdjacencyDimension(dm,0)); 52179566063dSJacob Faibussowitsch PetscCall(DMForestSetPartitionOverlap(dm,0)); 52180a96aa3bSJed Brown 52190a96aa3bSJed Brown /* create p4est data */ 52209566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm,&pforest)); 52210a96aa3bSJed Brown 52220a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 52230a96aa3bSJed Brown forest->data = pforest; 52240a96aa3bSJed Brown forest->destroy = DMForestDestroy_pforest; 52250a96aa3bSJed Brown forest->ftemplate = DMForestTemplate_pforest; 52260a96aa3bSJed Brown forest->transfervec = DMForestTransferVec_pforest; 52270a96aa3bSJed Brown forest->transfervecfrombase = DMForestTransferVecFromBase_pforest; 52280a96aa3bSJed Brown forest->createcellchart = DMForestCreateCellChart_pforest; 52290a96aa3bSJed Brown forest->createcellsf = DMForestCreateCellSF_pforest; 52300a96aa3bSJed Brown forest->clearadaptivityforest = DMForestClearAdaptivityForest_pforest; 52310a96aa3bSJed Brown forest->getadaptivitysuccess = DMForestGetAdaptivitySuccess_pforest; 52320a96aa3bSJed Brown pforest->topo = NULL; 52330a96aa3bSJed Brown pforest->forest = NULL; 52340a96aa3bSJed Brown pforest->ghost = NULL; 52350a96aa3bSJed Brown pforest->lnodes = NULL; 52360a96aa3bSJed Brown pforest->partition_for_coarsening = PETSC_TRUE; 52370a96aa3bSJed Brown pforest->coarsen_hierarchy = PETSC_FALSE; 52380a96aa3bSJed Brown pforest->cLocalStart = -1; 52390a96aa3bSJed Brown pforest->cLocalEnd = -1; 52400a96aa3bSJed Brown pforest->labelsFinalized = PETSC_FALSE; 52410a96aa3bSJed Brown pforest->ghostName = NULL; 52420a96aa3bSJed Brown PetscFunctionReturn(0); 52430a96aa3bSJed Brown } 52440a96aa3bSJed Brown 52450a96aa3bSJed Brown #endif /* defined(PETSC_HAVE_P4EST) */ 5246