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 } 2360a96aa3bSJed Brown if ((*topo)->geom) PetscStackCallP4est(p4est_geometry_destroy,((*topo)->geom)); 2370a96aa3bSJed Brown PetscStackCallP4est(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) 2580a96aa3bSJed Brown PetscStackCallP4estReturn((*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 2600a96aa3bSJed Brown PetscStackCallP4estReturn((*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; 2936858538eSMatthew G. Knepley PetscReal B[6] = {0.0,1.0,0.0,1.0,0.0,1.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]) { 3096858538eSMatthew G. Knepley L[i] = B[2 * i + 1]; 3106858538eSMatthew G. Knepley maxCell[i] = 1.1 * (L[i] / N[i]); 3116858538eSMatthew G. Knepley } 3120a96aa3bSJed Brown } 3139566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm,N,P,B,topo,useMorton)); 3146858538eSMatthew G. Knepley if (periodic) PetscCall(DMSetPeriodicity(dm, maxCell, L)); 3150a96aa3bSJed Brown } else { 3169566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm,topo)); 3170a96aa3bSJed Brown 3180a96aa3bSJed Brown (*topo)->refct = 1; 3190a96aa3bSJed Brown PetscStackCallP4estReturn((*topo)->conn,p4est_connectivity_new_byname,(name)); 3200a96aa3bSJed Brown (*topo)->geom = NULL; 3211baa6e33SBarry Smith if (isMoebius) PetscCall(DMSetCoordinateDim(dm,3)); 3220a96aa3bSJed Brown #if defined(P4_TO_P8) 3230a96aa3bSJed Brown if (isShell) { 3240a96aa3bSJed Brown PetscReal R2 = 1., R1 = .55; 3250a96aa3bSJed Brown 3260a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3279566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_shell_outer_radius",&R2,NULL)); 3289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_shell_inner_radius",&R1,NULL)); 3290a96aa3bSJed Brown } 3300a96aa3bSJed Brown PetscStackCallP4estReturn((*topo)->geom,p8est_geometry_new_shell,((*topo)->conn,R2,R1)); 3310a96aa3bSJed Brown } else if (isSphere) { 3320a96aa3bSJed Brown PetscReal R2 = 1., R1 = 0.191728, R0 = 0.039856; 3330a96aa3bSJed Brown 3340a96aa3bSJed Brown if (dm->setfromoptionscalled) { 3359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_sphere_outer_radius",&R2,NULL)); 3369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_sphere_inner_radius",&R1,NULL)); 3379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_sphere_core_radius",&R0,NULL)); 3380a96aa3bSJed Brown } 3390a96aa3bSJed Brown PetscStackCallP4estReturn((*topo)->geom,p8est_geometry_new_sphere,((*topo)->conn,R2,R1,R0)); 3400a96aa3bSJed Brown } 3410a96aa3bSJed Brown #endif 3429566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn,&(*topo)->tree_face_to_uniq)); 3430a96aa3bSJed Brown } 3440a96aa3bSJed Brown PetscFunctionReturn(0); 3450a96aa3bSJed Brown } 3460a96aa3bSJed Brown 3470a96aa3bSJed Brown #define DMConvert_plex_pforest _append_pforest(DMConvert_plex) 3480a96aa3bSJed Brown static PetscErrorCode DMConvert_plex_pforest(DM dm, DMType newtype, DM *pforest) 3490a96aa3bSJed Brown { 3500a96aa3bSJed Brown MPI_Comm comm; 3510a96aa3bSJed Brown PetscBool isPlex; 3520a96aa3bSJed Brown PetscInt dim; 3530a96aa3bSJed Brown void *ctx; 3540a96aa3bSJed Brown 3550a96aa3bSJed Brown PetscFunctionBegin; 3560a96aa3bSJed Brown 3570a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3580a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 3599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isPlex)); 36028b400f6SJacob Faibussowitsch PetscCheck(isPlex,comm,PETSC_ERR_ARG_WRONG,"Expected DM type %s, got %s",DMPLEX,((PetscObject)dm)->type_name); 3619566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm,&dim)); 36263a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM,comm,PETSC_ERR_ARG_WRONG,"Expected DM dimension %d, got %" PetscInt_FMT,P4EST_DIM,dim); 3639566063dSJacob Faibussowitsch PetscCall(DMCreate(comm,pforest)); 3649566063dSJacob Faibussowitsch PetscCall(DMSetType(*pforest,DMPFOREST)); 3659566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(*pforest,dm)); 3669566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dm,&ctx)); 3679566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(*pforest,ctx)); 3689566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm,*pforest)); 3690a96aa3bSJed Brown PetscFunctionReturn(0); 3700a96aa3bSJed Brown } 3710a96aa3bSJed Brown 3720a96aa3bSJed Brown #define DMForestDestroy_pforest _append_pforest(DMForestDestroy) 3730a96aa3bSJed Brown static PetscErrorCode DMForestDestroy_pforest(DM dm) 3740a96aa3bSJed Brown { 3750a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 3760a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 3770a96aa3bSJed Brown 3780a96aa3bSJed Brown PetscFunctionBegin; 3790a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3800a96aa3bSJed Brown if (pforest->lnodes) PetscStackCallP4est(p4est_lnodes_destroy,(pforest->lnodes)); 3810a96aa3bSJed Brown pforest->lnodes = NULL; 3820a96aa3bSJed Brown if (pforest->ghost) PetscStackCallP4est(p4est_ghost_destroy,(pforest->ghost)); 3830a96aa3bSJed Brown pforest->ghost = NULL; 3840a96aa3bSJed Brown if (pforest->forest) PetscStackCallP4est(p4est_destroy,(pforest->forest)); 3850a96aa3bSJed Brown pforest->forest = NULL; 3869566063dSJacob Faibussowitsch PetscCall(DMFTopologyDestroy_pforest(&pforest->topo)); 3879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_plex_pforest) "_C",NULL)); 3889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_pforest_plex) "_C",NULL)); 3892e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL)); 3909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",NULL)); 3912e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",NULL)); 3922e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",NULL)); 3939566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName)); 3949566063dSJacob Faibussowitsch PetscCall(DMDestroy(&pforest->plex)); 3959566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointAdaptToSelfSF)); 3969566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointSelfToAdaptSF)); 3979566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 3989566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 3999566063dSJacob Faibussowitsch PetscCall(PetscFree(forest->data)); 4000a96aa3bSJed Brown PetscFunctionReturn(0); 4010a96aa3bSJed Brown } 4020a96aa3bSJed Brown 4030a96aa3bSJed Brown #define DMForestTemplate_pforest _append_pforest(DMForestTemplate) 4040a96aa3bSJed Brown static PetscErrorCode DMForestTemplate_pforest(DM dm, DM tdm) 4050a96aa3bSJed Brown { 4060a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 4070a96aa3bSJed Brown DM_Forest_pforest *tpforest = (DM_Forest_pforest*) ((DM_Forest*) tdm->data)->data; 4080a96aa3bSJed Brown 4090a96aa3bSJed Brown PetscFunctionBegin; 4100a96aa3bSJed Brown if (pforest->topo) pforest->topo->refct++; 4119566063dSJacob Faibussowitsch PetscCall(DMFTopologyDestroy_pforest(&(tpforest->topo))); 4120a96aa3bSJed Brown tpforest->topo = pforest->topo; 4130a96aa3bSJed Brown PetscFunctionReturn(0); 4140a96aa3bSJed Brown } 4150a96aa3bSJed Brown 4160a96aa3bSJed Brown #define DMPlexCreateConnectivity_pforest _append_pforest(DMPlexCreateConnectivity) 4170a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM,p4est_connectivity_t**,PetscInt**); 4180a96aa3bSJed Brown 4190a96aa3bSJed Brown typedef struct _PforestAdaptCtx 4200a96aa3bSJed Brown { 4210a96aa3bSJed Brown PetscInt maxLevel; 4220a96aa3bSJed Brown PetscInt minLevel; 4230a96aa3bSJed Brown PetscInt currLevel; 4240a96aa3bSJed Brown PetscBool anyChange; 4250a96aa3bSJed Brown } 4260a96aa3bSJed Brown PforestAdaptCtx; 4270a96aa3bSJed Brown 4280a96aa3bSJed Brown static int pforest_coarsen_currlevel(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 4290a96aa3bSJed Brown { 4300a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 4310a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4320a96aa3bSJed Brown PetscInt currLevel = ctx->currLevel; 4330a96aa3bSJed Brown 4340a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4350a96aa3bSJed Brown return (int) ((PetscInt) quadrants[0]->level == currLevel); 4360a96aa3bSJed Brown } 4370a96aa3bSJed Brown 4380a96aa3bSJed Brown static int pforest_coarsen_uniform(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 4390a96aa3bSJed Brown { 4400a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 4410a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4420a96aa3bSJed Brown 4430a96aa3bSJed Brown return (int) ((PetscInt) quadrants[0]->level > minLevel); 4440a96aa3bSJed Brown } 4450a96aa3bSJed Brown 4460a96aa3bSJed Brown static int pforest_coarsen_flag_any(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 4470a96aa3bSJed Brown { 4480a96aa3bSJed Brown PetscInt i; 4490a96aa3bSJed Brown PetscBool any = PETSC_FALSE; 4500a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 4510a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4520a96aa3bSJed Brown 4530a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4540a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 4550a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_KEEP) { 4560a96aa3bSJed Brown any = PETSC_FALSE; 4570a96aa3bSJed Brown break; 4580a96aa3bSJed Brown } 4590a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_COARSEN) { 4600a96aa3bSJed Brown any = PETSC_TRUE; 4610a96aa3bSJed Brown break; 4620a96aa3bSJed Brown } 4630a96aa3bSJed Brown } 4640a96aa3bSJed Brown return any ? 1 : 0; 4650a96aa3bSJed Brown } 4660a96aa3bSJed Brown 4670a96aa3bSJed Brown static int pforest_coarsen_flag_all(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 4680a96aa3bSJed Brown { 4690a96aa3bSJed Brown PetscInt i; 4700a96aa3bSJed Brown PetscBool all = PETSC_TRUE; 4710a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 4720a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 4730a96aa3bSJed Brown 4740a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 4750a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 4760a96aa3bSJed Brown if (quadrants[i]->p.user_int != DM_ADAPT_COARSEN) { 4770a96aa3bSJed Brown all = PETSC_FALSE; 4780a96aa3bSJed Brown break; 4790a96aa3bSJed Brown } 4800a96aa3bSJed Brown } 4810a96aa3bSJed Brown return all ? 1 : 0; 4820a96aa3bSJed Brown } 4830a96aa3bSJed Brown 4840a96aa3bSJed Brown static void pforest_init_determine(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 4850a96aa3bSJed Brown { 4860a96aa3bSJed Brown quadrant->p.user_int = DM_ADAPT_DETERMINE; 4870a96aa3bSJed Brown } 4880a96aa3bSJed Brown 4890a96aa3bSJed Brown static int pforest_refine_uniform(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 4900a96aa3bSJed Brown { 4910a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 4920a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 4930a96aa3bSJed Brown 4940a96aa3bSJed Brown return ((PetscInt) quadrant->level < maxLevel); 4950a96aa3bSJed Brown } 4960a96aa3bSJed Brown 4970a96aa3bSJed Brown static int pforest_refine_flag(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 4980a96aa3bSJed Brown { 4990a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 5000a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 5010a96aa3bSJed Brown 5020a96aa3bSJed Brown if ((PetscInt) quadrant->level >= maxLevel) return 0; 5030a96aa3bSJed Brown 5040a96aa3bSJed Brown return (quadrant->p.user_int == DM_ADAPT_REFINE); 5050a96aa3bSJed Brown } 5060a96aa3bSJed Brown 5070a96aa3bSJed 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) 5080a96aa3bSJed Brown { 5090a96aa3bSJed Brown PetscMPIInt rank = p4estFrom->mpirank; 5100a96aa3bSJed Brown p4est_topidx_t t; 5110a96aa3bSJed Brown PetscInt toFineLeaves = 0, fromFineLeaves = 0; 5120a96aa3bSJed Brown 5130a96aa3bSJed Brown PetscFunctionBegin; 5140a96aa3bSJed Brown for (t = flt; t <= llt; t++) { /* count roots and leaves */ 5150a96aa3bSJed Brown p4est_tree_t *treeFrom = &(((p4est_tree_t*) p4estFrom->trees->array)[t]); 5160a96aa3bSJed Brown p4est_tree_t *treeTo = &(((p4est_tree_t*) p4estTo->trees->array)[t]); 5170a96aa3bSJed Brown p4est_quadrant_t *firstFrom = &treeFrom->first_desc; 5180a96aa3bSJed Brown p4est_quadrant_t *firstTo = &treeTo->first_desc; 5190a96aa3bSJed Brown PetscInt numFrom = (PetscInt) treeFrom->quadrants.elem_count; 5200a96aa3bSJed Brown PetscInt numTo = (PetscInt) treeTo->quadrants.elem_count; 5210a96aa3bSJed Brown p4est_quadrant_t *quadsFrom = (p4est_quadrant_t*) treeFrom->quadrants.array; 5220a96aa3bSJed Brown p4est_quadrant_t *quadsTo = (p4est_quadrant_t*) treeTo->quadrants.array; 5230a96aa3bSJed Brown PetscInt currentFrom, currentTo; 5240a96aa3bSJed Brown PetscInt treeOffsetFrom = (PetscInt) treeFrom->quadrants_offset; 5250a96aa3bSJed Brown PetscInt treeOffsetTo = (PetscInt) treeTo->quadrants_offset; 5260a96aa3bSJed Brown int comp; 5270a96aa3bSJed Brown 5280a96aa3bSJed Brown PetscStackCallP4estReturn(comp,p4est_quadrant_is_equal,(firstFrom,firstTo)); 52928b400f6SJacob Faibussowitsch PetscCheck(comp,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"non-matching partitions"); 5300a96aa3bSJed Brown 5310a96aa3bSJed Brown for (currentFrom = 0, currentTo = 0; currentFrom < numFrom && currentTo < numTo;) { 5320a96aa3bSJed Brown p4est_quadrant_t *quadFrom = &quadsFrom[currentFrom]; 5330a96aa3bSJed Brown p4est_quadrant_t *quadTo = &quadsTo[currentTo]; 5340a96aa3bSJed Brown 5350a96aa3bSJed Brown if (quadFrom->level == quadTo->level) { 5360a96aa3bSJed Brown if (toLeaves) { 5370a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5380a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5390a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5400a96aa3bSJed Brown } 5410a96aa3bSJed Brown toFineLeaves++; 5420a96aa3bSJed Brown currentFrom++; 5430a96aa3bSJed Brown currentTo++; 5440a96aa3bSJed Brown } else { 5450a96aa3bSJed Brown int fromIsAncestor; 5460a96aa3bSJed Brown 5470a96aa3bSJed Brown PetscStackCallP4estReturn(fromIsAncestor,p4est_quadrant_is_ancestor,(quadFrom,quadTo)); 5480a96aa3bSJed Brown if (fromIsAncestor) { 5490a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5500a96aa3bSJed Brown 5510a96aa3bSJed Brown if (toLeaves) { 5520a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 5530a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 5540a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 5550a96aa3bSJed Brown } 5560a96aa3bSJed Brown toFineLeaves++; 5570a96aa3bSJed Brown currentTo++; 5580a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_last_descendant,(quadFrom,&lastDesc,quadTo->level)); 5590a96aa3bSJed Brown PetscStackCallP4estReturn(comp,p4est_quadrant_is_equal,(quadTo,&lastDesc)); 5600a96aa3bSJed Brown if (comp) currentFrom++; 5610a96aa3bSJed Brown } else { 5620a96aa3bSJed Brown p4est_quadrant_t lastDesc; 5630a96aa3bSJed Brown 5640a96aa3bSJed Brown if (fromLeaves) { 5650a96aa3bSJed Brown fromLeaves[fromFineLeaves] = currentFrom + treeOffsetFrom + FromOffset; 5660a96aa3bSJed Brown toRoots[fromFineLeaves].rank = rank; 5670a96aa3bSJed Brown toRoots[fromFineLeaves].index = currentTo + treeOffsetTo + ToOffset; 5680a96aa3bSJed Brown } 5690a96aa3bSJed Brown fromFineLeaves++; 5700a96aa3bSJed Brown currentFrom++; 5710a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_last_descendant,(quadTo,&lastDesc,quadFrom->level)); 5720a96aa3bSJed Brown PetscStackCallP4estReturn(comp,p4est_quadrant_is_equal,(quadFrom,&lastDesc)); 5730a96aa3bSJed Brown if (comp) currentTo++; 5740a96aa3bSJed Brown } 5750a96aa3bSJed Brown } 5760a96aa3bSJed Brown } 5770a96aa3bSJed Brown } 5780a96aa3bSJed Brown *toFineLeavesCount = toFineLeaves; 5790a96aa3bSJed Brown *fromFineLeavesCount = fromFineLeaves; 5800a96aa3bSJed Brown PetscFunctionReturn(0); 5810a96aa3bSJed Brown } 5820a96aa3bSJed Brown 5830a96aa3bSJed Brown /* Compute the maximum level across all the trees */ 5840a96aa3bSJed Brown static PetscErrorCode DMPforestGetRefinementLevel(DM dm, PetscInt *lev) 5850a96aa3bSJed Brown { 5860a96aa3bSJed Brown p4est_topidx_t t, flt, llt; 5870a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 5880a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 5890a96aa3bSJed Brown PetscInt maxlevelloc = 0; 5900a96aa3bSJed Brown p4est_t *p4est; 5910a96aa3bSJed Brown 5920a96aa3bSJed Brown PetscFunctionBegin; 59328b400f6SJacob Faibussowitsch PetscCheck(pforest,PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Missing DM_Forest_pforest"); 59428b400f6SJacob Faibussowitsch PetscCheck(pforest->forest,PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Missing p4est_t"); 5950a96aa3bSJed Brown p4est = pforest->forest; 5960a96aa3bSJed Brown flt = p4est->first_local_tree; 5970a96aa3bSJed Brown llt = p4est->last_local_tree; 5980a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 5990a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4est->trees->array)[t]); 6000a96aa3bSJed Brown maxlevelloc = PetscMax((PetscInt)tree->maxlevel,maxlevelloc); 6010a96aa3bSJed Brown } 6021c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&maxlevelloc,lev,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm))); 6030a96aa3bSJed Brown PetscFunctionReturn(0); 6040a96aa3bSJed Brown } 6050a96aa3bSJed Brown 6060a96aa3bSJed Brown /* Puts identity in coarseToFine */ 6070a96aa3bSJed Brown /* assumes a matching partition */ 6080a96aa3bSJed Brown static PetscErrorCode DMPforestComputeLocalCellTransferSF(MPI_Comm comm, p4est_t *p4estFrom, PetscInt FromOffset, p4est_t *p4estTo, PetscInt ToOffset, PetscSF *fromCoarseToFine, PetscSF *toCoarseFromFine) 6090a96aa3bSJed Brown { 6100a96aa3bSJed Brown p4est_topidx_t flt, llt; 6110a96aa3bSJed Brown PetscSF fromCoarse, toCoarse; 6120a96aa3bSJed Brown PetscInt numRootsFrom, numRootsTo, numLeavesFrom, numLeavesTo; 6130a96aa3bSJed Brown PetscInt *fromLeaves = NULL, *toLeaves = NULL; 6140a96aa3bSJed Brown PetscSFNode *fromRoots = NULL, *toRoots = NULL; 6150a96aa3bSJed Brown 6160a96aa3bSJed Brown PetscFunctionBegin; 6170a96aa3bSJed Brown flt = p4estFrom->first_local_tree; 6180a96aa3bSJed Brown llt = p4estFrom->last_local_tree; 6199566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&fromCoarse)); 6200a96aa3bSJed Brown if (toCoarseFromFine) { 6219566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&toCoarse)); 6220a96aa3bSJed Brown } 6230a96aa3bSJed Brown numRootsFrom = p4estFrom->local_num_quadrants + FromOffset; 6240a96aa3bSJed Brown numRootsTo = p4estTo->local_num_quadrants + ToOffset; 6259566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom,FromOffset,p4estTo,ToOffset,flt,llt,&numLeavesTo,NULL,NULL,&numLeavesFrom,NULL,NULL)); 6269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo,&toLeaves)); 6279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo,&fromRoots)); 6280a96aa3bSJed Brown if (toCoarseFromFine) { 6299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom,&fromLeaves)); 6309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom,&fromRoots)); 6310a96aa3bSJed Brown } 6329566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom,FromOffset,p4estTo,ToOffset,flt,llt,&numLeavesTo,toLeaves,fromRoots,&numLeavesFrom,fromLeaves,toRoots)); 6330a96aa3bSJed Brown if (!ToOffset && (numLeavesTo == numRootsTo)) { /* compress */ 6349566063dSJacob Faibussowitsch PetscCall(PetscFree(toLeaves)); 6359566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(fromCoarse,numRootsFrom,numLeavesTo,NULL,PETSC_OWN_POINTER,fromRoots,PETSC_OWN_POINTER)); 6361baa6e33SBarry Smith } else PetscCall(PetscSFSetGraph(fromCoarse,numRootsFrom,numLeavesTo,toLeaves,PETSC_OWN_POINTER,fromRoots,PETSC_OWN_POINTER)); 6370a96aa3bSJed Brown *fromCoarseToFine = fromCoarse; 6380a96aa3bSJed Brown if (toCoarseFromFine) { 6399566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(toCoarse,numRootsTo,numLeavesFrom,fromLeaves,PETSC_OWN_POINTER,toRoots,PETSC_OWN_POINTER)); 6400a96aa3bSJed Brown *toCoarseFromFine = toCoarse; 6410a96aa3bSJed Brown } 6420a96aa3bSJed Brown PetscFunctionReturn(0); 6430a96aa3bSJed Brown } 6440a96aa3bSJed Brown 6450a96aa3bSJed Brown /* range of processes whose B sections overlap this ranks A section */ 6460a96aa3bSJed Brown static PetscErrorCode DMPforestComputeOverlappingRanks(PetscMPIInt size, PetscMPIInt rank, p4est_t *p4estA, p4est_t *p4estB, PetscInt *startB, PetscInt *endB) 6470a96aa3bSJed Brown { 6480a96aa3bSJed Brown p4est_quadrant_t * myCoarseStart = &(p4estA->global_first_position[rank]); 6490a96aa3bSJed Brown p4est_quadrant_t * myCoarseEnd = &(p4estA->global_first_position[rank+1]); 6500a96aa3bSJed Brown p4est_quadrant_t * globalFirstB = p4estB->global_first_position; 6510a96aa3bSJed Brown 6520a96aa3bSJed Brown PetscFunctionBegin; 6530a96aa3bSJed Brown *startB = -1; 6540a96aa3bSJed Brown *endB = -1; 6550a96aa3bSJed Brown if (p4estA->local_num_quadrants) { 6560a96aa3bSJed Brown PetscInt lo, hi, guess; 6570a96aa3bSJed Brown /* binary search to find interval containing myCoarseStart */ 6580a96aa3bSJed Brown lo = 0; 6590a96aa3bSJed Brown hi = size; 6600a96aa3bSJed Brown guess = rank; 6610a96aa3bSJed Brown while (1) { 6620a96aa3bSJed Brown int startCompMy, myCompEnd; 6630a96aa3bSJed Brown 6640a96aa3bSJed Brown PetscStackCallP4estReturn(startCompMy,p4est_quadrant_compare_piggy,(&globalFirstB[guess],myCoarseStart)); 6650a96aa3bSJed Brown PetscStackCallP4estReturn(myCompEnd,p4est_quadrant_compare_piggy,(myCoarseStart,&globalFirstB[guess+1])); 6660a96aa3bSJed Brown if (startCompMy <= 0 && myCompEnd < 0) { 6670a96aa3bSJed Brown *startB = guess; 6680a96aa3bSJed Brown break; 6690a96aa3bSJed Brown } else if (startCompMy > 0) { /* guess is to high */ 6700a96aa3bSJed Brown hi = guess; 6710a96aa3bSJed Brown } else { /* guess is to low */ 6720a96aa3bSJed Brown lo = guess + 1; 6730a96aa3bSJed Brown } 6740a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6750a96aa3bSJed Brown } 6760a96aa3bSJed Brown /* reset bounds, but not guess */ 6770a96aa3bSJed Brown lo = 0; 6780a96aa3bSJed Brown hi = size; 6790a96aa3bSJed Brown while (1) { 6800a96aa3bSJed Brown int startCompMy, myCompEnd; 6810a96aa3bSJed Brown 6820a96aa3bSJed Brown PetscStackCallP4estReturn(startCompMy,p4est_quadrant_compare_piggy,(&globalFirstB[guess],myCoarseEnd)); 6830a96aa3bSJed Brown PetscStackCallP4estReturn(myCompEnd,p4est_quadrant_compare_piggy,(myCoarseEnd,&globalFirstB[guess+1])); 6840a96aa3bSJed Brown if (startCompMy < 0 && myCompEnd <= 0) { /* notice that the comparison operators are different from above */ 6850a96aa3bSJed Brown *endB = guess + 1; 6860a96aa3bSJed Brown break; 6870a96aa3bSJed Brown } else if (startCompMy >= 0) { /* guess is to high */ 6880a96aa3bSJed Brown hi = guess; 6890a96aa3bSJed Brown } else { /* guess is to low */ 6900a96aa3bSJed Brown lo = guess + 1; 6910a96aa3bSJed Brown } 6920a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 6930a96aa3bSJed Brown } 6940a96aa3bSJed Brown } 6950a96aa3bSJed Brown PetscFunctionReturn(0); 6960a96aa3bSJed Brown } 6970a96aa3bSJed Brown 6980a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM,DM*); 6990a96aa3bSJed Brown 7000a96aa3bSJed Brown #define DMSetUp_pforest _append_pforest(DMSetUp) 7010a96aa3bSJed Brown static PetscErrorCode DMSetUp_pforest(DM dm) 7020a96aa3bSJed Brown { 7030a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 7040a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 7050a96aa3bSJed Brown DM base, adaptFrom; 7060a96aa3bSJed Brown DMForestTopology topoName; 7070a96aa3bSJed Brown PetscSF preCoarseToFine = NULL, coarseToPreFine = NULL; 7080a96aa3bSJed Brown PforestAdaptCtx ctx; 7090a96aa3bSJed Brown 7100a96aa3bSJed Brown PetscFunctionBegin; 7110a96aa3bSJed Brown ctx.minLevel = PETSC_MAX_INT; 7120a96aa3bSJed Brown ctx.maxLevel = 0; 7130a96aa3bSJed Brown ctx.currLevel = 0; 7140a96aa3bSJed Brown ctx.anyChange = PETSC_FALSE; 7150a96aa3bSJed Brown /* sanity check */ 7169566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm,&adaptFrom)); 7179566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 7189566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm,&topoName)); 7191dca8a05SBarry 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"); 7200a96aa3bSJed Brown 7210a96aa3bSJed Brown /* === Step 1: DMFTopology === */ 7220a96aa3bSJed Brown if (adaptFrom) { /* reference already created topology */ 7230a96aa3bSJed Brown PetscBool ispforest; 7240a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest*) adaptFrom->data; 7250a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest*) aforest->data; 7260a96aa3bSJed Brown 7279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)adaptFrom,DMPFOREST,&ispforest)); 72828b400f6SJacob Faibussowitsch PetscCheck(ispforest,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_NOTSAMETYPE,"Trying to adapt from %s, which is not %s",((PetscObject)adaptFrom)->type_name,DMPFOREST); 72928b400f6SJacob Faibussowitsch PetscCheck(apforest->topo,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"The pre-adaptation forest must have a topology"); 7309566063dSJacob Faibussowitsch PetscCall(DMSetUp(adaptFrom)); 7319566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 7329566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm,&topoName)); 7330a96aa3bSJed Brown } else if (base) { /* construct a connectivity from base */ 7340a96aa3bSJed Brown PetscBool isPlex, isDA; 7350a96aa3bSJed Brown 7369566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)base,&topoName)); 7379566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm,topoName)); 7389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base,DMPLEX,&isPlex)); 7399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base,DMDA,&isDA)); 7400a96aa3bSJed Brown if (isPlex) { 7410a96aa3bSJed Brown MPI_Comm comm = PetscObjectComm((PetscObject)dm); 7420a96aa3bSJed Brown PetscInt depth; 7430a96aa3bSJed Brown PetscMPIInt size; 7440a96aa3bSJed Brown p4est_connectivity_t *conn = NULL; 7450a96aa3bSJed Brown DMFTopology_pforest *topo; 7460a96aa3bSJed Brown PetscInt *tree_face_to_uniq = NULL; 7470a96aa3bSJed Brown 7489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(base,&depth)); 7490a96aa3bSJed Brown if (depth == 1) { 7500a96aa3bSJed Brown DM connDM; 7510a96aa3bSJed Brown 7529566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(base,&connDM)); 7530a96aa3bSJed Brown base = connDM; 7549566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm,base)); 7559566063dSJacob Faibussowitsch PetscCall(DMDestroy(&connDM)); 75663a3b9bcSJacob 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); 7579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 7580a96aa3bSJed Brown if (size > 1) { 7590a96aa3bSJed Brown DM dmRedundant; 7600a96aa3bSJed Brown PetscSF sf; 7610a96aa3bSJed Brown 7629566063dSJacob Faibussowitsch PetscCall(DMPlexGetRedundantDM(base,&sf,&dmRedundant)); 76328b400f6SJacob Faibussowitsch PetscCheck(dmRedundant,comm,PETSC_ERR_PLIB,"Could not create redundant DM"); 7649566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dmRedundant,"_base_migration_sf",(PetscObject)sf)); 7659566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 7660a96aa3bSJed Brown base = dmRedundant; 7679566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm,base)); 7689566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRedundant)); 7690a96aa3bSJed Brown } 7709566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(base,NULL,"-dm_p4est_base_view")); 7719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConnectivity_pforest(base,&conn,&tree_face_to_uniq)); 7729566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm,&topo)); 7730a96aa3bSJed Brown topo->refct = 1; 7740a96aa3bSJed Brown topo->conn = conn; 7750a96aa3bSJed Brown topo->geom = NULL; 7760a96aa3bSJed Brown { 7770a96aa3bSJed Brown PetscErrorCode (*map)(DM,PetscInt,PetscInt,const PetscReal[],PetscReal[],void*); 7780a96aa3bSJed Brown void *mapCtx; 7790a96aa3bSJed Brown 7809566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx)); 7810a96aa3bSJed Brown if (map) { 7820a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest; 7830a96aa3bSJed Brown p4est_geometry_t *geom; 7840a96aa3bSJed Brown 7859566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom_pforest)); 7869566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm,&geom_pforest->coordDim)); 7870a96aa3bSJed Brown geom_pforest->map = map; 7880a96aa3bSJed Brown geom_pforest->mapCtx = mapCtx; 7890a96aa3bSJed Brown PetscStackCallP4estReturn(geom_pforest->inner,p4est_geometry_new_connectivity,(conn)); 7909566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom)); 7910a96aa3bSJed Brown geom->name = topoName; 7920a96aa3bSJed Brown geom->user = geom_pforest; 7930a96aa3bSJed Brown geom->X = GeometryMapping_pforest; 7940a96aa3bSJed Brown geom->destroy = GeometryDestroy_pforest; 7950a96aa3bSJed Brown topo->geom = geom; 7960a96aa3bSJed Brown } 7970a96aa3bSJed Brown } 7980a96aa3bSJed Brown topo->tree_face_to_uniq = tree_face_to_uniq; 7990a96aa3bSJed Brown pforest->topo = topo; 80028b400f6SJacob Faibussowitsch } else PetscCheck(!isDA,PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Not implemented yet"); 8010a96aa3bSJed Brown #if 0 8020a96aa3bSJed Brown PetscInt N[3], P[3]; 8030a96aa3bSJed Brown 8040a96aa3bSJed Brown /* get the sizes, periodicities */ 8050a96aa3bSJed Brown /* ... */ 8060a96aa3bSJed Brown /* don't use Morton order */ 8079566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm,N,P,&pforest->topo,PETSC_FALSE)); 8080a96aa3bSJed Brown #endif 8090a96aa3bSJed Brown { 8100a96aa3bSJed Brown PetscInt numLabels, l; 8110a96aa3bSJed Brown 8129566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(base,&numLabels)); 8130a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 8140a96aa3bSJed Brown PetscBool isDepth, isGhost, isVTK, isDim, isCellType; 8150a96aa3bSJed Brown DMLabel label, labelNew; 8160a96aa3bSJed Brown PetscInt defVal; 8170a96aa3bSJed Brown const char *name; 8180a96aa3bSJed Brown 8199566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(base, l, &name)); 8209566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(base, l, &label)); 8219566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"depth",&isDepth)); 8220a96aa3bSJed Brown if (isDepth) continue; 8239566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"dim",&isDim)); 8240a96aa3bSJed Brown if (isDim) continue; 8259566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"celltype",&isCellType)); 8260a96aa3bSJed Brown if (isCellType) continue; 8279566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"ghost",&isGhost)); 8280a96aa3bSJed Brown if (isGhost) continue; 8299566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"vtk",&isVTK)); 8300a96aa3bSJed Brown if (isVTK) continue; 8319566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm,name)); 8329566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm,name,&labelNew)); 8339566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label,&defVal)); 8349566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew,defVal)); 8350a96aa3bSJed Brown } 8360a96aa3bSJed Brown /* map dm points (internal plex) to base 8370a96aa3bSJed Brown we currently create the subpoint_map for the entire hierarchy, starting from the finest forest 8380a96aa3bSJed Brown and propagating back to the coarsest 8390a96aa3bSJed Brown This is not an optimal approach, since we need the map only on the coarsest level 8400a96aa3bSJed Brown during DMForestTransferVecFromBase */ 8419566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&l)); 8420a96aa3bSJed Brown if (!l) { 8439566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm,"_forest_base_subpoint_map")); 8440a96aa3bSJed Brown } 8450a96aa3bSJed Brown } 8460a96aa3bSJed Brown } else { /* construct from topology name */ 8470a96aa3bSJed Brown DMFTopology_pforest *topo; 8480a96aa3bSJed Brown 8499566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreate_pforest(dm,topoName,&topo)); 8500a96aa3bSJed Brown pforest->topo = topo; 8510a96aa3bSJed Brown /* TODO: construct base? */ 8520a96aa3bSJed Brown } 8530a96aa3bSJed Brown 8540a96aa3bSJed Brown /* === Step 2: get the leaves of the forest === */ 8550a96aa3bSJed Brown if (adaptFrom) { /* start with the old forest */ 8560a96aa3bSJed Brown DMLabel adaptLabel; 8570a96aa3bSJed Brown PetscInt defaultValue; 8580a96aa3bSJed Brown PetscInt numValues, numValuesGlobal, cLocalStart, count; 8590a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest*) adaptFrom->data; 8600a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest*) aforest->data; 8610a96aa3bSJed Brown PetscBool computeAdaptSF; 8620a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 8630a96aa3bSJed Brown 8640a96aa3bSJed Brown flt = apforest->forest->first_local_tree; 8650a96aa3bSJed Brown llt = apforest->forest->last_local_tree; 8660a96aa3bSJed Brown cLocalStart = apforest->cLocalStart; 8679566063dSJacob Faibussowitsch PetscCall(DMForestGetComputeAdaptivitySF(dm,&computeAdaptSF)); 8680a96aa3bSJed Brown PetscStackCallP4estReturn(pforest->forest,p4est_copy,(apforest->forest, 0)); /* 0 indicates no data copying */ 8699566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm,&adaptLabel)); 8700a96aa3bSJed Brown if (adaptLabel) { 8710a96aa3bSJed Brown /* apply the refinement/coarsening by flags, plus minimum/maximum refinement */ 8729566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(adaptLabel,&numValues)); 8739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&numValues,&numValuesGlobal,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)adaptFrom))); 8749566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(adaptLabel,&defaultValue)); 8750a96aa3bSJed Brown if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN_LAST) { /* uniform coarsen of the last level only (equivalent to DM_ADAPT_COARSEN for conforming grids) */ 8769566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&ctx.minLevel)); 8779566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm,&ctx.currLevel)); 8780a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 8790a96aa3bSJed Brown PetscStackCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_currlevel,NULL)); 8800a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 8810a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 8820a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 8830a96aa3bSJed Brown if (computeAdaptSF) { 8849566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),pforest->forest,0,apforest->forest,apforest->cLocalStart,&coarseToPreFine,NULL)); 8850a96aa3bSJed Brown } 8860a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN) { /* uniform coarsen */ 8879566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&ctx.minLevel)); 8880a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 8890a96aa3bSJed Brown PetscStackCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_uniform,NULL)); 8900a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 8910a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 8920a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 8930a96aa3bSJed Brown if (computeAdaptSF) { 8949566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),pforest->forest,0,apforest->forest,apforest->cLocalStart,&coarseToPreFine,NULL)); 8950a96aa3bSJed Brown } 8960a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_REFINE) { /* uniform refine */ 8979566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm,&ctx.maxLevel)); 8980a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 8990a96aa3bSJed Brown PetscStackCallP4est(p4est_refine,(pforest->forest,0,pforest_refine_uniform,NULL)); 9000a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 9010a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 9020a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 9030a96aa3bSJed Brown if (computeAdaptSF) { 9049566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),apforest->forest,apforest->cLocalStart,pforest->forest,0,&preCoarseToFine,NULL)); 9050a96aa3bSJed Brown } 9060a96aa3bSJed Brown } else if (numValuesGlobal) { 9070a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 9080a96aa3bSJed Brown PetscInt *cellFlags; 9090a96aa3bSJed Brown DMForestAdaptivityStrategy strategy; 9100a96aa3bSJed Brown PetscSF cellSF; 9110a96aa3bSJed Brown PetscInt c, cStart, cEnd; 9120a96aa3bSJed Brown PetscBool adaptAny; 9130a96aa3bSJed Brown 9149566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm,&ctx.maxLevel)); 9159566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&ctx.minLevel)); 9169566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityStrategy(dm,&strategy)); 9179566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(strategy,"any",3,&adaptAny)); 9189566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(adaptFrom,&cStart,&cEnd)); 9199566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(adaptFrom,&cellSF)); 9209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd-cStart,&cellFlags)); 9219566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; c++) PetscCall(DMLabelGetValue(adaptLabel,c,&cellFlags[c-cStart])); 9220a96aa3bSJed Brown if (cellSF) { 9230a96aa3bSJed Brown if (adaptAny) { 9249566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MAX)); 9259566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MAX)); 9260a96aa3bSJed Brown } else { 9279566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MIN)); 9289566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MIN)); 9290a96aa3bSJed Brown } 9300a96aa3bSJed Brown } 9310a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9320a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4est->trees->array)[t]); 9330a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count, i; 9340a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 9350a96aa3bSJed Brown 9360a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9370a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9380a96aa3bSJed Brown q->p.user_int = cellFlags[count++]; 9390a96aa3bSJed Brown } 9400a96aa3bSJed Brown } 9419566063dSJacob Faibussowitsch PetscCall(PetscFree(cellFlags)); 9420a96aa3bSJed Brown 9430a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 9441baa6e33SBarry Smith if (adaptAny) PetscStackCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_flag_any,pforest_init_determine)); 9451baa6e33SBarry Smith else PetscStackCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_flag_all,pforest_init_determine)); 9460a96aa3bSJed Brown PetscStackCallP4est(p4est_refine,(pforest->forest,0,pforest_refine_flag,NULL)); 9470a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 9480a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 9490a96aa3bSJed Brown if (computeAdaptSF) { 9509566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),apforest->forest,apforest->cLocalStart,pforest->forest,0,&preCoarseToFine,&coarseToPreFine)); 9510a96aa3bSJed Brown } 9520a96aa3bSJed Brown } 9530a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 9540a96aa3bSJed Brown p4est_tree_t *atree = &(((p4est_tree_t*) apforest->forest->trees->array)[t]); 9550a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) pforest->forest->trees->array)[t]); 9560a96aa3bSJed Brown PetscInt anumQuads = (PetscInt) atree->quadrants.elem_count, i; 9570a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 9580a96aa3bSJed Brown p4est_quadrant_t *aquads = (p4est_quadrant_t *) atree->quadrants.array; 9590a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 9600a96aa3bSJed Brown 9610a96aa3bSJed Brown if (anumQuads != numQuads) { 9620a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9630a96aa3bSJed Brown } else { 9640a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 9650a96aa3bSJed Brown p4est_quadrant_t *aq = &aquads[i]; 9660a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 9670a96aa3bSJed Brown 9680a96aa3bSJed Brown if (aq->level != q->level) { 9690a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 9700a96aa3bSJed Brown break; 9710a96aa3bSJed Brown } 9720a96aa3bSJed Brown } 9730a96aa3bSJed Brown } 9740a96aa3bSJed Brown if (ctx.anyChange) { 9750a96aa3bSJed Brown break; 9760a96aa3bSJed Brown } 9770a96aa3bSJed Brown } 9780a96aa3bSJed Brown } 9790a96aa3bSJed Brown { 9800a96aa3bSJed Brown PetscInt numLabels, l; 9810a96aa3bSJed Brown 9829566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(adaptFrom,&numLabels)); 9830a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 9840a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 9850a96aa3bSJed Brown DMLabel label, labelNew; 9860a96aa3bSJed Brown PetscInt defVal; 9870a96aa3bSJed Brown const char *name; 9880a96aa3bSJed Brown 9899566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(adaptFrom, l, &name)); 9909566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(adaptFrom, l, &label)); 9919566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"depth",&isDepth)); 9920a96aa3bSJed Brown if (isDepth) continue; 9939566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"celltype",&isCellType)); 9940a96aa3bSJed Brown if (isCellType) continue; 9959566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"ghost",&isGhost)); 9960a96aa3bSJed Brown if (isGhost) continue; 9979566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"vtk",&isVTK)); 9980a96aa3bSJed Brown if (isVTK) continue; 9999566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm,name)); 10009566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm,name,&labelNew)); 10019566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label,&defVal)); 10029566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew,defVal)); 10030a96aa3bSJed Brown } 10040a96aa3bSJed Brown } 10050a96aa3bSJed Brown } else { /* initial */ 10060a96aa3bSJed Brown PetscInt initLevel, minLevel; 10070a96aa3bSJed Brown 10089566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm,&initLevel)); 10099566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&minLevel)); 10100a96aa3bSJed Brown PetscStackCallP4estReturn(pforest->forest,p4est_new_ext,(PetscObjectComm((PetscObject)dm),pforest->topo->conn, 10110a96aa3bSJed Brown 0, /* minimum number of quadrants per processor */ 10120a96aa3bSJed Brown initLevel, /* level of refinement */ 10130a96aa3bSJed Brown 1, /* uniform refinement */ 10140a96aa3bSJed Brown 0, /* we don't allocate any per quadrant data */ 10150a96aa3bSJed Brown NULL, /* there is no special quadrant initialization */ 10160a96aa3bSJed Brown (void*)dm)); /* this dm is the user context */ 10170a96aa3bSJed Brown 10180a96aa3bSJed Brown if (initLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 10190a96aa3bSJed Brown if (dm->setfromoptionscalled) { 10200a96aa3bSJed Brown PetscBool flgPattern, flgFractal; 10210a96aa3bSJed Brown PetscInt corner = 0; 10220a96aa3bSJed Brown PetscInt corners[P4EST_CHILDREN], ncorner = P4EST_CHILDREN; 10230a96aa3bSJed Brown PetscReal likelihood = 1./ P4EST_DIM; 10240a96aa3bSJed Brown PetscInt pattern; 10250a96aa3bSJed Brown const char *prefix; 10260a96aa3bSJed Brown 10279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix)); 10289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEList(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_pattern",DMRefinePatternName,PATTERN_COUNT,&pattern,&flgPattern)); 10299566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_corner",&corner,NULL)); 10309566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_fractal_corners",corners,&ncorner,&flgFractal)); 10319566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_hash_likelihood",&likelihood,NULL)); 10320a96aa3bSJed Brown 10330a96aa3bSJed Brown if (flgPattern) { 10340a96aa3bSJed Brown DMRefinePatternCtx *ctx; 10350a96aa3bSJed Brown PetscInt maxLevel; 10360a96aa3bSJed Brown 10379566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm,&maxLevel)); 10389566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm,&ctx)); 10390a96aa3bSJed Brown ctx->maxLevel = PetscMin(maxLevel,P4EST_QMAXLEVEL); 10400a96aa3bSJed Brown if (initLevel + ctx->maxLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 10410a96aa3bSJed Brown switch (pattern) { 10420a96aa3bSJed Brown case PATTERN_HASH: 10430a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Hash; 10440a96aa3bSJed Brown ctx->hashLikelihood = likelihood; 10450a96aa3bSJed Brown break; 10460a96aa3bSJed Brown case PATTERN_CORNER: 10470a96aa3bSJed Brown ctx->corner = corner; 10480a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Corner; 10490a96aa3bSJed Brown break; 10500a96aa3bSJed Brown case PATTERN_CENTER: 10510a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Center; 10520a96aa3bSJed Brown break; 10530a96aa3bSJed Brown case PATTERN_FRACTAL: 10540a96aa3bSJed Brown if (flgFractal) { 10550a96aa3bSJed Brown PetscInt i; 10560a96aa3bSJed Brown 10570a96aa3bSJed Brown for (i = 0; i < ncorner; i++) ctx->fractal[corners[i]] = PETSC_TRUE; 10580a96aa3bSJed Brown } else { 10590a96aa3bSJed Brown #if !defined(P4_TO_P8) 10600a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[1] = ctx->fractal[2] = PETSC_TRUE; 10610a96aa3bSJed Brown #else 10620a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[3] = ctx->fractal[5] = ctx->fractal[6] = PETSC_TRUE; 10630a96aa3bSJed Brown #endif 10640a96aa3bSJed Brown } 10650a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Fractal; 10660a96aa3bSJed Brown break; 10670a96aa3bSJed Brown default: 10680a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Not a valid refinement pattern"); 10690a96aa3bSJed Brown } 10700a96aa3bSJed Brown 10710a96aa3bSJed Brown pforest->forest->user_pointer = (void*) ctx; 10720a96aa3bSJed Brown PetscStackCallP4est(p4est_refine,(pforest->forest,1,ctx->refine_fn,NULL)); 10730a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 10749566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 10750a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 10760a96aa3bSJed Brown } 10770a96aa3bSJed Brown } 10780a96aa3bSJed Brown } 10790a96aa3bSJed Brown if (pforest->coarsen_hierarchy) { 10800a96aa3bSJed Brown PetscInt initLevel, currLevel, minLevel; 10810a96aa3bSJed Brown 10829566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm,&currLevel)); 10839566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm,&initLevel)); 10849566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&minLevel)); 10850a96aa3bSJed Brown if (currLevel > minLevel) { 10860a96aa3bSJed Brown DM_Forest_pforest *coarse_pforest; 10870a96aa3bSJed Brown DMLabel coarsen; 10880a96aa3bSJed Brown DM coarseDM; 10890a96aa3bSJed Brown 10909566063dSJacob Faibussowitsch PetscCall(DMForestTemplate(dm,MPI_COMM_NULL,&coarseDM)); 10919566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityPurpose(coarseDM,DM_ADAPT_COARSEN)); 10929566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "coarsen",&coarsen)); 10939566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(coarsen,DM_ADAPT_COARSEN)); 10949566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityLabel(coarseDM,coarsen)); 10959566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&coarsen)); 10969566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm,coarseDM)); 10979566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 10980a96aa3bSJed Brown initLevel = currLevel == initLevel ? initLevel - 1 : initLevel; 10999566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(coarseDM,initLevel)); 11009566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(coarseDM,minLevel)); 11010a96aa3bSJed Brown coarse_pforest = (DM_Forest_pforest*) ((DM_Forest*) coarseDM->data)->data; 11020a96aa3bSJed Brown coarse_pforest->coarsen_hierarchy = PETSC_TRUE; 11030a96aa3bSJed Brown } 11040a96aa3bSJed Brown } 11050a96aa3bSJed Brown 11060a96aa3bSJed Brown { /* repartitioning and overlap */ 11070a96aa3bSJed Brown PetscMPIInt size, rank; 11080a96aa3bSJed Brown 11099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size)); 11109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank)); 11110a96aa3bSJed Brown if ((size > 1) && (pforest->partition_for_coarsening || forest->cellWeights || forest->weightCapacity != 1. || forest->weightsFactor != 1.)) { 11120a96aa3bSJed Brown PetscBool copyForest = PETSC_FALSE; 11130a96aa3bSJed Brown p4est_t *forest_copy = NULL; 11140a96aa3bSJed Brown p4est_gloidx_t shipped = 0; 11150a96aa3bSJed Brown 11160a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) copyForest = PETSC_TRUE; 11170a96aa3bSJed Brown if (copyForest) PetscStackCallP4estReturn(forest_copy,p4est_copy,(pforest->forest,0)); 11180a96aa3bSJed Brown 11190a96aa3bSJed Brown if (!forest->cellWeights && forest->weightCapacity == 1. && forest->weightsFactor == 1.) { 11200a96aa3bSJed Brown PetscStackCallP4estReturn(shipped,p4est_partition_ext,(pforest->forest,(int)pforest->partition_for_coarsening,NULL)); 11210a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Non-uniform partition cases not implemented yet"); 11220a96aa3bSJed Brown if (shipped) ctx.anyChange = PETSC_TRUE; 11230a96aa3bSJed Brown if (forest_copy) { 11240a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 11250a96aa3bSJed Brown PetscSF repartSF; /* repartSF has roots in the old partition */ 11260a96aa3bSJed Brown PetscInt pStart = -1, pEnd = -1, p; 11270a96aa3bSJed Brown PetscInt numRoots, numLeaves; 11280a96aa3bSJed Brown PetscSFNode *repartRoots; 11290a96aa3bSJed Brown p4est_gloidx_t postStart = pforest->forest->global_first_quadrant[rank]; 11300a96aa3bSJed Brown p4est_gloidx_t postEnd = pforest->forest->global_first_quadrant[rank+1]; 11310a96aa3bSJed Brown p4est_gloidx_t partOffset = postStart; 11320a96aa3bSJed Brown 11330a96aa3bSJed Brown numRoots = (PetscInt) (forest_copy->global_first_quadrant[rank + 1] - forest_copy->global_first_quadrant[rank]); 11340a96aa3bSJed Brown numLeaves = (PetscInt) (postEnd - postStart); 11359566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(size,rank,pforest->forest,forest_copy,&pStart,&pEnd)); 11369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((PetscInt) pforest->forest->local_num_quadrants,&repartRoots)); 11370a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 11380a96aa3bSJed Brown p4est_gloidx_t preStart = forest_copy->global_first_quadrant[p]; 11390a96aa3bSJed Brown p4est_gloidx_t preEnd = forest_copy->global_first_quadrant[p+1]; 11400a96aa3bSJed Brown PetscInt q; 11410a96aa3bSJed Brown 11420a96aa3bSJed Brown if (preEnd == preStart) continue; 114308401ef6SPierre Jolivet PetscCheck(preStart <= postStart,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Bad partition overlap computation"); 11440a96aa3bSJed Brown preEnd = preEnd > postEnd ? postEnd : preEnd; 11450a96aa3bSJed Brown for (q = partOffset; q < preEnd; q++) { 11460a96aa3bSJed Brown repartRoots[q - postStart].rank = p; 11470a96aa3bSJed Brown repartRoots[q - postStart].index = partOffset - preStart; 11480a96aa3bSJed Brown } 11490a96aa3bSJed Brown partOffset = preEnd; 11500a96aa3bSJed Brown } 11519566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&repartSF)); 11529566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(repartSF,numRoots,numLeaves,NULL,PETSC_OWN_POINTER,repartRoots,PETSC_OWN_POINTER)); 11539566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(repartSF)); 11540a96aa3bSJed Brown if (preCoarseToFine) { 11550a96aa3bSJed Brown PetscSF repartSFembed, preCoarseToFineNew; 11560a96aa3bSJed Brown PetscInt nleaves; 11570a96aa3bSJed Brown const PetscInt *leaves; 11580a96aa3bSJed Brown 11599566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 11609566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine,NULL,&nleaves,&leaves,NULL)); 11610a96aa3bSJed Brown if (leaves) { 11629566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(repartSF,nleaves,leaves,&repartSFembed)); 11630a96aa3bSJed Brown } else { 11640a96aa3bSJed Brown repartSFembed = repartSF; 11659566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)repartSFembed)); 11660a96aa3bSJed Brown } 11679566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(preCoarseToFine,repartSFembed,&preCoarseToFineNew)); 11689566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 11699566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFembed)); 11700a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 11710a96aa3bSJed Brown } 11720a96aa3bSJed Brown if (coarseToPreFine) { 11730a96aa3bSJed Brown PetscSF repartSFinv, coarseToPreFineNew; 11740a96aa3bSJed Brown 11759566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(repartSF,&repartSFinv)); 11769566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(repartSFinv,coarseToPreFine,&coarseToPreFineNew)); 11779566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 11789566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFinv)); 11790a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 11800a96aa3bSJed Brown } 11819566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSF)); 11820a96aa3bSJed Brown } 11830a96aa3bSJed Brown PetscStackCallP4est(p4est_destroy,(forest_copy)); 11840a96aa3bSJed Brown } 11850a96aa3bSJed Brown } 11860a96aa3bSJed Brown if (size > 1) { 11870a96aa3bSJed Brown PetscInt overlap; 11880a96aa3bSJed Brown 11899566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm,&overlap)); 11900a96aa3bSJed Brown 11910a96aa3bSJed Brown if (adaptFrom) { 11920a96aa3bSJed Brown PetscInt aoverlap; 11930a96aa3bSJed Brown 11949566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(adaptFrom,&aoverlap)); 11950a96aa3bSJed Brown if (aoverlap != overlap) { 11960a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 11970a96aa3bSJed Brown } 11980a96aa3bSJed Brown } 11990a96aa3bSJed Brown 12000a96aa3bSJed Brown if (overlap > 0) { 12010a96aa3bSJed Brown PetscInt i, cLocalStart; 12020a96aa3bSJed Brown PetscInt cEnd; 12030a96aa3bSJed Brown PetscSF preCellSF = NULL, cellSF = NULL; 12040a96aa3bSJed Brown 12050a96aa3bSJed Brown PetscStackCallP4estReturn(pforest->ghost,p4est_ghost_new,(pforest->forest,P4EST_CONNECT_FULL)); 12060a96aa3bSJed Brown PetscStackCallP4estReturn(pforest->lnodes,p4est_lnodes_new,(pforest->forest,pforest->ghost,-P4EST_DIM)); 12070a96aa3bSJed Brown PetscStackCallP4est(p4est_ghost_support_lnodes,(pforest->forest,pforest->lnodes,pforest->ghost)); 12080a96aa3bSJed Brown for (i = 1; i < overlap; i++) PetscStackCallP4est(p4est_ghost_expand_by_lnodes,(pforest->forest,pforest->lnodes,pforest->ghost)); 12090a96aa3bSJed Brown 12100a96aa3bSJed Brown cLocalStart = pforest->cLocalStart = pforest->ghost->proc_offsets[rank]; 12110a96aa3bSJed Brown cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[size]; 12120a96aa3bSJed Brown 12130a96aa3bSJed Brown /* shift sfs by cLocalStart, expand by cell SFs */ 12140a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 12159566063dSJacob Faibussowitsch if (adaptFrom) PetscCall(DMForestGetCellSF(adaptFrom,&preCellSF)); 12160a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 12179566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(dm,&cellSF)); 12180a96aa3bSJed Brown } 12190a96aa3bSJed Brown if (preCoarseToFine) { 12200a96aa3bSJed Brown PetscSF preCoarseToFineNew; 12210a96aa3bSJed Brown PetscInt nleaves, nroots, *leavesNew, i, nleavesNew; 12220a96aa3bSJed Brown const PetscInt *leaves; 12230a96aa3bSJed Brown const PetscSFNode *remotes; 12240a96aa3bSJed Brown PetscSFNode *remotesAll; 12250a96aa3bSJed Brown 12269566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine)); 12279566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine,&nroots,&nleaves,&leaves,&remotes)); 12289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd,&remotesAll)); 12290a96aa3bSJed Brown for (i = 0; i < cEnd; i++) { 12300a96aa3bSJed Brown remotesAll[i].rank = -1; 12310a96aa3bSJed Brown remotesAll[i].index = -1; 12320a96aa3bSJed Brown } 12330a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesAll[(leaves ? leaves[i] : i) + cLocalStart] = remotes[i]; 12349566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(cellSF)); 12359566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(cellSF,MPIU_2INT,remotesAll,remotesAll,MPI_REPLACE)); 12369566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(cellSF,MPIU_2INT,remotesAll,remotesAll,MPI_REPLACE)); 12370a96aa3bSJed Brown nleavesNew = 0; 12380a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12390a96aa3bSJed Brown if (remotesAll[i].rank >= 0) nleavesNew++; 12400a96aa3bSJed Brown } 12419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesNew,&leavesNew)); 12420a96aa3bSJed Brown nleavesNew = 0; 12430a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 12440a96aa3bSJed Brown if (remotesAll[i].rank >= 0) { 12450a96aa3bSJed Brown leavesNew[nleavesNew] = i; 12460a96aa3bSJed Brown if (i > nleavesNew) remotesAll[nleavesNew] = remotesAll[i]; 12470a96aa3bSJed Brown nleavesNew++; 12480a96aa3bSJed Brown } 12490a96aa3bSJed Brown } 12509566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&preCoarseToFineNew)); 12510a96aa3bSJed Brown if (nleavesNew < cEnd) { 12529566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew,nroots,nleavesNew,leavesNew,PETSC_OWN_POINTER,remotesAll,PETSC_COPY_VALUES)); 12530a96aa3bSJed Brown } else { /* all cells are leaves */ 12549566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 12559566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew,nroots,nleavesNew,NULL,PETSC_OWN_POINTER,remotesAll,PETSC_COPY_VALUES)); 12560a96aa3bSJed Brown } 12579566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesAll)); 12589566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine)); 12590a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12600a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 12610a96aa3bSJed Brown } 12620a96aa3bSJed Brown if (coarseToPreFine) { 12630a96aa3bSJed Brown PetscSF coarseToPreFineNew; 12640a96aa3bSJed Brown PetscInt nleaves, nroots, i, nleavesCellSF, nleavesExpanded, *leavesNew; 12650a96aa3bSJed Brown const PetscInt *leaves; 12660a96aa3bSJed Brown const PetscSFNode *remotes; 12670a96aa3bSJed Brown PetscSFNode *remotesNew, *remotesNewRoot, *remotesExpanded; 12680a96aa3bSJed Brown 12699566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(coarseToPreFine)); 12709566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToPreFine,&nroots,&nleaves,&leaves,&remotes)); 12719566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCellSF,NULL,&nleavesCellSF,NULL,NULL)); 12729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots,&remotesNewRoot)); 12739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves,&remotesNew)); 12740a96aa3bSJed Brown for (i = 0; i < nroots; i++) { 12750a96aa3bSJed Brown remotesNewRoot[i].rank = rank; 12760a96aa3bSJed Brown remotesNewRoot[i].index = i + cLocalStart; 12770a96aa3bSJed Brown } 12789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToPreFine,MPIU_2INT,remotesNewRoot,remotesNew,MPI_REPLACE)); 12799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToPreFine,MPIU_2INT,remotesNewRoot,remotesNew,MPI_REPLACE)); 12809566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNewRoot)); 12819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesCellSF,&remotesExpanded)); 12820a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12830a96aa3bSJed Brown remotesExpanded[i].rank = -1; 12840a96aa3bSJed Brown remotesExpanded[i].index = -1; 12850a96aa3bSJed Brown } 12860a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesExpanded[leaves ? leaves[i] : i] = remotesNew[i]; 12879566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNew)); 12889566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(preCellSF,MPIU_2INT,remotesExpanded,remotesExpanded,MPI_REPLACE)); 12899566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(preCellSF,MPIU_2INT,remotesExpanded,remotesExpanded,MPI_REPLACE)); 12900a96aa3bSJed Brown 12910a96aa3bSJed Brown nleavesExpanded = 0; 12920a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12930a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) nleavesExpanded++; 12940a96aa3bSJed Brown } 12959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesExpanded,&leavesNew)); 12960a96aa3bSJed Brown nleavesExpanded = 0; 12970a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 12980a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) { 12990a96aa3bSJed Brown leavesNew[nleavesExpanded] = i; 13000a96aa3bSJed Brown if (i > nleavesExpanded) remotesExpanded[nleavesExpanded] = remotes[i]; 13010a96aa3bSJed Brown nleavesExpanded++; 13020a96aa3bSJed Brown } 13030a96aa3bSJed Brown } 13049566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&coarseToPreFineNew)); 13050a96aa3bSJed Brown if (nleavesExpanded < nleavesCellSF) { 13069566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew,cEnd,nleavesExpanded,leavesNew,PETSC_OWN_POINTER,remotesExpanded,PETSC_COPY_VALUES)); 13070a96aa3bSJed Brown } else { 13089566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew)); 13099566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew,cEnd,nleavesExpanded,NULL,PETSC_OWN_POINTER,remotesExpanded,PETSC_COPY_VALUES)); 13100a96aa3bSJed Brown } 13119566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesExpanded)); 13129566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine)); 13130a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 13140a96aa3bSJed Brown } 13150a96aa3bSJed Brown } 13160a96aa3bSJed Brown } 13170a96aa3bSJed Brown } 13180a96aa3bSJed Brown forest->preCoarseToFine = preCoarseToFine; 13190a96aa3bSJed Brown forest->coarseToPreFine = coarseToPreFine; 13200a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 13219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&ctx.anyChange,&(pforest->adaptivitySuccess),1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm))); 13229566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,NULL)); 13230a96aa3bSJed Brown PetscFunctionReturn(0); 13240a96aa3bSJed Brown } 13250a96aa3bSJed Brown 13260a96aa3bSJed Brown #define DMForestGetAdaptivitySuccess_pforest _append_pforest(DMForestGetAdaptivitySuccess) 13270a96aa3bSJed Brown static PetscErrorCode DMForestGetAdaptivitySuccess_pforest(DM dm, PetscBool *success) 13280a96aa3bSJed Brown { 13290a96aa3bSJed Brown DM_Forest *forest; 13300a96aa3bSJed Brown DM_Forest_pforest *pforest; 13310a96aa3bSJed Brown 13320a96aa3bSJed Brown PetscFunctionBegin; 13330a96aa3bSJed Brown forest = (DM_Forest *) dm->data; 13340a96aa3bSJed Brown pforest = (DM_Forest_pforest *) forest->data; 13350a96aa3bSJed Brown *success = pforest->adaptivitySuccess; 13360a96aa3bSJed Brown PetscFunctionReturn(0); 13370a96aa3bSJed Brown } 13380a96aa3bSJed Brown 13390a96aa3bSJed Brown #define DMView_ASCII_pforest _append_pforest(DMView_ASCII) 13400a96aa3bSJed Brown static PetscErrorCode DMView_ASCII_pforest(PetscObject odm, PetscViewer viewer) 13410a96aa3bSJed Brown { 13420a96aa3bSJed Brown DM dm = (DM) odm; 13430a96aa3bSJed Brown 13440a96aa3bSJed Brown PetscFunctionBegin; 13450a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13460a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13479566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13480a96aa3bSJed Brown switch (viewer->format) { 13490a96aa3bSJed Brown case PETSC_VIEWER_DEFAULT: 13500a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO: 13510a96aa3bSJed Brown { 13520a96aa3bSJed Brown PetscInt dim; 13530a96aa3bSJed Brown const char *name; 13540a96aa3bSJed Brown 13559566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) dm, &name)); 13569566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 135763a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "Forest %s in %" PetscInt_FMT " dimensions:\n", name, dim)); 135863a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Forest in %" PetscInt_FMT " dimensions:\n", dim)); 13590a96aa3bSJed Brown } 13600a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO_DETAIL: 13610a96aa3bSJed Brown case PETSC_VIEWER_LOAD_BALANCE: 13620a96aa3bSJed Brown { 13630a96aa3bSJed Brown DM plex; 13640a96aa3bSJed Brown 13659566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 13669566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 13670a96aa3bSJed Brown } 13680a96aa3bSJed Brown break; 136998921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 13700a96aa3bSJed Brown } 13710a96aa3bSJed Brown PetscFunctionReturn(0); 13720a96aa3bSJed Brown } 13730a96aa3bSJed Brown 13740a96aa3bSJed Brown #define DMView_VTK_pforest _append_pforest(DMView_VTK) 13750a96aa3bSJed Brown static PetscErrorCode DMView_VTK_pforest(PetscObject odm, PetscViewer viewer) 13760a96aa3bSJed Brown { 13770a96aa3bSJed Brown DM dm = (DM) odm; 13780a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 13790a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 13800a96aa3bSJed Brown PetscBool isvtk; 13810a96aa3bSJed Brown PetscReal vtkScale = 1. - PETSC_MACHINE_EPSILON; 13820a96aa3bSJed Brown PetscViewer_VTK *vtk = (PetscViewer_VTK*)viewer->data; 13830a96aa3bSJed Brown const char *name; 13840a96aa3bSJed Brown char *filenameStrip = NULL; 13850a96aa3bSJed Brown PetscBool hasExt; 13860a96aa3bSJed Brown size_t len; 13870a96aa3bSJed Brown p4est_geometry_t *geom; 13880a96aa3bSJed Brown 13890a96aa3bSJed Brown PetscFunctionBegin; 13900a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13910a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13929566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 13930a96aa3bSJed Brown geom = pforest->topo->geom; 13949566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 139528b400f6SJacob Faibussowitsch PetscCheck(isvtk,PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name); 13960a96aa3bSJed Brown switch (viewer->format) { 13970a96aa3bSJed Brown case PETSC_VIEWER_VTK_VTU: 139828b400f6SJacob Faibussowitsch PetscCheck(pforest->forest,PetscObjectComm(odm),PETSC_ERR_ARG_WRONG,"DM has not been setup with a valid forest"); 13990a96aa3bSJed Brown name = vtk->filename; 14009566063dSJacob Faibussowitsch PetscCall(PetscStrlen(name,&len)); 14019566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(name+len-4,".vtu",&hasExt)); 14020a96aa3bSJed Brown if (hasExt) { 14039566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name,&filenameStrip)); 14040a96aa3bSJed Brown filenameStrip[len-4]='\0'; 14050a96aa3bSJed Brown name = filenameStrip; 14060a96aa3bSJed Brown } 14070a96aa3bSJed Brown if (!pforest->topo->geom) PetscStackCallP4estReturn(geom,p4est_geometry_new_connectivity,(pforest->topo->conn)); 14080a96aa3bSJed Brown { 14090a96aa3bSJed Brown p4est_vtk_context_t *pvtk; 14100a96aa3bSJed Brown int footerr; 14110a96aa3bSJed Brown 14120a96aa3bSJed Brown PetscStackCallP4estReturn(pvtk,p4est_vtk_context_new,(pforest->forest,name)); 14130a96aa3bSJed Brown PetscStackCallP4est(p4est_vtk_context_set_geom,(pvtk,geom)); 14140a96aa3bSJed Brown PetscStackCallP4est(p4est_vtk_context_set_scale,(pvtk,(double)vtkScale)); 14150a96aa3bSJed Brown PetscStackCallP4estReturn(pvtk,p4est_vtk_write_header,(pvtk)); 141628b400f6SJacob Faibussowitsch PetscCheck(pvtk,PetscObjectComm((PetscObject)odm),PETSC_ERR_LIB,P4EST_STRING "_vtk_write_header() failed"); 14170a96aa3bSJed Brown PetscStackCallP4estReturn(pvtk,p4est_vtk_write_cell_dataf,(pvtk, 14180a96aa3bSJed Brown 1, /* write tree */ 14190a96aa3bSJed Brown 1, /* write level */ 14200a96aa3bSJed Brown 1, /* write rank */ 14210a96aa3bSJed Brown 0, /* do not wrap rank */ 14220a96aa3bSJed Brown 0, /* no scalar fields */ 14230a96aa3bSJed Brown 0, /* no vector fields */ 14240a96aa3bSJed Brown pvtk)); 142528b400f6SJacob Faibussowitsch PetscCheck(pvtk,PetscObjectComm((PetscObject)odm),PETSC_ERR_LIB,P4EST_STRING "_vtk_write_cell_dataf() failed"); 14260a96aa3bSJed Brown PetscStackCallP4estReturn(footerr,p4est_vtk_write_footer,(pvtk)); 142728b400f6SJacob Faibussowitsch PetscCheck(!footerr,PetscObjectComm((PetscObject)odm),PETSC_ERR_LIB,P4EST_STRING "_vtk_write_footer() failed"); 14280a96aa3bSJed Brown } 14290a96aa3bSJed Brown if (!pforest->topo->geom) PetscStackCallP4est(p4est_geometry_destroy,(geom)); 14309566063dSJacob Faibussowitsch PetscCall(PetscFree(filenameStrip)); 14310a96aa3bSJed Brown break; 143298921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 14330a96aa3bSJed Brown } 14340a96aa3bSJed Brown PetscFunctionReturn(0); 14350a96aa3bSJed Brown } 14360a96aa3bSJed Brown 14370a96aa3bSJed Brown #define DMView_HDF5_pforest _append_pforest(DMView_HDF5) 14380a96aa3bSJed Brown static PetscErrorCode DMView_HDF5_pforest(DM dm, PetscViewer viewer) 14390a96aa3bSJed Brown { 14400a96aa3bSJed Brown DM plex; 14410a96aa3bSJed Brown 14420a96aa3bSJed Brown PetscFunctionBegin; 14439566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 14449566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 14459566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 14460a96aa3bSJed Brown PetscFunctionReturn(0); 14470a96aa3bSJed Brown } 14480a96aa3bSJed Brown 14490a96aa3bSJed Brown #define DMView_GLVis_pforest _append_pforest(DMView_GLVis) 14500a96aa3bSJed Brown static PetscErrorCode DMView_GLVis_pforest(DM dm, PetscViewer viewer) 14510a96aa3bSJed Brown { 14520a96aa3bSJed Brown DM plex; 14530a96aa3bSJed Brown 14540a96aa3bSJed Brown PetscFunctionBegin; 14559566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 14569566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex)); 14579566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer)); 14580a96aa3bSJed Brown PetscFunctionReturn(0); 14590a96aa3bSJed Brown } 14600a96aa3bSJed Brown 14610a96aa3bSJed Brown #define DMView_pforest _append_pforest(DMView) 14620a96aa3bSJed Brown static PetscErrorCode DMView_pforest(DM dm, PetscViewer viewer) 14630a96aa3bSJed Brown { 14640a96aa3bSJed Brown PetscBool isascii, isvtk, ishdf5, isglvis; 14650a96aa3bSJed Brown 14660a96aa3bSJed Brown PetscFunctionBegin; 14670a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14680a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 14699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii)); 14709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk)); 14719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5)); 14729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis)); 14730a96aa3bSJed Brown if (isascii) { 14749566063dSJacob Faibussowitsch PetscCall(DMView_ASCII_pforest((PetscObject) dm,viewer)); 14750a96aa3bSJed Brown } else if (isvtk) { 14769566063dSJacob Faibussowitsch PetscCall(DMView_VTK_pforest((PetscObject) dm,viewer)); 14770a96aa3bSJed Brown } else if (ishdf5) { 14789566063dSJacob Faibussowitsch PetscCall(DMView_HDF5_pforest(dm, viewer)); 14790a96aa3bSJed Brown } else if (isglvis) { 14809566063dSJacob Faibussowitsch PetscCall(DMView_GLVis_pforest(dm, viewer)); 14810a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject) dm),PETSC_ERR_SUP,"Viewer not supported (not VTK, HDF5, or GLVis)"); 14820a96aa3bSJed Brown PetscFunctionReturn(0); 14830a96aa3bSJed Brown } 14840a96aa3bSJed Brown 14850a96aa3bSJed Brown static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *conn, PetscInt **tree_face_to_uniq) 14860a96aa3bSJed Brown { 14870a96aa3bSJed Brown PetscInt *ttf, f, t, g, count; 14880a96aa3bSJed Brown PetscInt numFacets; 14890a96aa3bSJed Brown 14900a96aa3bSJed Brown PetscFunctionBegin; 14910a96aa3bSJed Brown numFacets = conn->num_trees * P4EST_FACES; 14929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFacets,&ttf)); 14930a96aa3bSJed Brown for (f = 0; f < numFacets; f++) ttf[f] = -1; 14940a96aa3bSJed Brown for (g = 0, count = 0, t = 0; t < conn->num_trees; t++) { 14950a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++, g++) { 14960a96aa3bSJed Brown if (ttf[g] == -1) { 14970a96aa3bSJed Brown PetscInt ng; 14980a96aa3bSJed Brown 14990a96aa3bSJed Brown ttf[g] = count++; 15000a96aa3bSJed Brown ng = conn->tree_to_tree[g] * P4EST_FACES + (conn->tree_to_face[g] % P4EST_FACES); 15010a96aa3bSJed Brown ttf[ng] = ttf[g]; 15020a96aa3bSJed Brown } 15030a96aa3bSJed Brown } 15040a96aa3bSJed Brown } 15050a96aa3bSJed Brown *tree_face_to_uniq = ttf; 15060a96aa3bSJed Brown PetscFunctionReturn(0); 15070a96aa3bSJed Brown } 15080a96aa3bSJed Brown 15090a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM dm, p4est_connectivity_t **connOut, PetscInt **tree_face_to_uniq) 15100a96aa3bSJed Brown { 15110a96aa3bSJed Brown p4est_topidx_t numTrees, numVerts, numCorns, numCtt; 15120a96aa3bSJed Brown PetscSection ctt; 15130a96aa3bSJed Brown #if defined(P4_TO_P8) 15140a96aa3bSJed Brown p4est_topidx_t numEdges, numEtt; 15150a96aa3bSJed Brown PetscSection ett; 15160a96aa3bSJed Brown PetscInt eStart, eEnd, e, ettSize; 15170a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES + P8EST_EDGES; 15180a96aa3bSJed Brown PetscInt edgeOff = 1 + P4EST_FACES; 15190a96aa3bSJed Brown #else 15200a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES; 15210a96aa3bSJed Brown #endif 15220a96aa3bSJed Brown p4est_connectivity_t *conn; 15230a96aa3bSJed Brown PetscInt cStart, cEnd, c, vStart, vEnd, v, fStart, fEnd, f; 15240a96aa3bSJed Brown PetscInt *star = NULL, *closure = NULL, closureSize, starSize, cttSize; 15250a96aa3bSJed Brown PetscInt *ttf; 15260a96aa3bSJed Brown 15270a96aa3bSJed Brown PetscFunctionBegin; 15280a96aa3bSJed Brown /* 1: count objects, allocate */ 15299566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd)); 15309566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cEnd-cStart,&numTrees)); 15310a96aa3bSJed Brown numVerts = P4EST_CHILDREN * numTrees; 15329566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,0,&vStart,&vEnd)); 15339566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(vEnd-vStart,&numCorns)); 15349566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,&ctt)); 15359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ctt,vStart,vEnd)); 15360a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 15370a96aa3bSJed Brown PetscInt s; 15380a96aa3bSJed Brown 15399566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star)); 15400a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 15410a96aa3bSJed Brown PetscInt p = star[2*s]; 15420a96aa3bSJed Brown 15430a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 15440a96aa3bSJed Brown /* we want to count every time cell p references v, so we see how many times it comes up in the closure. This 15450a96aa3bSJed Brown * only protects against periodicity problems */ 15469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 154763a3b9bcSJacob 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); 15480a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 15490a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 15500a96aa3bSJed Brown 15511dca8a05SBarry Smith PetscCheck(cellVert >= vStart && cellVert < vEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure: vertices"); 15520a96aa3bSJed Brown if (cellVert == v) { 15539566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(ctt,v,1)); 15540a96aa3bSJed Brown } 15550a96aa3bSJed Brown } 15569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 15570a96aa3bSJed Brown } 15580a96aa3bSJed Brown } 15599566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star)); 15600a96aa3bSJed Brown } 15619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ctt)); 15629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ctt,&cttSize)); 15639566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cttSize,&numCtt)); 15640a96aa3bSJed Brown #if defined(P4_TO_P8) 15659566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,P4EST_DIM-1,&eStart,&eEnd)); 15669566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(eEnd-eStart,&numEdges)); 15679566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,&ett)); 15689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ett,eStart,eEnd)); 15690a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 15700a96aa3bSJed Brown PetscInt s; 15710a96aa3bSJed Brown 15729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star)); 15730a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 15740a96aa3bSJed Brown PetscInt p = star[2*s]; 15750a96aa3bSJed Brown 15760a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 15770a96aa3bSJed Brown /* we want to count every time cell p references e, so we see how many times it comes up in the closure. This 15780a96aa3bSJed Brown * only protects against periodicity problems */ 15799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 158008401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cell with wrong closure size"); 15810a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 15820a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 15830a96aa3bSJed Brown 15841dca8a05SBarry Smith PetscCheck(cellEdge >= eStart && cellEdge < eEnd,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure: edges"); 15850a96aa3bSJed Brown if (cellEdge == e) { 15869566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(ett,e,1)); 15870a96aa3bSJed Brown } 15880a96aa3bSJed Brown } 15899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 15900a96aa3bSJed Brown } 15910a96aa3bSJed Brown } 15929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star)); 15930a96aa3bSJed Brown } 15949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ett)); 15959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ett,&ettSize)); 15969566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(ettSize,&numEtt)); 15970a96aa3bSJed Brown 15980a96aa3bSJed Brown /* This routine allocates space for the arrays, which we fill below */ 15990a96aa3bSJed Brown PetscStackCallP4estReturn(conn,p8est_connectivity_new,(numVerts,numTrees,numEdges,numEtt,numCorns,numCtt)); 16000a96aa3bSJed Brown #else 16010a96aa3bSJed Brown PetscStackCallP4estReturn(conn,p4est_connectivity_new,(numVerts,numTrees,numCorns,numCtt)); 16020a96aa3bSJed Brown #endif 16030a96aa3bSJed Brown 16040a96aa3bSJed Brown /* 2: visit every face, determine neighboring cells(trees) */ 16059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm,1,&fStart,&fEnd)); 16069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd-cStart) * P4EST_FACES,&ttf)); 16070a96aa3bSJed Brown for (f = fStart; f < fEnd; f++) { 16080a96aa3bSJed Brown PetscInt numSupp, s; 16090a96aa3bSJed Brown PetscInt myFace[2] = {-1, -1}; 16100a96aa3bSJed Brown PetscInt myOrnt[2] = {PETSC_MIN_INT, PETSC_MIN_INT}; 16110a96aa3bSJed Brown const PetscInt *supp; 16120a96aa3bSJed Brown 16139566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &numSupp)); 16141dca8a05SBarry 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); 16159566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &supp)); 16160a96aa3bSJed Brown 16170a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16180a96aa3bSJed Brown PetscInt p = supp[s]; 16190a96aa3bSJed Brown 16200a96aa3bSJed Brown if (p >= cEnd) { 16210a96aa3bSJed Brown numSupp--; 16220a96aa3bSJed Brown if (s) supp = &supp[1 - s]; 16230a96aa3bSJed Brown break; 16240a96aa3bSJed Brown } 16250a96aa3bSJed Brown } 16260a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16270a96aa3bSJed Brown PetscInt p = supp[s], i; 16280a96aa3bSJed Brown PetscInt numCone; 16290a96aa3bSJed Brown DMPolytopeType ct; 16300a96aa3bSJed Brown const PetscInt *cone; 16310a96aa3bSJed Brown const PetscInt *ornt; 16320a96aa3bSJed Brown PetscInt orient = PETSC_MIN_INT; 16330a96aa3bSJed Brown 16349566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &numCone)); 163563a3b9bcSJacob 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); 16369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 16379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[0], &ct)); 16389566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 16390a96aa3bSJed Brown for (i = 0; i < P4EST_FACES; i++) { 16400a96aa3bSJed Brown if (cone[i] == f) { 16410a96aa3bSJed Brown orient = DMPolytopeConvertNewOrientation_Internal(ct, ornt[i]); 16420a96aa3bSJed Brown break; 16430a96aa3bSJed Brown } 16440a96aa3bSJed Brown } 164563a3b9bcSJacob Faibussowitsch PetscCheck(i < P4EST_FACES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"cell %" PetscInt_FMT " faced %" PetscInt_FMT " mismatch",p,f); 16460a96aa3bSJed Brown if (p < cStart || p >= cEnd) { 16470a96aa3bSJed Brown DMPolytopeType ct; 16489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 164963a3b9bcSJacob 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); 16500a96aa3bSJed Brown } 16510a96aa3bSJed Brown ttf[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = f - fStart; 16520a96aa3bSJed Brown if (numSupp == 1) { 16530a96aa3bSJed Brown /* boundary faces indicated by self reference */ 16540a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = p - cStart; 16550a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = (int8_t) PetscFaceToP4estFace[i]; 16560a96aa3bSJed Brown } else { 16570a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16580a96aa3bSJed Brown 16590a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = supp[1 - s] - cStart; 16600a96aa3bSJed Brown myFace[s] = PetscFaceToP4estFace[i]; 16610a96aa3bSJed Brown /* get the orientation of cell p in p4est-type closure to facet f, by composing the p4est-closure to 16620a96aa3bSJed Brown * petsc-closure permutation and the petsc-closure to facet orientation */ 16630a96aa3bSJed Brown myOrnt[s] = DihedralCompose(N,orient,DMPolytopeConvertNewOrientation_Internal(ct, P4estFaceToPetscOrnt[myFace[s]])); 16640a96aa3bSJed Brown } 16650a96aa3bSJed Brown } 16660a96aa3bSJed Brown if (numSupp == 2) { 16670a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 16680a96aa3bSJed Brown PetscInt p = supp[s]; 16690a96aa3bSJed Brown PetscInt orntAtoB; 16700a96aa3bSJed Brown PetscInt p4estOrient; 16710a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 16720a96aa3bSJed Brown 16730a96aa3bSJed Brown /* composing the forward permutation with the other cell's inverse permutation gives the self-to-neighbor 16740a96aa3bSJed Brown * permutation of this cell-facet's cone */ 16750a96aa3bSJed Brown orntAtoB = DihedralCompose(N,DihedralInvert(N,myOrnt[1-s]),myOrnt[s]); 16760a96aa3bSJed Brown 16770a96aa3bSJed Brown /* convert cone-description permutation (i.e., edges around facet) to cap-description permutation (i.e., 16780a96aa3bSJed Brown * vertices around facet) */ 16790a96aa3bSJed Brown #if !defined(P4_TO_P8) 16800a96aa3bSJed Brown p4estOrient = orntAtoB < 0 ? -(orntAtoB + 1) : orntAtoB; 16810a96aa3bSJed Brown #else 16820a96aa3bSJed Brown { 16830a96aa3bSJed Brown PetscInt firstVert = orntAtoB < 0 ? ((-orntAtoB) % N) : orntAtoB; 16840a96aa3bSJed Brown PetscInt p4estFirstVert = firstVert < 2 ? firstVert : (firstVert ^ 1); 16850a96aa3bSJed Brown 16860a96aa3bSJed Brown /* swap bits */ 16870a96aa3bSJed Brown p4estOrient = ((myFace[s] <= myFace[1 - s]) || (orntAtoB < 0)) ? p4estFirstVert : ((p4estFirstVert >> 1) | ((p4estFirstVert & 1) << 1)); 16880a96aa3bSJed Brown } 16890a96aa3bSJed Brown #endif 16900a96aa3bSJed Brown /* encode neighbor face and orientation in tree_to_face per p4est_connectivity standard (see 16910a96aa3bSJed Brown * p4est_connectivity.h, p8est_connectivity.h) */ 16920a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + myFace[s]] = (int8_t) myFace[1 - s] + p4estOrient * P4EST_FACES; 16930a96aa3bSJed Brown } 16940a96aa3bSJed Brown } 16950a96aa3bSJed Brown } 16960a96aa3bSJed Brown 16970a96aa3bSJed Brown #if defined(P4_TO_P8) 16980a96aa3bSJed Brown /* 3: visit every edge */ 16990a96aa3bSJed Brown conn->ett_offset[0] = 0; 17000a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 17010a96aa3bSJed Brown PetscInt off, s; 17020a96aa3bSJed Brown 17039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ett,e,&off)); 17040a96aa3bSJed Brown conn->ett_offset[e - eStart] = (p4est_topidx_t) off; 17059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star)); 17060a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 17070a96aa3bSJed Brown PetscInt p = star[2 * s]; 17080a96aa3bSJed Brown 17090a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 17109566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 171108401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure"); 17120a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 17130a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 17140a96aa3bSJed Brown PetscInt cellOrnt = closure[2 * (c + edgeOff) + 1]; 17150a96aa3bSJed Brown DMPolytopeType ct; 17160a96aa3bSJed Brown 17179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cellEdge, &ct)); 17180a96aa3bSJed Brown cellOrnt = DMPolytopeConvertNewOrientation_Internal(ct, cellOrnt); 17190a96aa3bSJed Brown if (cellEdge == e) { 17200a96aa3bSJed Brown PetscInt p4estEdge = PetscEdgeToP4estEdge[c]; 17210a96aa3bSJed Brown PetscInt totalOrient; 17220a96aa3bSJed Brown 17230a96aa3bSJed Brown /* compose p4est-closure to petsc-closure permutation and petsc-closure to edge orientation */ 17240a96aa3bSJed Brown totalOrient = DihedralCompose(2,cellOrnt,DMPolytopeConvertNewOrientation_Internal(DM_POLYTOPE_SEGMENT, P4estEdgeToPetscOrnt[p4estEdge])); 17250a96aa3bSJed Brown /* p4est orientations are positive: -2 => 1, -1 => 0 */ 17260a96aa3bSJed Brown totalOrient = (totalOrient < 0) ? -(totalOrient + 1) : totalOrient; 17270a96aa3bSJed Brown conn->edge_to_tree[off] = (p4est_locidx_t) (p - cStart); 17280a96aa3bSJed Brown /* encode cell-edge and orientation in edge_to_edge per p8est_connectivity standart (see 17290a96aa3bSJed Brown * p8est_connectivity.h) */ 17300a96aa3bSJed Brown conn->edge_to_edge[off++] = (int8_t) p4estEdge + P8EST_EDGES * totalOrient; 17310a96aa3bSJed Brown conn->tree_to_edge[P8EST_EDGES * (p - cStart) + p4estEdge] = e - eStart; 17320a96aa3bSJed Brown } 17330a96aa3bSJed Brown } 17349566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 17350a96aa3bSJed Brown } 17360a96aa3bSJed Brown } 17379566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star)); 17380a96aa3bSJed Brown } 17399566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ett)); 17400a96aa3bSJed Brown #endif 17410a96aa3bSJed Brown 17420a96aa3bSJed Brown /* 4: visit every vertex */ 17430a96aa3bSJed Brown conn->ctt_offset[0] = 0; 17440a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 17450a96aa3bSJed Brown PetscInt off, s; 17460a96aa3bSJed Brown 17479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ctt,v,&off)); 17480a96aa3bSJed Brown conn->ctt_offset[v - vStart] = (p4est_topidx_t) off; 17499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star)); 17500a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 17510a96aa3bSJed Brown PetscInt p = star[2 * s]; 17520a96aa3bSJed Brown 17530a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 17549566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 175508401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure"); 17560a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 17570a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 17580a96aa3bSJed Brown 17590a96aa3bSJed Brown if (cellVert == v) { 17600a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[c]; 17610a96aa3bSJed Brown 17620a96aa3bSJed Brown conn->corner_to_tree[off] = (p4est_locidx_t) (p - cStart); 17630a96aa3bSJed Brown conn->corner_to_corner[off++] = (int8_t) p4estVert; 17640a96aa3bSJed Brown conn->tree_to_corner[P4EST_CHILDREN * (p - cStart) + p4estVert] = v - vStart; 17650a96aa3bSJed Brown } 17660a96aa3bSJed Brown } 17679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure)); 17680a96aa3bSJed Brown } 17690a96aa3bSJed Brown } 17709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star)); 17710a96aa3bSJed Brown } 17729566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ctt)); 17730a96aa3bSJed Brown 17740a96aa3bSJed Brown /* 5: Compute the coordinates */ 17750a96aa3bSJed Brown { 17760a96aa3bSJed Brown PetscInt coordDim; 17770a96aa3bSJed Brown 17789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim)); 17796858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 17800a96aa3bSJed Brown for (c = cStart; c < cEnd; c++) { 17810a96aa3bSJed Brown PetscInt dof; 17826858538eSMatthew G. Knepley PetscBool isDG; 17830a96aa3bSJed Brown PetscScalar *cellCoords = NULL; 17846858538eSMatthew G. Knepley const PetscScalar *array; 17850a96aa3bSJed Brown 17866858538eSMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 17876858538eSMatthew 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); 17880a96aa3bSJed Brown for (v = 0; v < P4EST_CHILDREN; v++) { 17890a96aa3bSJed Brown PetscInt i, lim = PetscMin(3, coordDim); 17900a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[v]; 17910a96aa3bSJed Brown 17920a96aa3bSJed Brown conn->tree_to_vertex[P4EST_CHILDREN * (c - cStart) + v] = P4EST_CHILDREN * (c - cStart) + v; 17930a96aa3bSJed Brown /* p4est vertices are always embedded in R^3 */ 17940a96aa3bSJed Brown for (i = 0; i < 3; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = 0.; 17950a96aa3bSJed Brown for (i = 0; i < lim; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = PetscRealPart(cellCoords[v * coordDim + i]); 17960a96aa3bSJed Brown } 17976858538eSMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords)); 17980a96aa3bSJed Brown } 17990a96aa3bSJed Brown } 18000a96aa3bSJed Brown 18010a96aa3bSJed Brown #if defined(P4EST_ENABLE_DEBUG) 180208401ef6SPierre Jolivet PetscCheck(p4est_connectivity_is_valid(conn),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Plex to p4est conversion failed"); 18030a96aa3bSJed Brown #endif 18040a96aa3bSJed Brown 18050a96aa3bSJed Brown *connOut = conn; 18060a96aa3bSJed Brown 18070a96aa3bSJed Brown *tree_face_to_uniq = ttf; 18080a96aa3bSJed Brown 18090a96aa3bSJed Brown PetscFunctionReturn(0); 18100a96aa3bSJed Brown } 18110a96aa3bSJed Brown 18120a96aa3bSJed Brown static PetscErrorCode locidx_to_PetscInt(sc_array_t * array) 18130a96aa3bSJed Brown { 18140a96aa3bSJed Brown sc_array_t *newarray; 18150a96aa3bSJed Brown size_t zz, count = array->elem_count; 18160a96aa3bSJed Brown 18170a96aa3bSJed Brown PetscFunctionBegin; 181808401ef6SPierre Jolivet PetscCheck(array->elem_size == sizeof(p4est_locidx_t),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong locidx size"); 18190a96aa3bSJed Brown 18200a96aa3bSJed Brown if (sizeof(p4est_locidx_t) == sizeof(PetscInt)) PetscFunctionReturn(0); 18210a96aa3bSJed Brown 18220a96aa3bSJed Brown newarray = sc_array_new_size (sizeof(PetscInt), array->elem_count); 18230a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18240a96aa3bSJed Brown p4est_locidx_t il = *((p4est_locidx_t*) sc_array_index (array, zz)); 18250a96aa3bSJed Brown PetscInt *ip = (PetscInt*) sc_array_index (newarray, zz); 18260a96aa3bSJed Brown 18270a96aa3bSJed Brown *ip = (PetscInt) il; 18280a96aa3bSJed Brown } 18290a96aa3bSJed Brown 18300a96aa3bSJed Brown sc_array_reset (array); 18310a96aa3bSJed Brown sc_array_init_size (array, sizeof(PetscInt), count); 18320a96aa3bSJed Brown sc_array_copy (array, newarray); 18330a96aa3bSJed Brown sc_array_destroy (newarray); 18340a96aa3bSJed Brown PetscFunctionReturn(0); 18350a96aa3bSJed Brown } 18360a96aa3bSJed Brown 18370a96aa3bSJed Brown static PetscErrorCode coords_double_to_PetscScalar(sc_array_t * array, PetscInt dim) 18380a96aa3bSJed Brown { 18390a96aa3bSJed Brown sc_array_t *newarray; 18400a96aa3bSJed Brown size_t zz, count = array->elem_count; 18410a96aa3bSJed Brown 18420a96aa3bSJed Brown PetscFunctionBegin; 18431dca8a05SBarry Smith PetscCheck(array->elem_size == 3 * sizeof(double),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong coordinate size"); 18440a96aa3bSJed Brown #if !defined(PETSC_USE_COMPLEX) 18450a96aa3bSJed Brown if (sizeof(double) == sizeof(PetscScalar) && dim == 3) PetscFunctionReturn(0); 18460a96aa3bSJed Brown #endif 18470a96aa3bSJed Brown 18480a96aa3bSJed Brown newarray = sc_array_new_size (dim * sizeof(PetscScalar), array->elem_count); 18490a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18500a96aa3bSJed Brown int i; 18510a96aa3bSJed Brown double *id = (double*) sc_array_index (array, zz); 18520a96aa3bSJed Brown PetscScalar *ip = (PetscScalar*) sc_array_index (newarray, zz); 18530a96aa3bSJed Brown 18540a96aa3bSJed Brown for (i = 0; i < dim; i++) ip[i] = 0.; 18550a96aa3bSJed Brown for (i = 0; i < PetscMin(dim,3); i++) ip[i] = (PetscScalar) id[i]; 18560a96aa3bSJed Brown } 18570a96aa3bSJed Brown 18580a96aa3bSJed Brown sc_array_reset (array); 18590a96aa3bSJed Brown sc_array_init_size (array, dim * sizeof(PetscScalar), count); 18600a96aa3bSJed Brown sc_array_copy (array, newarray); 18610a96aa3bSJed Brown sc_array_destroy (newarray); 18620a96aa3bSJed Brown PetscFunctionReturn(0); 18630a96aa3bSJed Brown } 18640a96aa3bSJed Brown 18650a96aa3bSJed Brown static PetscErrorCode locidx_pair_to_PetscSFNode(sc_array_t * array) 18660a96aa3bSJed Brown { 18670a96aa3bSJed Brown sc_array_t *newarray; 18680a96aa3bSJed Brown size_t zz, count = array->elem_count; 18690a96aa3bSJed Brown 18700a96aa3bSJed Brown PetscFunctionBegin; 18711dca8a05SBarry Smith PetscCheck(array->elem_size == 2 * sizeof(p4est_locidx_t),PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong locidx size"); 18720a96aa3bSJed Brown 18730a96aa3bSJed Brown newarray = sc_array_new_size (sizeof(PetscSFNode), array->elem_count); 18740a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 18750a96aa3bSJed Brown p4est_locidx_t *il = (p4est_locidx_t*) sc_array_index (array, zz); 18760a96aa3bSJed Brown PetscSFNode *ip = (PetscSFNode*) sc_array_index (newarray, zz); 18770a96aa3bSJed Brown 18780a96aa3bSJed Brown ip->rank = (PetscInt) il[0]; 18790a96aa3bSJed Brown ip->index = (PetscInt) il[1]; 18800a96aa3bSJed Brown } 18810a96aa3bSJed Brown 18820a96aa3bSJed Brown sc_array_reset (array); 18830a96aa3bSJed Brown sc_array_init_size (array, sizeof(PetscSFNode), count); 18840a96aa3bSJed Brown sc_array_copy (array, newarray); 18850a96aa3bSJed Brown sc_array_destroy (newarray); 18860a96aa3bSJed Brown PetscFunctionReturn(0); 18870a96aa3bSJed Brown } 18880a96aa3bSJed Brown 18890a96aa3bSJed Brown static PetscErrorCode P4estToPlex_Local(p4est_t *p4est, DM * plex) 18900a96aa3bSJed Brown { 18910a96aa3bSJed Brown PetscFunctionBegin; 18920a96aa3bSJed Brown { 18930a96aa3bSJed Brown sc_array_t *points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 18940a96aa3bSJed Brown sc_array_t *cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 18950a96aa3bSJed Brown sc_array_t *cones = sc_array_new(sizeof(p4est_locidx_t)); 18960a96aa3bSJed Brown sc_array_t *cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 18970a96aa3bSJed Brown sc_array_t *coords = sc_array_new(3 * sizeof(double)); 18980a96aa3bSJed Brown sc_array_t *children = sc_array_new(sizeof(p4est_locidx_t)); 18990a96aa3bSJed Brown sc_array_t *parents = sc_array_new(sizeof(p4est_locidx_t)); 19000a96aa3bSJed Brown sc_array_t *childids = sc_array_new(sizeof(p4est_locidx_t)); 19010a96aa3bSJed Brown sc_array_t *leaves = sc_array_new(sizeof(p4est_locidx_t)); 19020a96aa3bSJed Brown sc_array_t *remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 19030a96aa3bSJed Brown p4est_locidx_t first_local_quad; 19040a96aa3bSJed Brown 19050a96aa3bSJed Brown PetscStackCallP4est(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)); 19060a96aa3bSJed Brown 19079566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 19089566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 19099566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 19109566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 19119566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, P4EST_DIM)); 19120a96aa3bSJed Brown 19139566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PETSC_COMM_SELF,plex)); 19149566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*plex,P4EST_DIM)); 19159566063dSJacob 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)); 19169566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(*plex)); 19170a96aa3bSJed Brown sc_array_destroy (points_per_dim); 19180a96aa3bSJed Brown sc_array_destroy (cone_sizes); 19190a96aa3bSJed Brown sc_array_destroy (cones); 19200a96aa3bSJed Brown sc_array_destroy (cone_orientations); 19210a96aa3bSJed Brown sc_array_destroy (coords); 19220a96aa3bSJed Brown sc_array_destroy (children); 19230a96aa3bSJed Brown sc_array_destroy (parents); 19240a96aa3bSJed Brown sc_array_destroy (childids); 19250a96aa3bSJed Brown sc_array_destroy (leaves); 19260a96aa3bSJed Brown sc_array_destroy (remotes); 19270a96aa3bSJed Brown } 19280a96aa3bSJed Brown PetscFunctionReturn(0); 19290a96aa3bSJed Brown } 19300a96aa3bSJed Brown 19310a96aa3bSJed Brown #define DMReferenceTreeGetChildSymmetry_pforest _append_pforest(DMReferenceTreeGetChildSymmetry) 19320a96aa3bSJed Brown static PetscErrorCode DMReferenceTreeGetChildSymmetry_pforest(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB,PetscInt *childB) 19330a96aa3bSJed Brown { 19340a96aa3bSJed Brown PetscInt coneSize, dStart, dEnd, vStart, vEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 19350a96aa3bSJed Brown 19360a96aa3bSJed Brown PetscFunctionBegin; 19370a96aa3bSJed Brown if (parentOrientA == parentOrientB) { 19380a96aa3bSJed Brown if (childOrientB) *childOrientB = childOrientA; 19390a96aa3bSJed Brown if (childB) *childB = childA; 19400a96aa3bSJed Brown PetscFunctionReturn(0); 19410a96aa3bSJed Brown } 19429566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,0,&vStart,&vEnd)); 19436aad120cSJose E. Roman if (childA >= vStart && childA < vEnd) { /* vertices (always in the middle) are invariant under rotation */ 19440a96aa3bSJed Brown if (childOrientB) *childOrientB = 0; 19450a96aa3bSJed Brown if (childB) *childB = childA; 19460a96aa3bSJed Brown PetscFunctionReturn(0); 19470a96aa3bSJed Brown } 19480a96aa3bSJed Brown for (dim = 0; dim < 3; dim++) { 19499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd)); 19500a96aa3bSJed Brown if (parent >= dStart && parent <= dEnd) break; 19510a96aa3bSJed Brown } 195263a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %" PetscInt_FMT "-cells",dim); 195328b400f6SJacob Faibussowitsch PetscCheck(dim,PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children"); 19540a96aa3bSJed Brown if (childA < dStart || childA >= dEnd) { /* a 1-cell in a 2-cell */ 19550a96aa3bSJed Brown /* this is a lower-dimensional child: bootstrap */ 19560a96aa3bSJed Brown PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 19570a96aa3bSJed Brown const PetscInt *supp, *coneA, *coneB, *oA, *oB; 19580a96aa3bSJed Brown 19599566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm,childA,&size)); 19609566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm,childA,&supp)); 19610a96aa3bSJed Brown 19620a96aa3bSJed Brown /* find a point sA in supp(childA) that has the same parent */ 19630a96aa3bSJed Brown for (i = 0; i < size; i++) { 19640a96aa3bSJed Brown PetscInt sParent; 19650a96aa3bSJed Brown 19660a96aa3bSJed Brown sA = supp[i]; 19670a96aa3bSJed Brown if (sA == parent) continue; 19689566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm,sA,&sParent,NULL)); 19690a96aa3bSJed Brown if (sParent == parent) break; 19700a96aa3bSJed Brown } 197108401ef6SPierre Jolivet PetscCheck(i != size,PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children"); 19720a96aa3bSJed Brown /* find out which point sB is in an equivalent position to sA under 19730a96aa3bSJed Brown * parentOrientB */ 19749566063dSJacob Faibussowitsch PetscCall(DMReferenceTreeGetChildSymmetry_pforest(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB)); 19759566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,sA,&sConeSize)); 19769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,sA,&coneA)); 19779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm,sB,&coneB)); 19789566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm,sA,&oA)); 19799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm,sB,&oB)); 19800a96aa3bSJed Brown /* step through the cone of sA in natural order */ 19810a96aa3bSJed Brown for (i = 0; i < sConeSize; i++) { 19820a96aa3bSJed Brown if (coneA[i] == childA) { 19830a96aa3bSJed Brown /* if childA is at position i in coneA, 19840a96aa3bSJed Brown * then we want the point that is at sOrientB*i in coneB */ 19850a96aa3bSJed Brown PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize); 19860a96aa3bSJed Brown if (childB) *childB = coneB[j]; 19870a96aa3bSJed Brown if (childOrientB) { 19880a96aa3bSJed Brown DMPolytopeType ct; 19890a96aa3bSJed Brown PetscInt oBtrue; 19900a96aa3bSJed Brown 19919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,childA,&coneSize)); 19920a96aa3bSJed Brown /* compose sOrientB and oB[j] */ 19931dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge"); 19940a96aa3bSJed Brown ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 19950a96aa3bSJed Brown /* we may have to flip an edge */ 19960a96aa3bSJed Brown oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientationInv(ct, -1, oB[j]); 19970a96aa3bSJed Brown oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 19980a96aa3bSJed Brown ABswap = DihedralSwap(coneSize,DMPolytopeConvertNewOrientation_Internal(ct, oA[i]),oBtrue); 19990a96aa3bSJed Brown *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 20000a96aa3bSJed Brown } 20010a96aa3bSJed Brown break; 20020a96aa3bSJed Brown } 20030a96aa3bSJed Brown } 200408401ef6SPierre Jolivet PetscCheck(i != sConeSize,PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch"); 20050a96aa3bSJed Brown PetscFunctionReturn(0); 20060a96aa3bSJed Brown } 20070a96aa3bSJed Brown /* get the cone size and symmetry swap */ 20089566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm,parent,&coneSize)); 20090a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 20100a96aa3bSJed Brown if (dim == 2) { 20110a96aa3bSJed Brown /* orientations refer to cones: we want them to refer to vertices: 20120a96aa3bSJed Brown * if it's a rotation, they are the same, but if the order is reversed, a 20130a96aa3bSJed Brown * permutation that puts side i first does *not* put vertex i first */ 20140a96aa3bSJed Brown oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 20150a96aa3bSJed Brown oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 20160a96aa3bSJed Brown ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 20170a96aa3bSJed Brown } else { 20180a96aa3bSJed Brown oAvert = parentOrientA; 20190a96aa3bSJed Brown oBvert = parentOrientB; 20200a96aa3bSJed Brown ABswapVert = ABswap; 20210a96aa3bSJed Brown } 20220a96aa3bSJed Brown if (childB) { 20230a96aa3bSJed Brown /* assume that each child corresponds to a vertex, in the same order */ 20240a96aa3bSJed Brown PetscInt p, posA = -1, numChildren, i; 20250a96aa3bSJed Brown const PetscInt *children; 20260a96aa3bSJed Brown 20270a96aa3bSJed Brown /* count which position the child is in */ 20289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm,parent,&numChildren,&children)); 20290a96aa3bSJed Brown for (i = 0; i < numChildren; i++) { 20300a96aa3bSJed Brown p = children[i]; 20310a96aa3bSJed Brown if (p == childA) { 20320a96aa3bSJed Brown if (dim == 1) { 20330a96aa3bSJed Brown posA = i; 20340a96aa3bSJed Brown } else { /* 2D Morton to rotation */ 20350a96aa3bSJed Brown posA = (i & 2) ? (i ^ 1) : i; 20360a96aa3bSJed Brown } 20370a96aa3bSJed Brown break; 20380a96aa3bSJed Brown } 20390a96aa3bSJed Brown } 20400a96aa3bSJed Brown if (posA >= coneSize) { 20410a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not find childA in children of parent"); 20420a96aa3bSJed Brown } else { 20430a96aa3bSJed Brown /* figure out position B by applying ABswapVert */ 20440a96aa3bSJed Brown PetscInt posB, childIdB; 20450a96aa3bSJed Brown 20460a96aa3bSJed Brown posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 20470a96aa3bSJed Brown if (dim == 1) { 20480a96aa3bSJed Brown childIdB = posB; 20490a96aa3bSJed Brown } else { /* 2D rotation to Morton */ 20500a96aa3bSJed Brown childIdB = (posB & 2) ? (posB ^ 1) : posB; 20510a96aa3bSJed Brown } 20520a96aa3bSJed Brown if (childB) *childB = children[childIdB]; 20530a96aa3bSJed Brown } 20540a96aa3bSJed Brown } 20550a96aa3bSJed Brown if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 20560a96aa3bSJed Brown PetscFunctionReturn(0); 20570a96aa3bSJed Brown } 20580a96aa3bSJed Brown 20590a96aa3bSJed Brown #define DMCreateReferenceTree_pforest _append_pforest(DMCreateReferenceTree) 20600a96aa3bSJed Brown static PetscErrorCode DMCreateReferenceTree_pforest(MPI_Comm comm, DM *dm) 20610a96aa3bSJed Brown { 20620a96aa3bSJed Brown p4est_connectivity_t *refcube; 20630a96aa3bSJed Brown p4est_t *root, *refined; 20640a96aa3bSJed Brown DM dmRoot, dmRefined; 20650a96aa3bSJed Brown DM_Plex *mesh; 20660a96aa3bSJed Brown PetscMPIInt rank; 20670a96aa3bSJed Brown 20680a96aa3bSJed Brown PetscFunctionBegin; 20690a96aa3bSJed Brown PetscStackCallP4estReturn(refcube,p4est_connectivity_new_byname,("unit")); 20700a96aa3bSJed Brown { /* [-1,1]^d geometry */ 20710a96aa3bSJed Brown PetscInt i, j; 20720a96aa3bSJed Brown 20730a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 20740a96aa3bSJed Brown for (j = 0; j < 3; j++) { 20750a96aa3bSJed Brown refcube->vertices[3 * i + j] *= 2.; 20760a96aa3bSJed Brown refcube->vertices[3 * i + j] -= 1.; 20770a96aa3bSJed Brown } 20780a96aa3bSJed Brown } 20790a96aa3bSJed Brown } 20800a96aa3bSJed Brown PetscStackCallP4estReturn(root,p4est_new,(PETSC_COMM_SELF,refcube,0,NULL,NULL)); 20810a96aa3bSJed Brown PetscStackCallP4estReturn(refined,p4est_new_ext,(PETSC_COMM_SELF,refcube,0,1,1,0,NULL,NULL)); 20829566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(root,&dmRoot)); 20839566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(refined,&dmRefined)); 20840a96aa3bSJed Brown { 20850a96aa3bSJed Brown #if !defined(P4_TO_P8) 20860a96aa3bSJed Brown PetscInt nPoints = 25; 20870a96aa3bSJed Brown PetscInt perm[25] = {0, 1, 2, 3, 20880a96aa3bSJed Brown 4, 12, 8, 14, 20890a96aa3bSJed Brown 6, 9, 15, 20900a96aa3bSJed Brown 5, 13, 10, 20910a96aa3bSJed Brown 7, 11, 20920a96aa3bSJed Brown 16, 22, 20, 24, 20930a96aa3bSJed Brown 17, 21, 20940a96aa3bSJed Brown 18, 23, 20950a96aa3bSJed Brown 19}; 20960a96aa3bSJed Brown PetscInt ident[25] = {0, 0, 0, 0, 20970a96aa3bSJed Brown 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 0, 20980a96aa3bSJed Brown 5, 6, 7, 8, 1, 2, 3, 4, 0}; 20990a96aa3bSJed Brown #else 21000a96aa3bSJed Brown PetscInt nPoints = 125; 21010a96aa3bSJed Brown PetscInt perm[125] = {0, 1, 2, 3, 4, 5, 6, 7, 21020a96aa3bSJed Brown 8, 32, 16, 36, 24, 40, 21030a96aa3bSJed Brown 12, 17, 37, 25, 41, 21040a96aa3bSJed Brown 9, 33, 20, 26, 42, 21050a96aa3bSJed Brown 13, 21, 27, 43, 21060a96aa3bSJed Brown 10, 34, 18, 38, 28, 21070a96aa3bSJed Brown 14, 19, 39, 29, 21080a96aa3bSJed Brown 11, 35, 22, 30, 21090a96aa3bSJed Brown 15, 23, 31, 21100a96aa3bSJed Brown 44, 84, 76, 92, 52, 86, 68, 94, 60, 78, 70, 96, 21110a96aa3bSJed Brown 45, 85, 77, 93, 54, 72, 62, 74, 21120a96aa3bSJed Brown 46, 80, 53, 87, 69, 95, 64, 82, 21130a96aa3bSJed Brown 47, 81, 55, 73, 66, 21140a96aa3bSJed Brown 48, 88, 56, 90, 61, 79, 71, 97, 21150a96aa3bSJed Brown 49, 89, 58, 63, 75, 21160a96aa3bSJed Brown 50, 57, 91, 65, 83, 21170a96aa3bSJed Brown 51, 59, 67, 21180a96aa3bSJed Brown 98, 106, 110, 122, 114, 120, 118, 124, 21190a96aa3bSJed Brown 99, 111, 115, 119, 21200a96aa3bSJed Brown 100, 107, 116, 121, 21210a96aa3bSJed Brown 101, 117, 21220a96aa3bSJed Brown 102, 108, 112, 123, 21230a96aa3bSJed Brown 103, 113, 21240a96aa3bSJed Brown 104, 109, 21250a96aa3bSJed Brown 105}; 21260a96aa3bSJed Brown PetscInt ident[125] = {0, 0, 0, 0, 0, 0, 0, 0, 21270a96aa3bSJed 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, 21280a96aa3bSJed Brown 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21290a96aa3bSJed 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, 21300a96aa3bSJed 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, 21310a96aa3bSJed Brown 0, 0, 0, 0, 0, 0, 21320a96aa3bSJed Brown 19, 20, 21, 22, 23, 24, 25, 26, 21330a96aa3bSJed Brown 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21340a96aa3bSJed Brown 1, 2, 3, 4, 5, 6, 21350a96aa3bSJed Brown 0}; 21360a96aa3bSJed Brown 21370a96aa3bSJed Brown #endif 21380a96aa3bSJed Brown IS permIS; 21390a96aa3bSJed Brown DM dmPerm; 21400a96aa3bSJed Brown 21419566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,nPoints,perm,PETSC_USE_POINTER,&permIS)); 21429566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dmRefined,permIS,&dmPerm)); 21430a96aa3bSJed Brown if (dmPerm) { 21449566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 21450a96aa3bSJed Brown dmRefined = dmPerm; 21460a96aa3bSJed Brown } 21479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS)); 21480a96aa3bSJed Brown { 21490a96aa3bSJed Brown PetscInt p; 21509566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRoot,"identity")); 21519566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRefined,"identity")); 21520a96aa3bSJed Brown for (p = 0; p < P4EST_INSUL; p++) { 21539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dmRoot,"identity",p,p)); 21540a96aa3bSJed Brown } 21550a96aa3bSJed Brown for (p = 0; p < nPoints; p++) { 21569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dmRefined,"identity",p,ident[p])); 21570a96aa3bSJed Brown } 21580a96aa3bSJed Brown } 21590a96aa3bSJed Brown } 21609566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(dmRoot,dmRefined,"identity",dm)); 21610a96aa3bSJed Brown mesh = (DM_Plex*) (*dm)->data; 21620a96aa3bSJed Brown mesh->getchildsymmetry = DMReferenceTreeGetChildSymmetry_pforest; 21639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 21640a96aa3bSJed Brown if (rank == 0) { 21659566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRoot, NULL,"-dm_p4est_ref_root_view")); 21669566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined,NULL,"-dm_p4est_ref_refined_view")); 21679566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined,NULL,"-dm_p4est_ref_tree_view")); 21680a96aa3bSJed Brown } 21699566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined)); 21709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRoot)); 21710a96aa3bSJed Brown PetscStackCallP4est(p4est_destroy,(refined)); 21720a96aa3bSJed Brown PetscStackCallP4est(p4est_destroy,(root)); 21730a96aa3bSJed Brown PetscStackCallP4est(p4est_connectivity_destroy,(refcube)); 21740a96aa3bSJed Brown PetscFunctionReturn(0); 21750a96aa3bSJed Brown } 21760a96aa3bSJed Brown 21770a96aa3bSJed Brown static PetscErrorCode DMShareDiscretization(DM dmA, DM dmB) 21780a96aa3bSJed Brown { 21790a96aa3bSJed Brown void *ctx; 21800a96aa3bSJed Brown PetscInt num; 21810a96aa3bSJed Brown PetscReal val; 21820a96aa3bSJed Brown 21830a96aa3bSJed Brown PetscFunctionBegin; 21849566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmA,&ctx)); 21859566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(dmB,ctx)); 21869566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmA,dmB)); 21879566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dmA,&num,&val)); 21889566063dSJacob Faibussowitsch PetscCall(DMSetOutputSequenceNumber(dmB,num,val)); 21890a96aa3bSJed Brown if (dmB->localSection != dmA->localSection || dmB->globalSection != dmA->globalSection) { 21909566063dSJacob Faibussowitsch PetscCall(DMClearLocalVectors(dmB)); 21919566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->localSection)); 21929566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->localSection))); 21930a96aa3bSJed Brown dmB->localSection = dmA->localSection; 21949566063dSJacob Faibussowitsch PetscCall(DMClearGlobalVectors(dmB)); 21959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->globalSection)); 21969566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->globalSection))); 21970a96aa3bSJed Brown dmB->globalSection = dmA->globalSection; 21989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.section)); 21999566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&(dmB->defaultConstraint.section))); 22003b8ba7d1SJed Brown dmB->defaultConstraint.section = dmA->defaultConstraint.section; 22019566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.mat)); 22029566063dSJacob Faibussowitsch PetscCall(MatDestroy(&(dmB->defaultConstraint.mat))); 22033b8ba7d1SJed Brown dmB->defaultConstraint.mat = dmA->defaultConstraint.mat; 22049566063dSJacob Faibussowitsch if (dmA->map) PetscCall(PetscLayoutReference(dmA->map, &dmB->map)); 22050a96aa3bSJed Brown } 22060a96aa3bSJed Brown if (dmB->sectionSF != dmA->sectionSF) { 22079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->sectionSF)); 22089566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&dmB->sectionSF)); 22090a96aa3bSJed Brown dmB->sectionSF = dmA->sectionSF; 22100a96aa3bSJed Brown } 22110a96aa3bSJed Brown PetscFunctionReturn(0); 22120a96aa3bSJed Brown } 22130a96aa3bSJed Brown 22140a96aa3bSJed Brown /* Get an SF that broadcasts a coarse-cell covering of the local fine cells */ 22150a96aa3bSJed Brown static PetscErrorCode DMPforestGetCellCoveringSF(MPI_Comm comm,p4est_t *p4estC, p4est_t *p4estF, PetscInt cStart, PetscInt cEnd, PetscSF *coveringSF) 22160a96aa3bSJed Brown { 22170a96aa3bSJed Brown PetscInt startF, endF, startC, endC, p, nLeaves; 22180a96aa3bSJed Brown PetscSFNode *leaves; 22190a96aa3bSJed Brown PetscSF sf; 22200a96aa3bSJed Brown PetscInt *recv, *send; 22210a96aa3bSJed Brown PetscMPIInt tag; 22220a96aa3bSJed Brown MPI_Request *recvReqs, *sendReqs; 22230a96aa3bSJed Brown PetscSection section; 22240a96aa3bSJed Brown 22250a96aa3bSJed Brown PetscFunctionBegin; 22269566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize,p4estC->mpirank,p4estF,p4estC,&startC,&endC)); 22279566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2*(endC-startC),&recv,endC-startC,&recvReqs)); 22289566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(comm,&tag)); 22290a96aa3bSJed Brown for (p = startC; p < endC; p++) { 22300a96aa3bSJed Brown recvReqs[p-startC] = MPI_REQUEST_NULL; /* just in case we don't initiate a receive */ 22310a96aa3bSJed Brown if (p4estC->global_first_quadrant[p] == p4estC->global_first_quadrant[p+1]) { /* empty coarse partition */ 22320a96aa3bSJed Brown recv[2*(p-startC)] = 0; 22330a96aa3bSJed Brown recv[2*(p-startC)+1] = 0; 22340a96aa3bSJed Brown continue; 22350a96aa3bSJed Brown } 22360a96aa3bSJed Brown 22379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(&recv[2*(p-startC)],2,MPIU_INT,p,tag,comm,&recvReqs[p-startC])); 22380a96aa3bSJed Brown } 22399566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize,p4estC->mpirank,p4estC,p4estF,&startF,&endF)); 22409566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2*(endF-startF),&send,endF-startF,&sendReqs)); 22410a96aa3bSJed Brown /* count the quadrants rank will send to each of [startF,endF) */ 22420a96aa3bSJed Brown for (p = startF; p < endF; p++) { 22430a96aa3bSJed Brown p4est_quadrant_t *myFineStart = &p4estF->global_first_position[p]; 22440a96aa3bSJed Brown p4est_quadrant_t *myFineEnd = &p4estF->global_first_position[p+1]; 22450a96aa3bSJed Brown PetscInt tStart = (PetscInt) myFineStart->p.which_tree; 22460a96aa3bSJed Brown PetscInt tEnd = (PetscInt) myFineEnd->p.which_tree; 22470a96aa3bSJed Brown PetscInt firstCell = -1, lastCell = -1; 22480a96aa3bSJed Brown p4est_tree_t *treeStart = &(((p4est_tree_t*) p4estC->trees->array)[tStart]); 22490a96aa3bSJed Brown p4est_tree_t *treeEnd = (size_t) tEnd < p4estC->trees->elem_count ? &(((p4est_tree_t*) p4estC->trees->array)[tEnd]) : NULL; 22500a96aa3bSJed Brown ssize_t overlapIndex; 22510a96aa3bSJed Brown 22520a96aa3bSJed Brown sendReqs[p-startF] = MPI_REQUEST_NULL; /* just in case we don't initiate a send */ 22530a96aa3bSJed Brown if (p4estF->global_first_quadrant[p] == p4estF->global_first_quadrant[p+1]) continue; 22540a96aa3bSJed Brown 22550a96aa3bSJed Brown /* locate myFineStart in (or before) a cell */ 22560a96aa3bSJed Brown if (treeStart->quadrants.elem_count) { 22570a96aa3bSJed Brown PetscStackCallP4estReturn(overlapIndex,sc_array_bsearch,(&(treeStart->quadrants),myFineStart,p4est_quadrant_disjoint)); 22580a96aa3bSJed Brown if (overlapIndex < 0) { 22590a96aa3bSJed Brown firstCell = 0; 22600a96aa3bSJed Brown } else { 22610a96aa3bSJed Brown firstCell = treeStart->quadrants_offset + overlapIndex; 22620a96aa3bSJed Brown } 22630a96aa3bSJed Brown } else { 22640a96aa3bSJed Brown firstCell = 0; 22650a96aa3bSJed Brown } 22660a96aa3bSJed Brown if (treeEnd && treeEnd->quadrants.elem_count) { 22670a96aa3bSJed Brown PetscStackCallP4estReturn(overlapIndex,sc_array_bsearch,(&(treeEnd->quadrants),myFineEnd,p4est_quadrant_disjoint)); 22680a96aa3bSJed Brown if (overlapIndex < 0) { /* all of this local section is overlapped */ 22690a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 22700a96aa3bSJed Brown } else { 22710a96aa3bSJed Brown p4est_quadrant_t *container = &(((p4est_quadrant_t*) treeEnd->quadrants.array)[overlapIndex]); 22720a96aa3bSJed Brown p4est_quadrant_t first_desc; 22730a96aa3bSJed Brown int equal; 22740a96aa3bSJed Brown 22750a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_first_descendant,(container,&first_desc,P4EST_QMAXLEVEL)); 22760a96aa3bSJed Brown PetscStackCallP4estReturn(equal,p4est_quadrant_is_equal,(myFineEnd,&first_desc)); 22770a96aa3bSJed Brown if (equal) { 22780a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex; 22790a96aa3bSJed Brown } else { 22800a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex + 1; 22810a96aa3bSJed Brown } 22820a96aa3bSJed Brown } 22830a96aa3bSJed Brown } else { 22840a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 22850a96aa3bSJed Brown } 22860a96aa3bSJed Brown send[2*(p-startF)] = firstCell; 22870a96aa3bSJed Brown send[2*(p-startF)+1] = lastCell - firstCell; 22889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(&send[2*(p-startF)],2,MPIU_INT,p,tag,comm,&sendReqs[p-startF])); 22890a96aa3bSJed Brown } 22909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endC-startC),recvReqs,MPI_STATUSES_IGNORE)); 22919566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,§ion)); 22929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section,startC,endC)); 22930a96aa3bSJed Brown for (p = startC; p < endC; p++) { 22940a96aa3bSJed Brown PetscInt numCells = recv[2*(p-startC)+1]; 22959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section,p,numCells)); 22960a96aa3bSJed Brown } 22979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 22989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section,&nLeaves)); 22999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves,&leaves)); 23000a96aa3bSJed Brown for (p = startC; p < endC; p++) { 23010a96aa3bSJed Brown PetscInt firstCell = recv[2*(p-startC)]; 23020a96aa3bSJed Brown PetscInt numCells = recv[2*(p-startC)+1]; 23030a96aa3bSJed Brown PetscInt off, i; 23040a96aa3bSJed Brown 23059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section,p,&off)); 23060a96aa3bSJed Brown for (i = 0; i < numCells; i++) { 23070a96aa3bSJed Brown leaves[off+i].rank = p; 23080a96aa3bSJed Brown leaves[off+i].index = firstCell + i; 23090a96aa3bSJed Brown } 23100a96aa3bSJed Brown } 23119566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&sf)); 23129566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf,cEnd-cStart,nLeaves,NULL,PETSC_OWN_POINTER,leaves,PETSC_OWN_POINTER)); 23139566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 23149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endF-startF),sendReqs,MPI_STATUSES_IGNORE)); 23159566063dSJacob Faibussowitsch PetscCall(PetscFree2(send,sendReqs)); 23169566063dSJacob Faibussowitsch PetscCall(PetscFree2(recv,recvReqs)); 23170a96aa3bSJed Brown *coveringSF = sf; 23180a96aa3bSJed Brown PetscFunctionReturn(0); 23190a96aa3bSJed Brown } 23200a96aa3bSJed Brown 23210a96aa3bSJed Brown /* closure points for locally-owned cells */ 23220a96aa3bSJed Brown static PetscErrorCode DMPforestGetCellSFNodes(DM dm, PetscInt numClosureIndices, PetscInt *numClosurePoints, PetscSFNode **closurePoints,PetscBool redirect) 23230a96aa3bSJed Brown { 23240a96aa3bSJed Brown PetscInt cStart, cEnd; 23250a96aa3bSJed Brown PetscInt count, c; 23260a96aa3bSJed Brown PetscMPIInt rank; 23270a96aa3bSJed Brown PetscInt closureSize = -1; 23280a96aa3bSJed Brown PetscInt *closure = NULL; 23290a96aa3bSJed Brown PetscSF pointSF; 23300a96aa3bSJed Brown PetscInt nleaves, nroots; 23310a96aa3bSJed Brown const PetscInt *ilocal; 23320a96aa3bSJed Brown const PetscSFNode *iremote; 23330a96aa3bSJed Brown DM plex; 23340a96aa3bSJed Brown DM_Forest *forest; 23350a96aa3bSJed Brown DM_Forest_pforest *pforest; 23360a96aa3bSJed Brown 23370a96aa3bSJed Brown PetscFunctionBegin; 23380a96aa3bSJed Brown forest = (DM_Forest *) dm->data; 23390a96aa3bSJed Brown pforest = (DM_Forest_pforest *) forest->data; 23400a96aa3bSJed Brown cStart = pforest->cLocalStart; 23410a96aa3bSJed Brown cEnd = pforest->cLocalEnd; 23429566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 23439566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm,&pointSF)); 23449566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF,&nroots,&nleaves,&ilocal,&iremote)); 23450a96aa3bSJed Brown nleaves = PetscMax(0,nleaves); 23460a96aa3bSJed Brown nroots = PetscMax(0,nroots); 23470a96aa3bSJed Brown *numClosurePoints = numClosureIndices * (cEnd - cStart); 23489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numClosurePoints,closurePoints)); 23499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank)); 23500a96aa3bSJed Brown for (c = cStart, count = 0; c < cEnd; c++) { 23510a96aa3bSJed Brown PetscInt i; 23529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,c,PETSC_TRUE,&closureSize,&closure)); 23530a96aa3bSJed Brown 23540a96aa3bSJed Brown for (i = 0; i < numClosureIndices; i++, count++) { 23550a96aa3bSJed Brown PetscInt p = closure[2 * i]; 23560a96aa3bSJed Brown PetscInt loc = -1; 23570a96aa3bSJed Brown 23589566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p,nleaves,ilocal,&loc)); 23590a96aa3bSJed Brown if (redirect && loc >= 0) { 23600a96aa3bSJed Brown (*closurePoints)[count].rank = iremote[loc].rank; 23610a96aa3bSJed Brown (*closurePoints)[count].index = iremote[loc].index; 23620a96aa3bSJed Brown } else { 23630a96aa3bSJed Brown (*closurePoints)[count].rank = rank; 23640a96aa3bSJed Brown (*closurePoints)[count].index = p; 23650a96aa3bSJed Brown } 23660a96aa3bSJed Brown } 23679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,c,PETSC_TRUE,&closureSize,&closure)); 23680a96aa3bSJed Brown } 23690a96aa3bSJed Brown PetscFunctionReturn(0); 23700a96aa3bSJed Brown } 23710a96aa3bSJed Brown 23720a96aa3bSJed Brown static void MPIAPI DMPforestMaxSFNode(void *a, void *b, PetscMPIInt *len, MPI_Datatype *type) 23730a96aa3bSJed Brown { 23740a96aa3bSJed Brown PetscMPIInt i; 23750a96aa3bSJed Brown 23760a96aa3bSJed Brown for (i = 0; i < *len; i++) { 23770a96aa3bSJed Brown PetscSFNode *A = (PetscSFNode*)a; 23780a96aa3bSJed Brown PetscSFNode *B = (PetscSFNode*)b; 23790a96aa3bSJed Brown 23800a96aa3bSJed Brown if (B->rank < 0) *B = *A; 23810a96aa3bSJed Brown } 23820a96aa3bSJed Brown } 23830a96aa3bSJed Brown 23840a96aa3bSJed Brown static PetscErrorCode DMPforestGetTransferSF_Point(DM coarse, DM fine, PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 23850a96aa3bSJed Brown { 23860a96aa3bSJed Brown MPI_Comm comm; 23870a96aa3bSJed Brown PetscMPIInt rank, size; 23880a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 23890a96aa3bSJed Brown p4est_t *p4estC, *p4estF; 23900a96aa3bSJed Brown PetscInt numClosureIndices; 23910a96aa3bSJed Brown PetscInt numClosurePointsC, numClosurePointsF; 23920a96aa3bSJed Brown PetscSFNode *closurePointsC, *closurePointsF; 23930a96aa3bSJed Brown p4est_quadrant_t *coverQuads = NULL; 23940a96aa3bSJed Brown p4est_quadrant_t **treeQuads; 23950a96aa3bSJed Brown PetscInt *treeQuadCounts; 23960a96aa3bSJed Brown MPI_Datatype nodeType; 23970a96aa3bSJed Brown MPI_Datatype nodeClosureType; 23980a96aa3bSJed Brown MPI_Op sfNodeReduce; 23990a96aa3bSJed Brown p4est_topidx_t fltF, lltF, t; 24000a96aa3bSJed Brown DM plexC, plexF; 24010a96aa3bSJed Brown PetscInt pStartF, pEndF, pStartC, pEndC; 24020a96aa3bSJed Brown PetscBool saveInCoarse = PETSC_FALSE; 24030a96aa3bSJed Brown PetscBool saveInFine = PETSC_FALSE; 24040a96aa3bSJed Brown PetscBool formCids = (childIds != NULL) ? PETSC_TRUE : PETSC_FALSE; 24050a96aa3bSJed Brown PetscInt *cids = NULL; 24060a96aa3bSJed Brown 24070a96aa3bSJed Brown PetscFunctionBegin; 24080a96aa3bSJed Brown pforestC = (DM_Forest_pforest*) ((DM_Forest*) coarse->data)->data; 24090a96aa3bSJed Brown pforestF = (DM_Forest_pforest*) ((DM_Forest*) fine->data)->data; 24100a96aa3bSJed Brown p4estC = pforestC->forest; 24110a96aa3bSJed Brown p4estF = pforestF->forest; 241208401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo,PetscObjectComm((PetscObject)coarse),PETSC_ERR_ARG_INCOMP,"DM's must have the same base DM"); 24130a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 24149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 24159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 24169566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine,&plexF)); 24179566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF,&pStartF,&pEndF)); 24189566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse,&plexC)); 24199566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC,&pStartC,&pEndC)); 24200a96aa3bSJed Brown { /* check if the results have been cached */ 24210a96aa3bSJed Brown DM adaptCoarse, adaptFine; 24220a96aa3bSJed Brown 24239566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(coarse,&adaptCoarse)); 24249566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(fine,&adaptFine)); 24250a96aa3bSJed Brown if (adaptCoarse && adaptCoarse->data == fine->data) { /* coarse is adapted from fine */ 24260a96aa3bSJed Brown if (pforestC->pointSelfToAdaptSF) { 24279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(pforestC->pointSelfToAdaptSF))); 24280a96aa3bSJed Brown *sf = pforestC->pointSelfToAdaptSF; 24290a96aa3bSJed Brown if (childIds) { 24309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&cids)); 24319566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids,pforestC->pointSelfToAdaptCids,pEndF-pStartF)); 24320a96aa3bSJed Brown *childIds = cids; 24330a96aa3bSJed Brown } 24340a96aa3bSJed Brown PetscFunctionReturn(0); 24350a96aa3bSJed Brown } else { 24360a96aa3bSJed Brown saveInCoarse = PETSC_TRUE; 24370a96aa3bSJed Brown formCids = PETSC_TRUE; 24380a96aa3bSJed Brown } 24390a96aa3bSJed Brown } else if (adaptFine && adaptFine->data == coarse->data) { /* fine is adapted from coarse */ 24400a96aa3bSJed Brown if (pforestF->pointAdaptToSelfSF) { 24419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)(pforestF->pointAdaptToSelfSF))); 24420a96aa3bSJed Brown *sf = pforestF->pointAdaptToSelfSF; 24430a96aa3bSJed Brown if (childIds) { 24449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&cids)); 24459566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids,pforestF->pointAdaptToSelfCids,pEndF-pStartF)); 24460a96aa3bSJed Brown *childIds = cids; 24470a96aa3bSJed Brown } 24480a96aa3bSJed Brown PetscFunctionReturn(0); 24490a96aa3bSJed Brown } else { 24500a96aa3bSJed Brown saveInFine = PETSC_TRUE; 24510a96aa3bSJed Brown formCids = PETSC_TRUE; 24520a96aa3bSJed Brown } 24530a96aa3bSJed Brown } 24540a96aa3bSJed Brown } 24550a96aa3bSJed Brown 24560a96aa3bSJed Brown /* count the number of closure points that have dofs and create a list */ 24570a96aa3bSJed Brown numClosureIndices = P4EST_INSUL; 24580a96aa3bSJed Brown /* create the datatype */ 24599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(2,MPIU_INT,&nodeType)); 24609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 24619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(DMPforestMaxSFNode,PETSC_FALSE,&sfNodeReduce)); 24629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(numClosureIndices*2,MPIU_INT,&nodeClosureType)); 24639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeClosureType)); 24640a96aa3bSJed Brown /* everything has to go through cells: for each cell, create a list of the sfnodes in its closure */ 24650a96aa3bSJed Brown /* get lists of closure point SF nodes for every cell */ 24669566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(coarse,numClosureIndices,&numClosurePointsC,&closurePointsC,PETSC_TRUE)); 24679566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(fine ,numClosureIndices,&numClosurePointsF,&closurePointsF,PETSC_FALSE)); 24680a96aa3bSJed Brown /* create pointers for tree lists */ 24690a96aa3bSJed Brown fltF = p4estF->first_local_tree; 24700a96aa3bSJed Brown lltF = p4estF->last_local_tree; 24719566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(lltF + 1 - fltF, &treeQuads, lltF + 1 - fltF, &treeQuadCounts)); 24720a96aa3bSJed Brown /* if the partitions don't match, ship the coarse to cover the fine */ 24730a96aa3bSJed Brown if (size > 1) { 24740a96aa3bSJed Brown PetscInt p; 24750a96aa3bSJed Brown 24760a96aa3bSJed Brown for (p = 0; p < size; p++) { 24770a96aa3bSJed Brown int equal; 24780a96aa3bSJed Brown 24790a96aa3bSJed Brown PetscStackCallP4estReturn(equal,p4est_quadrant_is_equal_piggy,(&p4estC->global_first_position[p],&p4estF->global_first_position[p])); 24800a96aa3bSJed Brown if (!equal) break; 24810a96aa3bSJed Brown } 24820a96aa3bSJed Brown if (p < size) { /* non-matching distribution: send the coarse to cover the fine */ 24830a96aa3bSJed Brown PetscInt cStartC, cEndC; 24840a96aa3bSJed Brown PetscSF coveringSF; 24850a96aa3bSJed Brown PetscInt nleaves; 24860a96aa3bSJed Brown PetscInt count; 24870a96aa3bSJed Brown PetscSFNode *newClosurePointsC; 24880a96aa3bSJed Brown p4est_quadrant_t *coverQuadsSend; 24890a96aa3bSJed Brown p4est_topidx_t fltC = p4estC->first_local_tree; 24900a96aa3bSJed Brown p4est_topidx_t lltC = p4estC->last_local_tree; 24910a96aa3bSJed Brown p4est_topidx_t t; 24920a96aa3bSJed Brown PetscMPIInt blockSizes[4] = {P4EST_DIM,2,1,1}; 24930a96aa3bSJed Brown MPI_Aint blockOffsets[4] = {offsetof(p4est_quadrant_t,x), 24940a96aa3bSJed Brown offsetof(p4est_quadrant_t,level), 24950a96aa3bSJed Brown offsetof(p4est_quadrant_t,pad16), 24960a96aa3bSJed Brown offsetof(p4est_quadrant_t,p)}; 24970a96aa3bSJed Brown MPI_Datatype blockTypes[4] = {MPI_INT32_T,MPI_INT8_T,MPI_INT16_T,MPI_INT32_T/* p.which_tree */}; 24980a96aa3bSJed Brown MPI_Datatype quadStruct,quadType; 24990a96aa3bSJed Brown 25009566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC,0,&cStartC,&cEndC)); 25019566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellCoveringSF(comm,p4estC,p4estF,pforestC->cLocalStart,pforestC->cLocalEnd,&coveringSF)); 25029566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coveringSF,NULL,&nleaves,NULL,NULL)); 25039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numClosureIndices*nleaves,&newClosurePointsC)); 25049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves,&coverQuads)); 25059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEndC-cStartC,&coverQuadsSend)); 25060a96aa3bSJed Brown count = 0; 25070a96aa3bSJed Brown for (t = fltC; t <= lltC; t++) { /* unfortunately, we need to pack a send array, since quads are not stored packed in p4est */ 25080a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4estC->trees->array)[t]); 25090a96aa3bSJed Brown PetscInt q; 25100a96aa3bSJed Brown 25119566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&coverQuadsSend[count],tree->quadrants.array,tree->quadrants.elem_count * sizeof(p4est_quadrant_t))); 25120a96aa3bSJed Brown for (q = 0; (size_t) q < tree->quadrants.elem_count; q++) coverQuadsSend[count+q].p.which_tree = t; 25130a96aa3bSJed Brown count += tree->quadrants.elem_count; 25140a96aa3bSJed Brown } 25150a96aa3bSJed Brown /* p is of a union type p4est_quadrant_data, but only the p.which_tree field is active at this time. So, we 25160a96aa3bSJed Brown have a simple blockTypes[] to use. Note that quadStruct does not count potential padding in array of 25170a96aa3bSJed Brown p4est_quadrant_t. We have to call MPI_Type_create_resized() to change upper-bound of quadStruct. 25180a96aa3bSJed Brown */ 25199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(4,blockSizes,blockOffsets,blockTypes,&quadStruct)); 25209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_resized(quadStruct,0,sizeof(p4est_quadrant_t),&quadType)); 25219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&quadType)); 25229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF,nodeClosureType,closurePointsC,newClosurePointsC,MPI_REPLACE)); 25239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF,quadType,coverQuadsSend,coverQuads,MPI_REPLACE)); 25249566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF,nodeClosureType,closurePointsC,newClosurePointsC,MPI_REPLACE)); 25259566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF,quadType,coverQuadsSend,coverQuads,MPI_REPLACE)); 25269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadStruct)); 25279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadType)); 25289566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuadsSend)); 25299566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 25309566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coveringSF)); 25310a96aa3bSJed Brown closurePointsC = newClosurePointsC; 25320a96aa3bSJed Brown 25330a96aa3bSJed Brown /* assign tree quads based on locations in coverQuads */ 25340a96aa3bSJed Brown { 25350a96aa3bSJed Brown PetscInt q; 25360a96aa3bSJed Brown for (q = 0; q < nleaves; q++) { 25370a96aa3bSJed Brown p4est_locidx_t t = coverQuads[q].p.which_tree; 25380a96aa3bSJed Brown if (!treeQuadCounts[t-fltF]++) treeQuads[t-fltF] = &coverQuads[q]; 25390a96aa3bSJed Brown } 25400a96aa3bSJed Brown } 25410a96aa3bSJed Brown } 25420a96aa3bSJed Brown } 25430a96aa3bSJed Brown if (!coverQuads) { /* matching partitions: assign tree quads based on locations in p4est native arrays */ 25440a96aa3bSJed Brown for (t = fltF; t <= lltF; t++) { 25450a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4estC->trees->array)[t]); 25460a96aa3bSJed Brown 25470a96aa3bSJed Brown treeQuadCounts[t - fltF] = tree->quadrants.elem_count; 25480a96aa3bSJed Brown treeQuads[t - fltF] = (p4est_quadrant_t*) tree->quadrants.array; 25490a96aa3bSJed Brown } 25500a96aa3bSJed Brown } 25510a96aa3bSJed Brown 25520a96aa3bSJed Brown { 25530a96aa3bSJed Brown PetscInt p; 25540a96aa3bSJed Brown PetscInt cLocalStartF; 25550a96aa3bSJed Brown PetscSF pointSF; 25560a96aa3bSJed Brown PetscSFNode *roots; 25570a96aa3bSJed Brown PetscInt *rootType; 25580a96aa3bSJed Brown DM refTree = NULL; 25590a96aa3bSJed Brown DMLabel canonical; 25600a96aa3bSJed Brown PetscInt *childClosures[P4EST_CHILDREN] = {NULL}; 25610a96aa3bSJed Brown PetscInt *rootClosure = NULL; 25620a96aa3bSJed Brown PetscInt coarseOffset; 25630a96aa3bSJed Brown PetscInt numCoarseQuads; 25640a96aa3bSJed Brown 25659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&roots)); 25669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&rootType)); 25679566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(fine,&pointSF)); 25680a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 25690a96aa3bSJed Brown roots[p-pStartF].rank = -1; 25700a96aa3bSJed Brown roots[p-pStartF].index = -1; 25710a96aa3bSJed Brown rootType[p-pStartF] = -1; 25720a96aa3bSJed Brown } 25730a96aa3bSJed Brown if (formCids) { 25740a96aa3bSJed Brown PetscInt child; 25750a96aa3bSJed Brown 25769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&cids)); 25770a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) cids[p - pStartF] = -2; 25789566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF,&refTree)); 25799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree,0,PETSC_TRUE,NULL,&rootClosure)); 25800a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { /* get the closures of the child cells in the reference tree */ 25819566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree,child+1,PETSC_TRUE,NULL,&childClosures[child])); 25820a96aa3bSJed Brown } 25839566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree,"canonical",&canonical)); 25840a96aa3bSJed Brown } 25850a96aa3bSJed Brown cLocalStartF = pforestF->cLocalStart; 25860a96aa3bSJed Brown for (t = fltF, coarseOffset = 0, numCoarseQuads = 0; t <= lltF; t++, coarseOffset += numCoarseQuads) { 25870a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4estF->trees->array)[t]); 25880a96aa3bSJed Brown PetscInt numFineQuads = tree->quadrants.elem_count; 25890a96aa3bSJed Brown p4est_quadrant_t *coarseQuads = treeQuads[t - fltF]; 25900a96aa3bSJed Brown p4est_quadrant_t *fineQuads = (p4est_quadrant_t*) tree->quadrants.array; 25910a96aa3bSJed Brown PetscInt i, coarseCount = 0; 25920a96aa3bSJed Brown PetscInt offset = tree->quadrants_offset; 25930a96aa3bSJed Brown sc_array_t coarseQuadsArray; 25940a96aa3bSJed Brown 25950a96aa3bSJed Brown numCoarseQuads = treeQuadCounts[t - fltF]; 25960a96aa3bSJed Brown PetscStackCallP4est(sc_array_init_data,(&coarseQuadsArray,coarseQuads,sizeof(p4est_quadrant_t),(size_t) numCoarseQuads)); 25970a96aa3bSJed Brown for (i = 0; i < numFineQuads; i++) { 25980a96aa3bSJed Brown PetscInt c = i + offset; 25990a96aa3bSJed Brown p4est_quadrant_t *quad = &fineQuads[i]; 26000a96aa3bSJed Brown p4est_quadrant_t *quadCoarse = NULL; 26010a96aa3bSJed Brown ssize_t disjoint = -1; 26020a96aa3bSJed Brown 26030a96aa3bSJed Brown while (disjoint < 0 && coarseCount < numCoarseQuads) { 26040a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 26050a96aa3bSJed Brown PetscStackCallP4estReturn(disjoint,p4est_quadrant_disjoint,(quadCoarse,quad)); 26060a96aa3bSJed Brown if (disjoint < 0) coarseCount++; 26070a96aa3bSJed Brown } 260808401ef6SPierre Jolivet PetscCheck(disjoint == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"did not find overlapping coarse quad"); 26090a96aa3bSJed Brown if (quadCoarse->level > quad->level || (quadCoarse->level == quad->level && !transferIdent)) { /* the "coarse" mesh is finer than the fine mesh at the point: continue */ 26100a96aa3bSJed Brown if (transferIdent) { /* find corners */ 26110a96aa3bSJed Brown PetscInt j = 0; 26120a96aa3bSJed Brown 26130a96aa3bSJed Brown do { 26140a96aa3bSJed Brown if (j < P4EST_CHILDREN) { 26150a96aa3bSJed Brown p4est_quadrant_t cornerQuad; 26160a96aa3bSJed Brown int equal; 26170a96aa3bSJed Brown 26180a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_corner_descendant,(quad,&cornerQuad,j,quadCoarse->level)); 26190a96aa3bSJed Brown PetscStackCallP4estReturn(equal,p4est_quadrant_is_equal,(&cornerQuad,quadCoarse)); 26200a96aa3bSJed Brown if (equal) { 26210a96aa3bSJed Brown PetscInt petscJ = P4estVertToPetscVert[j]; 26220a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + (P4EST_INSUL - P4EST_CHILDREN) + petscJ].index; 26230a96aa3bSJed Brown PetscSFNode q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + (P4EST_INSUL - P4EST_CHILDREN) + petscJ]; 26240a96aa3bSJed Brown 26250a96aa3bSJed Brown roots[p-pStartF] = q; 26260a96aa3bSJed Brown rootType[p-pStartF] = PETSC_MAX_INT; 26270a96aa3bSJed Brown cids[p-pStartF] = -1; 26280a96aa3bSJed Brown j++; 26290a96aa3bSJed Brown } 26300a96aa3bSJed Brown } 26310a96aa3bSJed Brown coarseCount++; 26320a96aa3bSJed Brown disjoint = 1; 26330a96aa3bSJed Brown if (coarseCount < numCoarseQuads) { 26340a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 26350a96aa3bSJed Brown PetscStackCallP4estReturn(disjoint,p4est_quadrant_disjoint,(quadCoarse,quad)); 26360a96aa3bSJed Brown } 26370a96aa3bSJed Brown } while (!disjoint); 26380a96aa3bSJed Brown } 26390a96aa3bSJed Brown continue; 26400a96aa3bSJed Brown } 26410a96aa3bSJed Brown if (quadCoarse->level == quad->level) { /* same quad present in coarse and fine mesh */ 26420a96aa3bSJed Brown PetscInt j; 26430a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 26440a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + j].index; 26450a96aa3bSJed Brown 26460a96aa3bSJed Brown roots[p-pStartF] = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + j]; 26470a96aa3bSJed Brown rootType[p-pStartF] = PETSC_MAX_INT; /* unconditionally accept */ 26480a96aa3bSJed Brown cids[p-pStartF] = -1; 26490a96aa3bSJed Brown } 26500a96aa3bSJed Brown } else { 26510a96aa3bSJed Brown PetscInt levelDiff = quad->level - quadCoarse->level; 26520a96aa3bSJed Brown PetscInt proposedCids[P4EST_INSUL] = {0}; 26530a96aa3bSJed Brown 26540a96aa3bSJed Brown if (formCids) { 26550a96aa3bSJed Brown PetscInt cl; 26560a96aa3bSJed Brown PetscInt *pointClosure = NULL; 26570a96aa3bSJed Brown int cid; 26580a96aa3bSJed Brown 265908401ef6SPierre Jolivet PetscCheck(levelDiff <= 1,PETSC_COMM_SELF,PETSC_ERR_USER,"Recursive child ids not implemented"); 26600a96aa3bSJed Brown PetscStackCallP4estReturn(cid,p4est_quadrant_child_id,(quad)); 26619566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plexF,c + cLocalStartF,PETSC_TRUE,NULL,&pointClosure)); 26620a96aa3bSJed Brown for (cl = 0; cl < P4EST_INSUL; cl++) { 26630a96aa3bSJed Brown PetscInt p = pointClosure[2 * cl]; 26640a96aa3bSJed Brown PetscInt point = childClosures[cid][2 * cl]; 26650a96aa3bSJed Brown PetscInt ornt = childClosures[cid][2 * cl + 1]; 26660a96aa3bSJed Brown PetscInt newcid = -1; 26670a96aa3bSJed Brown DMPolytopeType ct; 26680a96aa3bSJed Brown 26690a96aa3bSJed Brown if (rootType[p-pStartF] == PETSC_MAX_INT) continue; 26709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, point, &ct)); 26710a96aa3bSJed Brown ornt = DMPolytopeConvertNewOrientation_Internal(ct, ornt); 26720a96aa3bSJed Brown if (!cl) { 26730a96aa3bSJed Brown newcid = cid + 1; 26740a96aa3bSJed Brown } else { 26750a96aa3bSJed Brown PetscInt rcl, parent, parentOrnt = 0; 26760a96aa3bSJed Brown 26779566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree,point,&parent,NULL)); 26780a96aa3bSJed Brown if (parent == point) { 26790a96aa3bSJed Brown newcid = -1; 26800a96aa3bSJed Brown } else if (!parent) { /* in the root */ 26810a96aa3bSJed Brown newcid = point; 26820a96aa3bSJed Brown } else { 26830a96aa3bSJed Brown DMPolytopeType rct = DM_POLYTOPE_UNKNOWN; 26840a96aa3bSJed Brown 26850a96aa3bSJed Brown for (rcl = 1; rcl < P4EST_INSUL; rcl++) { 26860a96aa3bSJed Brown if (rootClosure[2 * rcl] == parent) { 26879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, parent, &rct)); 26880a96aa3bSJed Brown parentOrnt = DMPolytopeConvertNewOrientation_Internal(rct, rootClosure[2 * rcl + 1]); 26890a96aa3bSJed Brown break; 26900a96aa3bSJed Brown } 26910a96aa3bSJed Brown } 269208401ef6SPierre Jolivet PetscCheck(rcl < P4EST_INSUL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Couldn't find parent in root closure"); 26939566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(refTree,parent,parentOrnt,ornt,point,DMPolytopeConvertNewOrientation_Internal(rct, pointClosure[2 * rcl + 1]),NULL,&newcid)); 26940a96aa3bSJed Brown } 26950a96aa3bSJed Brown } 26960a96aa3bSJed Brown if (newcid >= 0) { 26970a96aa3bSJed Brown 26980a96aa3bSJed Brown if (canonical) { 26999566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical,newcid,&newcid)); 27000a96aa3bSJed Brown } 27010a96aa3bSJed Brown proposedCids[cl] = newcid; 27020a96aa3bSJed Brown } 27030a96aa3bSJed Brown } 27049566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plexF,c + cLocalStartF,PETSC_TRUE,NULL,&pointClosure)); 27050a96aa3bSJed Brown } 27060a96aa3bSJed Brown p4est_qcoord_t coarseBound[2][P4EST_DIM] = {{quadCoarse->x,quadCoarse->y, 27070a96aa3bSJed Brown #if defined(P4_TO_P8) 27080a96aa3bSJed Brown quadCoarse->z 27090a96aa3bSJed Brown #endif 27100a96aa3bSJed Brown },{0}}; 27110a96aa3bSJed Brown p4est_qcoord_t fineBound[2][P4EST_DIM] = {{quad->x,quad->y, 27120a96aa3bSJed Brown #if defined(P4_TO_P8) 27130a96aa3bSJed Brown quad->z 27140a96aa3bSJed Brown #endif 27150a96aa3bSJed Brown },{0}}; 27160a96aa3bSJed Brown PetscInt j; 27170a96aa3bSJed Brown for (j = 0; j < P4EST_DIM; j++) { /* get the coordinates of cell boundaries in each direction */ 27180a96aa3bSJed Brown coarseBound[1][j] = coarseBound[0][j] + P4EST_QUADRANT_LEN(quadCoarse->level); 27190a96aa3bSJed Brown fineBound[1][j] = fineBound[0][j] + P4EST_QUADRANT_LEN(quad->level); 27200a96aa3bSJed Brown } 27210a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 27220a96aa3bSJed Brown PetscInt l, p; 27230a96aa3bSJed Brown PetscSFNode q; 27240a96aa3bSJed Brown 27250a96aa3bSJed Brown p = closurePointsF[numClosureIndices * c + j].index; 27260a96aa3bSJed Brown if (rootType[p-pStartF] == PETSC_MAX_INT) continue; 27270a96aa3bSJed Brown if (j == 0) { /* volume: ancestor is volume */ 27280a96aa3bSJed Brown l = 0; 27290a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES) { /* facet */ 27300a96aa3bSJed Brown PetscInt face = PetscFaceToP4estFace[j - 1]; 27310a96aa3bSJed Brown PetscInt direction = face / 2; 27320a96aa3bSJed Brown PetscInt coarseFace = -1; 27330a96aa3bSJed Brown 27340a96aa3bSJed Brown if (coarseBound[face % 2][direction] == fineBound[face % 2][direction]) { 27350a96aa3bSJed Brown coarseFace = face; 27360a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27370a96aa3bSJed Brown } else { 27380a96aa3bSJed Brown l = 0; 27390a96aa3bSJed Brown } 27400a96aa3bSJed Brown #if defined(P4_TO_P8) 27410a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES + P8EST_EDGES) { 27420a96aa3bSJed Brown PetscInt edge = PetscEdgeToP4estEdge[j - (1 + P4EST_FACES)]; 27430a96aa3bSJed Brown PetscInt direction = edge / 4; 27440a96aa3bSJed Brown PetscInt mod = edge % 4; 27450a96aa3bSJed Brown PetscInt coarseEdge = -1, coarseFace = -1; 27460a96aa3bSJed Brown PetscInt minDir = PetscMin((direction + 1) % 3,(direction + 2) % 3); 27470a96aa3bSJed Brown PetscInt maxDir = PetscMax((direction + 1) % 3,(direction + 2) % 3); 27480a96aa3bSJed Brown PetscBool dirTest[2]; 27490a96aa3bSJed Brown 27500a96aa3bSJed Brown dirTest[0] = (PetscBool) (coarseBound[mod % 2][minDir] == fineBound[mod % 2][minDir]); 27510a96aa3bSJed Brown dirTest[1] = (PetscBool) (coarseBound[mod / 2][maxDir] == fineBound[mod / 2][maxDir]); 27520a96aa3bSJed Brown 27530a96aa3bSJed Brown if (dirTest[0] && dirTest[1]) { /* fine edge falls on coarse edge */ 27540a96aa3bSJed Brown coarseEdge = edge; 27550a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 27560a96aa3bSJed Brown } else if (dirTest[0]) { /* fine edge falls on a coarse face in the minDir direction */ 27570a96aa3bSJed Brown coarseFace = 2 * minDir + (mod % 2); 27580a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27590a96aa3bSJed Brown } else if (dirTest[1]) { /* fine edge falls on a coarse face in the maxDir direction */ 27600a96aa3bSJed Brown coarseFace = 2 * maxDir + (mod / 2); 27610a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27620a96aa3bSJed Brown } else { 27630a96aa3bSJed Brown l = 0; 27640a96aa3bSJed Brown } 27650a96aa3bSJed Brown #endif 27660a96aa3bSJed Brown } else { 27670a96aa3bSJed Brown PetscInt vertex = PetscVertToP4estVert[P4EST_CHILDREN - (P4EST_INSUL - j)]; 27680a96aa3bSJed Brown PetscBool dirTest[P4EST_DIM]; 27690a96aa3bSJed Brown PetscInt m; 27700a96aa3bSJed Brown PetscInt numMatch = 0; 27710a96aa3bSJed Brown PetscInt coarseVertex = -1, coarseFace = -1; 27720a96aa3bSJed Brown #if defined(P4_TO_P8) 27730a96aa3bSJed Brown PetscInt coarseEdge = -1; 27740a96aa3bSJed Brown #endif 27750a96aa3bSJed Brown 27760a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27770a96aa3bSJed Brown dirTest[m] = (PetscBool) (coarseBound[(vertex >> m) & 1][m] == fineBound[(vertex >> m) & 1][m]); 27780a96aa3bSJed Brown if (dirTest[m]) numMatch++; 27790a96aa3bSJed Brown } 27800a96aa3bSJed Brown if (numMatch == P4EST_DIM) { /* vertex on vertex */ 27810a96aa3bSJed Brown coarseVertex = vertex; 27820a96aa3bSJed Brown l = P4EST_INSUL - (P4EST_CHILDREN - P4estVertToPetscVert[coarseVertex]); 27830a96aa3bSJed Brown } else if (numMatch == 1) { /* vertex on face */ 27840a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27850a96aa3bSJed Brown if (dirTest[m]) { 27860a96aa3bSJed Brown coarseFace = 2 * m + ((vertex >> m) & 1); 27870a96aa3bSJed Brown break; 27880a96aa3bSJed Brown } 27890a96aa3bSJed Brown } 27900a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 27910a96aa3bSJed Brown #if defined(P4_TO_P8) 27920a96aa3bSJed Brown } else if (numMatch == 2) { /* vertex on edge */ 27930a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 27940a96aa3bSJed Brown if (!dirTest[m]) { 27950a96aa3bSJed Brown PetscInt otherDir1 = (m + 1) % 3; 27960a96aa3bSJed Brown PetscInt otherDir2 = (m + 2) % 3; 27970a96aa3bSJed Brown PetscInt minDir = PetscMin(otherDir1,otherDir2); 27980a96aa3bSJed Brown PetscInt maxDir = PetscMax(otherDir1,otherDir2); 27990a96aa3bSJed Brown 28000a96aa3bSJed Brown coarseEdge = m * 4 + 2 * ((vertex >> maxDir) & 1) + ((vertex >> minDir) & 1); 28010a96aa3bSJed Brown break; 28020a96aa3bSJed Brown } 28030a96aa3bSJed Brown } 28040a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 28050a96aa3bSJed Brown #endif 28060a96aa3bSJed Brown } else { /* volume */ 28070a96aa3bSJed Brown l = 0; 28080a96aa3bSJed Brown } 28090a96aa3bSJed Brown } 28100a96aa3bSJed Brown q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + l]; 28110a96aa3bSJed Brown if (l > rootType[p-pStartF]) { 28120a96aa3bSJed Brown if (l >= P4EST_INSUL - P4EST_CHILDREN) { /* vertex on vertex: unconditional acceptance */ 28130a96aa3bSJed Brown if (transferIdent) { 28140a96aa3bSJed Brown roots[p-pStartF] = q; 28150a96aa3bSJed Brown rootType[p-pStartF] = PETSC_MAX_INT; 28160a96aa3bSJed Brown if (formCids) cids[p-pStartF] = -1; 28170a96aa3bSJed Brown } 28180a96aa3bSJed Brown } else { 28190a96aa3bSJed Brown PetscInt k, thisp = p, limit; 28200a96aa3bSJed Brown 28210a96aa3bSJed Brown roots[p-pStartF] = q; 28220a96aa3bSJed Brown rootType[p-pStartF] = l; 28230a96aa3bSJed Brown if (formCids) cids[p - pStartF] = proposedCids[j]; 28240a96aa3bSJed Brown limit = transferIdent ? levelDiff : (levelDiff - 1); 28250a96aa3bSJed Brown for (k = 0; k < limit; k++) { 28260a96aa3bSJed Brown PetscInt parent; 28270a96aa3bSJed Brown 28289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plexF,thisp,&parent,NULL)); 28290a96aa3bSJed Brown if (parent == thisp) break; 28300a96aa3bSJed Brown 28310a96aa3bSJed Brown roots[parent-pStartF] = q; 28320a96aa3bSJed Brown rootType[parent-pStartF] = PETSC_MAX_INT; 28330a96aa3bSJed Brown if (formCids) cids[parent-pStartF] = -1; 28340a96aa3bSJed Brown thisp = parent; 28350a96aa3bSJed Brown } 28360a96aa3bSJed Brown } 28370a96aa3bSJed Brown } 28380a96aa3bSJed Brown } 28390a96aa3bSJed Brown } 28400a96aa3bSJed Brown } 28410a96aa3bSJed Brown } 28420a96aa3bSJed Brown 28430a96aa3bSJed 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 */ 28440a96aa3bSJed Brown if (size > 1) { 28450a96aa3bSJed Brown PetscInt *rootTypeCopy, p; 28460a96aa3bSJed Brown 28479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&rootTypeCopy)); 28489566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(rootTypeCopy,rootType,pEndF-pStartF)); 28499566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPIU_MAX)); 28509566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPIU_MAX)); 28519566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPI_REPLACE)); 28529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPI_REPLACE)); 28530a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28540a96aa3bSJed 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 */ 28550a96aa3bSJed Brown roots[p-pStartF].rank = -1; 28560a96aa3bSJed Brown roots[p-pStartF].index = -1; 28570a96aa3bSJed Brown } 28580a96aa3bSJed Brown if (formCids && rootTypeCopy[p-pStartF] == PETSC_MAX_INT) { 28590a96aa3bSJed Brown cids[p-pStartF] = -1; /* we have found an antecedent that is the same: no child id */ 28600a96aa3bSJed Brown } 28610a96aa3bSJed Brown } 28629566063dSJacob Faibussowitsch PetscCall(PetscFree(rootTypeCopy)); 28639566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF,nodeType,roots,roots,sfNodeReduce)); 28649566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF,nodeType,roots,roots,sfNodeReduce)); 28659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF,nodeType,roots,roots,MPI_REPLACE)); 28669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF,nodeType,roots,roots,MPI_REPLACE)); 28670a96aa3bSJed Brown } 28689566063dSJacob Faibussowitsch PetscCall(PetscFree(rootType)); 28690a96aa3bSJed Brown 28700a96aa3bSJed Brown { 28710a96aa3bSJed Brown PetscInt numRoots; 28720a96aa3bSJed Brown PetscInt numLeaves; 28730a96aa3bSJed Brown PetscInt *leaves; 28740a96aa3bSJed Brown PetscSFNode *iremote; 28750a96aa3bSJed Brown /* count leaves */ 28760a96aa3bSJed Brown 28770a96aa3bSJed Brown numRoots = pEndC - pStartC; 28780a96aa3bSJed Brown 28790a96aa3bSJed Brown numLeaves = 0; 28800a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28810a96aa3bSJed Brown if (roots[p-pStartF].index >= 0) numLeaves++; 28820a96aa3bSJed Brown } 28839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves,&leaves)); 28849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves,&iremote)); 28850a96aa3bSJed Brown numLeaves = 0; 28860a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 28870a96aa3bSJed Brown if (roots[p-pStartF].index >= 0) { 28880a96aa3bSJed Brown leaves[numLeaves] = p-pStartF; 28890a96aa3bSJed Brown iremote[numLeaves] = roots[p-pStartF]; 28900a96aa3bSJed Brown numLeaves++; 28910a96aa3bSJed Brown } 28920a96aa3bSJed Brown } 28939566063dSJacob Faibussowitsch PetscCall(PetscFree(roots)); 28949566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,sf)); 28950a96aa3bSJed Brown if (numLeaves == (pEndF-pStartF)) { 28969566063dSJacob Faibussowitsch PetscCall(PetscFree(leaves)); 28979566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf,numRoots,numLeaves,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER)); 28980a96aa3bSJed Brown } else { 28999566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf,numRoots,numLeaves,leaves,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER)); 29000a96aa3bSJed Brown } 29010a96aa3bSJed Brown } 29020a96aa3bSJed Brown if (formCids) { 29030a96aa3bSJed Brown PetscSF pointSF; 29040a96aa3bSJed Brown PetscInt child; 29050a96aa3bSJed Brown 29069566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF,&refTree)); 29079566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plexF,&pointSF)); 29089566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF,MPIU_INT,cids,cids,MPIU_MAX)); 29099566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF,MPIU_INT,cids,cids,MPIU_MAX)); 29100a96aa3bSJed Brown if (childIds) *childIds = cids; 29110a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { 29129566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree,child+1,PETSC_TRUE,NULL,&childClosures[child])); 29130a96aa3bSJed Brown } 29149566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree,0,PETSC_TRUE,NULL,&rootClosure)); 29150a96aa3bSJed Brown } 29160a96aa3bSJed Brown } 29170a96aa3bSJed Brown if (saveInCoarse) { /* cache results */ 29189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 29190a96aa3bSJed Brown pforestC->pointSelfToAdaptSF = *sf; 29200a96aa3bSJed Brown if (!childIds) { 29210a96aa3bSJed Brown pforestC->pointSelfToAdaptCids = cids; 29220a96aa3bSJed Brown } else { 29239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&pforestC->pointSelfToAdaptCids)); 29249566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestC->pointSelfToAdaptCids,cids,pEndF-pStartF)); 29250a96aa3bSJed Brown } 29260a96aa3bSJed Brown } else if (saveInFine) { 29279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf)); 29280a96aa3bSJed Brown pforestF->pointAdaptToSelfSF = *sf; 29290a96aa3bSJed Brown if (!childIds) { 29300a96aa3bSJed Brown pforestF->pointAdaptToSelfCids = cids; 29310a96aa3bSJed Brown } else { 29329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&pforestF->pointAdaptToSelfCids)); 29339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestF->pointAdaptToSelfCids,cids,pEndF-pStartF)); 29340a96aa3bSJed Brown } 29350a96aa3bSJed Brown } 29369566063dSJacob Faibussowitsch PetscCall(PetscFree2(treeQuads,treeQuadCounts)); 29379566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuads)); 29389566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC)); 29399566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsF)); 29409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeClosureType)); 29419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&sfNodeReduce)); 29429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 29430a96aa3bSJed Brown PetscFunctionReturn(0); 29440a96aa3bSJed Brown } 29450a96aa3bSJed Brown 29460a96aa3bSJed Brown /* children are sf leaves of parents */ 29470a96aa3bSJed Brown static PetscErrorCode DMPforestGetTransferSF_Internal(DM coarse, DM fine, const PetscInt dofPerDim[], PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 29480a96aa3bSJed Brown { 29490a96aa3bSJed Brown MPI_Comm comm; 2950d70f29a3SPierre Jolivet PetscMPIInt rank; 29510a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 29520a96aa3bSJed Brown DM plexC, plexF; 29530a96aa3bSJed Brown PetscInt pStartC, pEndC, pStartF, pEndF; 29540a96aa3bSJed Brown PetscSF pointTransferSF; 29550a96aa3bSJed Brown PetscBool allOnes = PETSC_TRUE; 29560a96aa3bSJed Brown 29570a96aa3bSJed Brown PetscFunctionBegin; 29580a96aa3bSJed Brown pforestC = (DM_Forest_pforest*) ((DM_Forest*) coarse->data)->data; 29590a96aa3bSJed Brown pforestF = (DM_Forest_pforest*) ((DM_Forest*) fine->data)->data; 296008401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo,PetscObjectComm((PetscObject)coarse),PETSC_ERR_ARG_INCOMP,"DM's must have the same base DM"); 29610a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 29629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm,&rank)); 29630a96aa3bSJed Brown 29640a96aa3bSJed Brown { 29650a96aa3bSJed Brown PetscInt i; 29660a96aa3bSJed Brown for (i = 0; i <= P4EST_DIM; i++) { 29670a96aa3bSJed Brown if (dofPerDim[i] != 1) { 29680a96aa3bSJed Brown allOnes = PETSC_FALSE; 29690a96aa3bSJed Brown break; 29700a96aa3bSJed Brown } 29710a96aa3bSJed Brown } 29720a96aa3bSJed Brown } 29739566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Point(coarse,fine,&pointTransferSF,transferIdent,childIds)); 29740a96aa3bSJed Brown if (allOnes) { 29750a96aa3bSJed Brown *sf = pointTransferSF; 29760a96aa3bSJed Brown PetscFunctionReturn(0); 29770a96aa3bSJed Brown } 29780a96aa3bSJed Brown 29799566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine,&plexF)); 29809566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF,&pStartF,&pEndF)); 29819566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse,&plexC)); 29829566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC,&pStartC,&pEndC)); 29830a96aa3bSJed Brown { 29840a96aa3bSJed Brown PetscInt numRoots; 29850a96aa3bSJed Brown PetscInt numLeaves; 29860a96aa3bSJed Brown const PetscInt *leaves; 29870a96aa3bSJed Brown const PetscSFNode *iremote; 29880a96aa3bSJed Brown PetscInt d; 29890a96aa3bSJed Brown PetscSection leafSection, rootSection; 29900a96aa3bSJed Brown /* count leaves */ 29910a96aa3bSJed Brown 29929566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointTransferSF,&numRoots,&numLeaves,&leaves,&iremote)); 29939566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,&rootSection)); 29949566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF,&leafSection)); 29959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection,pStartC,pEndC)); 29969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafSection,pStartF,pEndF)); 29970a96aa3bSJed Brown 29980a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 29990a96aa3bSJed Brown PetscInt startC, endC, e; 30000a96aa3bSJed Brown 30019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC,P4EST_DIM-d,&startC,&endC)); 30020a96aa3bSJed Brown for (e = startC; e < endC; e++) { 30039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootSection,e,dofPerDim[d])); 30040a96aa3bSJed Brown } 30050a96aa3bSJed Brown } 30060a96aa3bSJed Brown 30070a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 30080a96aa3bSJed Brown PetscInt startF, endF, e; 30090a96aa3bSJed Brown 30109566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexF,P4EST_DIM-d,&startF,&endF)); 30110a96aa3bSJed Brown for (e = startF; e < endF; e++) { 30129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(leafSection,e,dofPerDim[d])); 30130a96aa3bSJed Brown } 30140a96aa3bSJed Brown } 30150a96aa3bSJed Brown 30169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection)); 30179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSection)); 30180a96aa3bSJed Brown { 30190a96aa3bSJed Brown PetscInt nroots, nleaves; 30200a96aa3bSJed Brown PetscInt *mine, i, p; 30210a96aa3bSJed Brown PetscInt *offsets, *offsetsRoot; 30220a96aa3bSJed Brown PetscSFNode *remote; 30230a96aa3bSJed Brown 30249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF-pStartF,&offsets)); 30259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC-pStartC,&offsetsRoot)); 30260a96aa3bSJed Brown for (p = pStartC; p < pEndC; p++) { 30279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootSection,p,&offsetsRoot[p-pStartC])); 30280a96aa3bSJed Brown } 30299566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointTransferSF,MPIU_INT,offsetsRoot,offsets,MPI_REPLACE)); 30309566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointTransferSF,MPIU_INT,offsetsRoot,offsets,MPI_REPLACE)); 30319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection,&nroots)); 30320a96aa3bSJed Brown nleaves = 0; 30330a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 30340a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 30350a96aa3bSJed Brown PetscInt dof; 30360a96aa3bSJed Brown 30379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection,leaf,&dof)); 30380a96aa3bSJed Brown nleaves += dof; 30390a96aa3bSJed Brown } 30409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves,&mine)); 30419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves,&remote)); 30420a96aa3bSJed Brown nleaves = 0; 30430a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 30440a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 30450a96aa3bSJed Brown PetscInt dof; 30460a96aa3bSJed Brown PetscInt off, j; 30470a96aa3bSJed Brown 30489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection,leaf,&dof)); 30499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection,leaf,&off)); 30500a96aa3bSJed Brown for (j = 0; j < dof; j++) { 30510a96aa3bSJed Brown remote[nleaves].rank = iremote[i].rank; 30520a96aa3bSJed Brown remote[nleaves].index = offsets[leaf] + j; 30530a96aa3bSJed Brown mine[nleaves++] = off + j; 30540a96aa3bSJed Brown } 30550a96aa3bSJed Brown } 30569566063dSJacob Faibussowitsch PetscCall(PetscFree(offsetsRoot)); 30579566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 30589566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,sf)); 30599566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf,nroots,nleaves,mine,PETSC_OWN_POINTER,remote,PETSC_OWN_POINTER)); 30600a96aa3bSJed Brown } 30619566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection)); 30629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection)); 30639566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointTransferSF)); 30640a96aa3bSJed Brown } 30650a96aa3bSJed Brown PetscFunctionReturn(0); 30660a96aa3bSJed Brown } 30670a96aa3bSJed Brown 30680a96aa3bSJed Brown static PetscErrorCode DMPforestGetTransferSF(DM dmA, DM dmB, const PetscInt dofPerDim[], PetscSF *sfAtoB, PetscSF *sfBtoA) 30690a96aa3bSJed Brown { 30700a96aa3bSJed Brown DM adaptA, adaptB; 30710a96aa3bSJed Brown DMAdaptFlag purpose; 30720a96aa3bSJed Brown 30730a96aa3bSJed Brown PetscFunctionBegin; 30749566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmA,&adaptA)); 30759566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmB,&adaptB)); 30760a96aa3bSJed Brown /* it is more efficient when the coarser mesh is the first argument: reorder if we know one is coarser than the other */ 30770a96aa3bSJed Brown if (adaptA && adaptA->data == dmB->data) { /* dmA was adapted from dmB */ 30789566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmA,&purpose)); 30790a96aa3bSJed Brown if (purpose == DM_ADAPT_REFINE) { 30809566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 30810a96aa3bSJed Brown PetscFunctionReturn(0); 30820a96aa3bSJed Brown } 30830a96aa3bSJed Brown } else if (adaptB && adaptB->data == dmA->data) { /* dmB was adapted from dmA */ 30849566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmB,&purpose)); 30850a96aa3bSJed Brown if (purpose == DM_ADAPT_COARSEN) { 30869566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB)); 30870a96aa3bSJed Brown PetscFunctionReturn(0); 30880a96aa3bSJed Brown } 30890a96aa3bSJed Brown } 30901baa6e33SBarry Smith if (sfAtoB) PetscCall(DMPforestGetTransferSF_Internal(dmA,dmB,dofPerDim,sfAtoB,PETSC_TRUE,NULL)); 30911baa6e33SBarry Smith if (sfBtoA) PetscCall(DMPforestGetTransferSF_Internal(dmB,dmA,dofPerDim,sfBtoA,(PetscBool) (sfAtoB == NULL),NULL)); 30920a96aa3bSJed Brown PetscFunctionReturn(0); 30930a96aa3bSJed Brown } 30940a96aa3bSJed Brown 30950a96aa3bSJed Brown static PetscErrorCode DMPforestLabelsInitialize(DM dm, DM plex) 30960a96aa3bSJed Brown { 30970a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 30980a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 30990a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, cStart, cEnd, fStart, fEnd, eStart, eEnd, vStart, vEnd; 31000a96aa3bSJed Brown PetscInt cStartBase, cEndBase, fStartBase, fEndBase, vStartBase, vEndBase, eStartBase, eEndBase; 31010a96aa3bSJed Brown PetscInt pStart, pEnd, pStartBase, pEndBase, p; 31020a96aa3bSJed Brown DM base; 31030a96aa3bSJed Brown PetscInt *star = NULL, starSize; 31040a96aa3bSJed Brown DMLabelLink next = dm->labels; 31050a96aa3bSJed Brown PetscInt guess = 0; 31060a96aa3bSJed Brown p4est_topidx_t num_trees = pforest->topo->conn->num_trees; 31070a96aa3bSJed Brown 31080a96aa3bSJed Brown PetscFunctionBegin; 31090a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 31100a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 31110a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 31129566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 31130a96aa3bSJed Brown if (!base) { 31140a96aa3bSJed Brown if (pforest->ghostName) { /* insert a label to make the boundaries, with stratum values denoting which face of the element touches the boundary */ 31150a96aa3bSJed Brown p4est_connectivity_t *conn = pforest->topo->conn; 31160a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 31170a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t*) p4est->trees->array; 31180a96aa3bSJed Brown p4est_topidx_t t, flt = p4est->first_local_tree; 31190a96aa3bSJed Brown p4est_topidx_t llt = pforest->forest->last_local_tree; 31200a96aa3bSJed Brown DMLabel ghostLabel; 31210a96aa3bSJed Brown PetscInt c; 31220a96aa3bSJed Brown 31239566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(plex,pforest->ghostName)); 31249566063dSJacob Faibussowitsch PetscCall(DMGetLabel(plex,pforest->ghostName,&ghostLabel)); 31250a96aa3bSJed Brown for (c = cLocalStart, t = flt; t <= llt; t++) { 31260a96aa3bSJed Brown p4est_tree_t *tree = &trees[t]; 31270a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t*) tree->quadrants.array; 31280a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 31290a96aa3bSJed Brown PetscInt q; 31300a96aa3bSJed Brown 31310a96aa3bSJed Brown for (q = 0; q < numQuads; q++, c++) { 31320a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[q]; 31330a96aa3bSJed Brown PetscInt f; 31340a96aa3bSJed Brown 31350a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++) { 31360a96aa3bSJed Brown p4est_quadrant_t neigh; 31370a96aa3bSJed Brown int isOutside; 31380a96aa3bSJed Brown 31390a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_face_neighbor,(quad,f,&neigh)); 31400a96aa3bSJed Brown PetscStackCallP4estReturn(isOutside,p4est_quadrant_is_outside_face,(&neigh)); 31410a96aa3bSJed Brown if (isOutside) { 31420a96aa3bSJed Brown p4est_topidx_t nt; 31430a96aa3bSJed Brown PetscInt nf; 31440a96aa3bSJed Brown 31450a96aa3bSJed Brown nt = conn->tree_to_tree[t * P4EST_FACES + f]; 31460a96aa3bSJed Brown nf = (PetscInt) conn->tree_to_face[t * P4EST_FACES + f]; 31470a96aa3bSJed Brown nf = nf % P4EST_FACES; 31480a96aa3bSJed Brown if (nt == t && nf == f) { 31490a96aa3bSJed Brown PetscInt plexF = P4estFaceToPetscFace[f]; 31500a96aa3bSJed Brown const PetscInt *cone; 31510a96aa3bSJed Brown 31529566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(plex,c,&cone)); 31539566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ghostLabel,cone[plexF],plexF+1)); 31540a96aa3bSJed Brown } 31550a96aa3bSJed Brown } 31560a96aa3bSJed Brown } 31570a96aa3bSJed Brown } 31580a96aa3bSJed Brown } 31590a96aa3bSJed Brown } 31600a96aa3bSJed Brown PetscFunctionReturn(0); 31610a96aa3bSJed Brown } 31629566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base,0,&cStartBase,&cEndBase)); 31639566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base,1,&fStartBase,&fEndBase)); 31649566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base,P4EST_DIM-1,&eStartBase,&eEndBase)); 31659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(base,0,&vStartBase,&vEndBase)); 31660a96aa3bSJed Brown 31679566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex,0,&cStart,&cEnd)); 31689566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex,1,&fStart,&fEnd)); 31699566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex,P4EST_DIM-1,&eStart,&eEnd)); 31709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex,0,&vStart,&vEnd)); 31710a96aa3bSJed Brown 31729566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex,&pStart,&pEnd)); 31739566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(base,&pStartBase,&pEndBase)); 31740a96aa3bSJed Brown /* go through the mesh: use star to find a quadrant that borders a point. Use the closure to determine the 31750a96aa3bSJed Brown * orientation of the quadrant relative to that point. Use that to relate the point to the numbering in the base 31760a96aa3bSJed Brown * mesh, and extract a label value (since the base mesh is redundantly distributed, can be found locally). */ 31770a96aa3bSJed Brown while (next) { 31780a96aa3bSJed Brown DMLabel baseLabel; 31790a96aa3bSJed Brown DMLabel label = next->label; 31800a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK, isSpmap; 31810a96aa3bSJed Brown const char *name; 31820a96aa3bSJed Brown 31839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) label, &name)); 31849566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"depth",&isDepth)); 31850a96aa3bSJed Brown if (isDepth) { 31860a96aa3bSJed Brown next = next->next; 31870a96aa3bSJed Brown continue; 31880a96aa3bSJed Brown } 31899566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"celltype",&isCellType)); 31900a96aa3bSJed Brown if (isCellType) { 31910a96aa3bSJed Brown next = next->next; 31920a96aa3bSJed Brown continue; 31930a96aa3bSJed Brown } 31949566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"ghost",&isGhost)); 31950a96aa3bSJed Brown if (isGhost) { 31960a96aa3bSJed Brown next = next->next; 31970a96aa3bSJed Brown continue; 31980a96aa3bSJed Brown } 31999566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"vtk",&isVTK)); 32000a96aa3bSJed Brown if (isVTK) { 32010a96aa3bSJed Brown next = next->next; 32020a96aa3bSJed Brown continue; 32030a96aa3bSJed Brown } 32049566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"_forest_base_subpoint_map",&isSpmap)); 32050a96aa3bSJed Brown if (!isSpmap) { 32069566063dSJacob Faibussowitsch PetscCall(DMGetLabel(base,name,&baseLabel)); 32070a96aa3bSJed Brown if (!baseLabel) { 32080a96aa3bSJed Brown next = next->next; 32090a96aa3bSJed Brown continue; 32100a96aa3bSJed Brown } 32119566063dSJacob Faibussowitsch PetscCall(DMLabelCreateIndex(baseLabel,pStartBase,pEndBase)); 32120a96aa3bSJed Brown } else baseLabel = NULL; 32130a96aa3bSJed Brown 32140a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 32150a96aa3bSJed Brown PetscInt s, c = -1, l; 32160a96aa3bSJed Brown PetscInt *closure = NULL, closureSize; 32170a96aa3bSJed Brown p4est_quadrant_t * ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 32180a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t*) pforest->forest->trees->array; 32190a96aa3bSJed Brown p4est_quadrant_t * q; 32200a96aa3bSJed Brown PetscInt t, val; 32210a96aa3bSJed Brown PetscBool zerosupportpoint = PETSC_FALSE; 32220a96aa3bSJed Brown 32239566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,p,PETSC_FALSE,&starSize,&star)); 32240a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 32250a96aa3bSJed Brown PetscInt point = star[2*s]; 32260a96aa3bSJed Brown 32270a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 32289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,point,PETSC_TRUE,&closureSize,&closure)); 32290a96aa3bSJed Brown for (l = 0; l < closureSize; l++) { 32300a96aa3bSJed Brown PetscInt qParent = closure[2 * l], q, pp = p, pParent = p; 32310a96aa3bSJed Brown do { /* check parents of q */ 32320a96aa3bSJed Brown q = qParent; 32330a96aa3bSJed Brown if (q == p) { 32340a96aa3bSJed Brown c = point; 32350a96aa3bSJed Brown break; 32360a96aa3bSJed Brown } 32379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&qParent,NULL)); 32380a96aa3bSJed Brown } while (qParent != q); 32390a96aa3bSJed Brown if (c != -1) break; 32409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,pp,&pParent,NULL)); 32410a96aa3bSJed Brown q = closure[2 * l]; 32420a96aa3bSJed Brown while (pParent != pp) { /* check parents of p */ 32430a96aa3bSJed Brown pp = pParent; 32440a96aa3bSJed Brown if (pp == q) { 32450a96aa3bSJed Brown c = point; 32460a96aa3bSJed Brown break; 32470a96aa3bSJed Brown } 32489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,pp,&pParent,NULL)); 32490a96aa3bSJed Brown } 32500a96aa3bSJed Brown if (c != -1) break; 32510a96aa3bSJed Brown } 32529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,point,PETSC_TRUE,NULL,&closure)); 32530a96aa3bSJed Brown if (l < closureSize) break; 32540a96aa3bSJed Brown } else { 32550a96aa3bSJed Brown PetscInt supportSize; 32560a96aa3bSJed Brown 32579566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(plex,point,&supportSize)); 32580a96aa3bSJed Brown zerosupportpoint = (PetscBool) (zerosupportpoint || !supportSize); 32590a96aa3bSJed Brown } 32600a96aa3bSJed Brown } 32610a96aa3bSJed Brown if (c < 0) { 32620a96aa3bSJed Brown const char* prefix; 32630a96aa3bSJed Brown PetscBool print = PETSC_FALSE; 32640a96aa3bSJed Brown 32659566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix)); 32669566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options,prefix,"-dm_forest_print_label_error",&print,NULL)); 32670a96aa3bSJed Brown if (print) { 32680a96aa3bSJed Brown PetscInt i; 32690a96aa3bSJed Brown 327063a3b9bcSJacob 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)); 327163a3b9bcSJacob 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])); 32720a96aa3bSJed Brown } 32739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,p,PETSC_FALSE,NULL,&star)); 32740a96aa3bSJed Brown if (zerosupportpoint) continue; 327563a3b9bcSJacob 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"); 32760a96aa3bSJed Brown } 32779566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,p,PETSC_FALSE,NULL,&star)); 32780a96aa3bSJed Brown 32790a96aa3bSJed Brown if (c < cLocalStart) { 32800a96aa3bSJed Brown /* get from the beginning of the ghost layer */ 32810a96aa3bSJed Brown q = &(ghosts[c]); 32820a96aa3bSJed Brown t = (PetscInt) q->p.which_tree; 32830a96aa3bSJed Brown } else if (c < cLocalEnd) { 32840a96aa3bSJed Brown PetscInt lo = 0, hi = num_trees; 32850a96aa3bSJed Brown /* get from local quadrants: have to find the right tree */ 32860a96aa3bSJed Brown 32870a96aa3bSJed Brown c -= cLocalStart; 32880a96aa3bSJed Brown 32890a96aa3bSJed Brown do { 32900a96aa3bSJed Brown p4est_tree_t *tree; 32910a96aa3bSJed Brown 32921dca8a05SBarry Smith PetscCheck(guess >= lo && guess < num_trees && lo < hi,PETSC_COMM_SELF,PETSC_ERR_PLIB,"failed binary search"); 32930a96aa3bSJed Brown tree = &trees[guess]; 32940a96aa3bSJed Brown if (c < tree->quadrants_offset) { 32950a96aa3bSJed Brown hi = guess; 32960a96aa3bSJed Brown } else if (c < tree->quadrants_offset + (PetscInt) tree->quadrants.elem_count) { 32970a96aa3bSJed Brown q = &((p4est_quadrant_t *)tree->quadrants.array)[c - (PetscInt) tree->quadrants_offset]; 32980a96aa3bSJed Brown t = guess; 32990a96aa3bSJed Brown break; 33000a96aa3bSJed Brown } else { 33010a96aa3bSJed Brown lo = guess + 1; 33020a96aa3bSJed Brown } 33030a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 33040a96aa3bSJed Brown } while (1); 33050a96aa3bSJed Brown } else { 33060a96aa3bSJed Brown /* get from the end of the ghost layer */ 33070a96aa3bSJed Brown c -= (cLocalEnd - cLocalStart); 33080a96aa3bSJed Brown 33090a96aa3bSJed Brown q = &(ghosts[c]); 33100a96aa3bSJed Brown t = (PetscInt) q->p.which_tree; 33110a96aa3bSJed Brown } 33120a96aa3bSJed Brown 33130a96aa3bSJed Brown if (l == 0) { /* cell */ 33140a96aa3bSJed Brown if (baseLabel) { 33159566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,t+cStartBase,&val)); 33160a96aa3bSJed Brown } else { 33170a96aa3bSJed Brown val = t+cStartBase; 33180a96aa3bSJed Brown } 33199566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33200a96aa3bSJed Brown } else if (l >= 1 && l < 1 + P4EST_FACES) { /* facet */ 33210a96aa3bSJed Brown p4est_quadrant_t nq; 33220a96aa3bSJed Brown int isInside; 33230a96aa3bSJed Brown 33240a96aa3bSJed Brown l = PetscFaceToP4estFace[l - 1]; 33250a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_face_neighbor,(q,l,&nq)); 33260a96aa3bSJed Brown PetscStackCallP4estReturn(isInside,p4est_quadrant_is_inside_root,(&nq)); 33270a96aa3bSJed Brown if (isInside) { 33280a96aa3bSJed Brown /* this facet is in the interior of a tree, so it inherits the label of the tree */ 33290a96aa3bSJed Brown if (baseLabel) { 33309566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,t+cStartBase,&val)); 33310a96aa3bSJed Brown } else { 33320a96aa3bSJed Brown val = t+cStartBase; 33330a96aa3bSJed Brown } 33349566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33350a96aa3bSJed Brown } else { 33360a96aa3bSJed Brown PetscInt f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + l]; 33370a96aa3bSJed Brown 33380a96aa3bSJed Brown if (baseLabel) { 33399566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,f+fStartBase,&val)); 33400a96aa3bSJed Brown } else { 33410a96aa3bSJed Brown val = f+fStartBase; 33420a96aa3bSJed Brown } 33439566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33440a96aa3bSJed Brown } 33450a96aa3bSJed Brown #if defined(P4_TO_P8) 33460a96aa3bSJed Brown } else if (l >= 1 + P4EST_FACES && l < 1 + P4EST_FACES + P8EST_EDGES) { /* edge */ 33470a96aa3bSJed Brown p4est_quadrant_t nq; 33480a96aa3bSJed Brown int isInside; 33490a96aa3bSJed Brown 33500a96aa3bSJed Brown l = PetscEdgeToP4estEdge[l - (1 + P4EST_FACES)]; 33510a96aa3bSJed Brown PetscStackCallP4est(p8est_quadrant_edge_neighbor,(q,l,&nq)); 33520a96aa3bSJed Brown PetscStackCallP4estReturn(isInside,p4est_quadrant_is_inside_root,(&nq)); 33530a96aa3bSJed Brown if (isInside) { 33540a96aa3bSJed Brown /* this edge is in the interior of a tree, so it inherits the label of the tree */ 33550a96aa3bSJed Brown if (baseLabel) { 33569566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,t+cStartBase,&val)); 33570a96aa3bSJed Brown } else { 33580a96aa3bSJed Brown val = t+cStartBase; 33590a96aa3bSJed Brown } 33609566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33610a96aa3bSJed Brown } else { 33620a96aa3bSJed Brown int isOutsideFace; 33630a96aa3bSJed Brown 33640a96aa3bSJed Brown PetscStackCallP4estReturn(isOutsideFace,p4est_quadrant_is_outside_face,(&nq)); 33650a96aa3bSJed Brown if (isOutsideFace) { 33660a96aa3bSJed Brown PetscInt f; 33670a96aa3bSJed Brown 33680a96aa3bSJed Brown if (nq.x < 0) { 33690a96aa3bSJed Brown f = 0; 33700a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 33710a96aa3bSJed Brown f = 1; 33720a96aa3bSJed Brown } else if (nq.y < 0) { 33730a96aa3bSJed Brown f = 2; 33740a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 33750a96aa3bSJed Brown f = 3; 33760a96aa3bSJed Brown } else if (nq.z < 0) { 33770a96aa3bSJed Brown f = 4; 33780a96aa3bSJed Brown } else { 33790a96aa3bSJed Brown f = 5; 33800a96aa3bSJed Brown } 33810a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 33820a96aa3bSJed Brown if (baseLabel) { 33839566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,f+fStartBase,&val)); 33840a96aa3bSJed Brown } else { 33850a96aa3bSJed Brown val = f+fStartBase; 33860a96aa3bSJed Brown } 33879566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33880a96aa3bSJed Brown } else { /* the quadrant edge corresponds to the tree edge */ 33890a96aa3bSJed Brown PetscInt e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + l]; 33900a96aa3bSJed Brown 33910a96aa3bSJed Brown if (baseLabel) { 33929566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,e+eStartBase,&val)); 33930a96aa3bSJed Brown } else { 33940a96aa3bSJed Brown val = e+eStartBase; 33950a96aa3bSJed Brown } 33969566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 33970a96aa3bSJed Brown } 33980a96aa3bSJed Brown } 33990a96aa3bSJed Brown #endif 34000a96aa3bSJed Brown } else { /* vertex */ 34010a96aa3bSJed Brown p4est_quadrant_t nq; 34020a96aa3bSJed Brown int isInside; 34030a96aa3bSJed Brown 34040a96aa3bSJed Brown #if defined(P4_TO_P8) 34050a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES + P8EST_EDGES)]; 34060a96aa3bSJed Brown #else 34070a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES)]; 34080a96aa3bSJed Brown #endif 34090a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_corner_neighbor,(q,l,&nq)); 34100a96aa3bSJed Brown PetscStackCallP4estReturn(isInside,p4est_quadrant_is_inside_root,(&nq)); 34110a96aa3bSJed Brown if (isInside) { 34120a96aa3bSJed Brown if (baseLabel) { 34139566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,t+cStartBase,&val)); 34140a96aa3bSJed Brown } else { 34150a96aa3bSJed Brown val = t+cStartBase; 34160a96aa3bSJed Brown } 34179566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 34180a96aa3bSJed Brown } else { 34190a96aa3bSJed Brown int isOutside; 34200a96aa3bSJed Brown 34210a96aa3bSJed Brown PetscStackCallP4estReturn(isOutside,p4est_quadrant_is_outside_face,(&nq)); 34220a96aa3bSJed Brown if (isOutside) { 34230a96aa3bSJed Brown PetscInt f = -1; 34240a96aa3bSJed Brown 34250a96aa3bSJed Brown if (nq.x < 0) { 34260a96aa3bSJed Brown f = 0; 34270a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 34280a96aa3bSJed Brown f = 1; 34290a96aa3bSJed Brown } else if (nq.y < 0) { 34300a96aa3bSJed Brown f = 2; 34310a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 34320a96aa3bSJed Brown f = 3; 34330a96aa3bSJed Brown #if defined(P4_TO_P8) 34340a96aa3bSJed Brown } else if (nq.z < 0) { 34350a96aa3bSJed Brown f = 4; 34360a96aa3bSJed Brown } else { 34370a96aa3bSJed Brown f = 5; 34380a96aa3bSJed Brown #endif 34390a96aa3bSJed Brown } 34400a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 34410a96aa3bSJed Brown if (baseLabel) { 34429566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,f+fStartBase,&val)); 34430a96aa3bSJed Brown } else { 34440a96aa3bSJed Brown val = f+fStartBase; 34450a96aa3bSJed Brown } 34469566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 34470a96aa3bSJed Brown continue; 34480a96aa3bSJed Brown } 34490a96aa3bSJed Brown #if defined(P4_TO_P8) 34500a96aa3bSJed Brown PetscStackCallP4estReturn(isOutside,p8est_quadrant_is_outside_edge,(&nq)); 34510a96aa3bSJed Brown if (isOutside) { 34520a96aa3bSJed Brown /* outside edge */ 34530a96aa3bSJed Brown PetscInt e = -1; 34540a96aa3bSJed Brown 34550a96aa3bSJed Brown if (nq.x >= 0 && nq.x < P4EST_ROOT_LEN) { 34560a96aa3bSJed Brown if (nq.z < 0) { 34570a96aa3bSJed Brown if (nq.y < 0) { 34580a96aa3bSJed Brown e = 0; 34590a96aa3bSJed Brown } else { 34600a96aa3bSJed Brown e = 1; 34610a96aa3bSJed Brown } 34620a96aa3bSJed Brown } else { 34630a96aa3bSJed Brown if (nq.y < 0) { 34640a96aa3bSJed Brown e = 2; 34650a96aa3bSJed Brown } else { 34660a96aa3bSJed Brown e = 3; 34670a96aa3bSJed Brown } 34680a96aa3bSJed Brown } 34690a96aa3bSJed Brown } else if (nq.y >= 0 && nq.y < P4EST_ROOT_LEN) { 34700a96aa3bSJed Brown if (nq.z < 0) { 34710a96aa3bSJed Brown if (nq.x < 0) { 34720a96aa3bSJed Brown e = 4; 34730a96aa3bSJed Brown } else { 34740a96aa3bSJed Brown e = 5; 34750a96aa3bSJed Brown } 34760a96aa3bSJed Brown } else { 34770a96aa3bSJed Brown if (nq.x < 0) { 34780a96aa3bSJed Brown e = 6; 34790a96aa3bSJed Brown } else { 34800a96aa3bSJed Brown e = 7; 34810a96aa3bSJed Brown } 34820a96aa3bSJed Brown } 34830a96aa3bSJed Brown } else { 34840a96aa3bSJed Brown if (nq.y < 0) { 34850a96aa3bSJed Brown if (nq.x < 0) { 34860a96aa3bSJed Brown e = 8; 34870a96aa3bSJed Brown } else { 34880a96aa3bSJed Brown e = 9; 34890a96aa3bSJed Brown } 34900a96aa3bSJed Brown } else { 34910a96aa3bSJed Brown if (nq.x < 0) { 34920a96aa3bSJed Brown e = 10; 34930a96aa3bSJed Brown } else { 34940a96aa3bSJed Brown e = 11; 34950a96aa3bSJed Brown } 34960a96aa3bSJed Brown } 34970a96aa3bSJed Brown } 34980a96aa3bSJed Brown 34990a96aa3bSJed Brown e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + e]; 35000a96aa3bSJed Brown if (baseLabel) { 35019566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,e+eStartBase,&val)); 35020a96aa3bSJed Brown } else { 35030a96aa3bSJed Brown val = e+eStartBase; 35040a96aa3bSJed Brown } 35059566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 35060a96aa3bSJed Brown continue; 35070a96aa3bSJed Brown } 35080a96aa3bSJed Brown #endif 35090a96aa3bSJed Brown { 35100a96aa3bSJed Brown /* outside vertex: same corner as quadrant corner */ 35110a96aa3bSJed Brown PetscInt v = pforest->topo->conn->tree_to_corner[P4EST_CHILDREN * t + l]; 35120a96aa3bSJed Brown 35130a96aa3bSJed Brown if (baseLabel) { 35149566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel,v+vStartBase,&val)); 35150a96aa3bSJed Brown } else { 35160a96aa3bSJed Brown val = v+vStartBase; 35170a96aa3bSJed Brown } 35189566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,val)); 35190a96aa3bSJed Brown } 35200a96aa3bSJed Brown } 35210a96aa3bSJed Brown } 35220a96aa3bSJed Brown } 35230a96aa3bSJed Brown next = next->next; 35240a96aa3bSJed Brown } 35250a96aa3bSJed Brown PetscFunctionReturn(0); 35260a96aa3bSJed Brown } 35270a96aa3bSJed Brown 35280a96aa3bSJed Brown static PetscErrorCode DMPforestLabelsFinalize(DM dm, DM plex) 35290a96aa3bSJed Brown { 35300a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 35310a96aa3bSJed Brown DM adapt; 35320a96aa3bSJed Brown 35330a96aa3bSJed Brown PetscFunctionBegin; 35340a96aa3bSJed Brown if (pforest->labelsFinalized) PetscFunctionReturn(0); 35350a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 35369566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm,&adapt)); 35370a96aa3bSJed Brown if (!adapt) { 35380a96aa3bSJed Brown /* Initialize labels from the base dm */ 35399566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsInitialize(dm,plex)); 35400a96aa3bSJed Brown } else { 35410a96aa3bSJed Brown PetscInt dofPerDim[4]={1, 1, 1, 1}; 35420a96aa3bSJed Brown PetscSF transferForward, transferBackward, pointSF; 35430a96aa3bSJed Brown PetscInt pStart, pEnd, pStartA, pEndA; 35440a96aa3bSJed Brown PetscInt *values, *adaptValues; 35450a96aa3bSJed Brown DMLabelLink next = adapt->labels; 35460a96aa3bSJed Brown DMLabel adaptLabel; 35470a96aa3bSJed Brown DM adaptPlex; 35480a96aa3bSJed Brown 35499566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm,&adaptLabel)); 35509566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(adapt,&adaptPlex)); 35519566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(adapt,dm,dofPerDim,&transferForward,&transferBackward)); 35529566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex,&pStart,&pEnd)); 35539566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(adaptPlex,&pStartA,&pEndA)); 35549566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd-pStart,&values,pEndA-pStartA,&adaptValues)); 35559566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plex,&pointSF)); 35560a96aa3bSJed Brown if (PetscDefined(USE_DEBUG)) { 35570a96aa3bSJed Brown PetscInt p; 35580a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) adaptValues[p-pStartA] = -1; 35590a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p-pStart] = -2; 35600a96aa3bSJed Brown if (transferForward) { 35619566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE)); 35629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE)); 35630a96aa3bSJed Brown } 35640a96aa3bSJed Brown if (transferBackward) { 35659566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(transferBackward,MPIU_INT,adaptValues,values,MPIU_MAX)); 35669566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(transferBackward,MPIU_INT,adaptValues,values,MPIU_MAX)); 35670a96aa3bSJed Brown } 35680a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 35690a96aa3bSJed Brown PetscInt q = p, parent; 35700a96aa3bSJed Brown 35719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&parent,NULL)); 35720a96aa3bSJed Brown while (parent != q) { 35730a96aa3bSJed Brown if (values[parent] == -2) values[parent] = values[q]; 35740a96aa3bSJed Brown q = parent; 35759566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&parent,NULL)); 35760a96aa3bSJed Brown } 35770a96aa3bSJed Brown } 35789566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF,MPIU_INT,values,values,MPIU_MAX)); 35799566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF,MPIU_INT,values,values,MPIU_MAX)); 35809566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF,MPIU_INT,values,values,MPI_REPLACE)); 35819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF,MPIU_INT,values,values,MPI_REPLACE)); 35820a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 358363a3b9bcSJacob Faibussowitsch PetscCheck(values[p-pStart] != -2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"uncovered point %" PetscInt_FMT,p); 35840a96aa3bSJed Brown } 35850a96aa3bSJed Brown } 35860a96aa3bSJed Brown while (next) { 35870a96aa3bSJed Brown DMLabel nextLabel = next->label; 35880a96aa3bSJed Brown const char *name; 35890a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 35900a96aa3bSJed Brown DMLabel label; 35910a96aa3bSJed Brown PetscInt p; 35920a96aa3bSJed Brown 35939566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject) nextLabel, &name)); 35949566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"depth",&isDepth)); 35950a96aa3bSJed Brown if (isDepth) { 35960a96aa3bSJed Brown next = next->next; 35970a96aa3bSJed Brown continue; 35980a96aa3bSJed Brown } 35999566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"celltype",&isCellType)); 36000a96aa3bSJed Brown if (isCellType) { 36010a96aa3bSJed Brown next = next->next; 36020a96aa3bSJed Brown continue; 36030a96aa3bSJed Brown } 36049566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"ghost",&isGhost)); 36050a96aa3bSJed Brown if (isGhost) { 36060a96aa3bSJed Brown next = next->next; 36070a96aa3bSJed Brown continue; 36080a96aa3bSJed Brown } 36099566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name,"vtk",&isVTK)); 36100a96aa3bSJed Brown if (isVTK) { 36110a96aa3bSJed Brown next = next->next; 36120a96aa3bSJed Brown continue; 36130a96aa3bSJed Brown } 36140a96aa3bSJed Brown if (nextLabel == adaptLabel) { 36150a96aa3bSJed Brown next = next->next; 36160a96aa3bSJed Brown continue; 36170a96aa3bSJed Brown } 36180a96aa3bSJed Brown /* label was created earlier */ 36199566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm,name,&label)); 36200a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) { 36219566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(nextLabel,p,&adaptValues[p])); 36220a96aa3bSJed Brown } 36230a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p] = PETSC_MIN_INT; 36240a96aa3bSJed Brown 36251baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastBegin(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE)); 36261baa6e33SBarry Smith if (transferBackward) PetscCall(PetscSFReduceBegin(transferBackward,MPIU_INT,adaptValues,values,MPIU_MAX)); 36271baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastEnd(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE)); 36281baa6e33SBarry Smith if (transferBackward) PetscCall(PetscSFReduceEnd(transferBackward,MPIU_INT,adaptValues,values,MPIU_MAX)); 36290a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 36300a96aa3bSJed Brown PetscInt q = p, parent; 36310a96aa3bSJed Brown 36329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&parent,NULL)); 36330a96aa3bSJed Brown while (parent != q) { 36340a96aa3bSJed Brown if (values[parent] == PETSC_MIN_INT) values[parent] = values[q]; 36350a96aa3bSJed Brown q = parent; 36369566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex,q,&parent,NULL)); 36370a96aa3bSJed Brown } 36380a96aa3bSJed Brown } 36399566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF,MPIU_INT,values,values,MPIU_MAX)); 36409566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF,MPIU_INT,values,values,MPIU_MAX)); 36419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF,MPIU_INT,values,values,MPI_REPLACE)); 36429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF,MPIU_INT,values,values,MPI_REPLACE)); 36430a96aa3bSJed Brown 36440a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 36459566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label,p,values[p])); 36460a96aa3bSJed Brown } 36470a96aa3bSJed Brown next = next->next; 36480a96aa3bSJed Brown } 36499566063dSJacob Faibussowitsch PetscCall(PetscFree2(values,adaptValues)); 36509566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferForward)); 36519566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferBackward)); 36520a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 36530a96aa3bSJed Brown } 36540a96aa3bSJed Brown PetscFunctionReturn(0); 36550a96aa3bSJed Brown } 36560a96aa3bSJed Brown 36570a96aa3bSJed 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) 36580a96aa3bSJed Brown { 36590a96aa3bSJed Brown PetscInt closureSize, c, coordStart, coordEnd, coordDim; 36600a96aa3bSJed Brown PetscInt *closure = NULL; 36610a96aa3bSJed Brown PetscSection coordSec; 36620a96aa3bSJed Brown 36630a96aa3bSJed Brown PetscFunctionBegin; 36649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex,&coordSec)); 36659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec,&coordStart,&coordEnd)); 36669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex,&coordDim)); 36679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,cell,PETSC_TRUE,&closureSize,&closure)); 36680a96aa3bSJed Brown for (c = 0; c < closureSize; c++) { 36690a96aa3bSJed Brown PetscInt point = closure[2 * c]; 36700a96aa3bSJed Brown 36710a96aa3bSJed Brown if (point >= coordStart && point < coordEnd) { 36720a96aa3bSJed Brown PetscInt dof, off; 36730a96aa3bSJed Brown PetscInt nCoords, i; 36749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec,point,&dof)); 367508401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Did not understand coordinate layout"); 36760a96aa3bSJed Brown nCoords = dof / coordDim; 36779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec,point,&off)); 36780a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 36790a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 36800a96aa3bSJed Brown double coordP4est[3] = {0.}; 36810a96aa3bSJed Brown double coordP4estMapped[3] = {0.}; 36820a96aa3bSJed Brown PetscInt j; 36830a96aa3bSJed Brown PetscReal treeCoords[P4EST_CHILDREN][3] = {{0.}}; 36840a96aa3bSJed Brown PetscReal eta[3] = {0.}; 36850a96aa3bSJed Brown PetscInt numRounds = 10; 36860a96aa3bSJed Brown PetscReal coordGuess[3] = {0.}; 36870a96aa3bSJed Brown 36880a96aa3bSJed Brown eta[0] = (PetscReal) q->x / (PetscReal) P4EST_ROOT_LEN; 36890a96aa3bSJed Brown eta[1] = (PetscReal) q->y / (PetscReal) P4EST_ROOT_LEN; 36900a96aa3bSJed Brown #if defined(P4_TO_P8) 36910a96aa3bSJed Brown eta[2] = (PetscReal) q->z / (PetscReal) P4EST_ROOT_LEN; 36920a96aa3bSJed Brown #endif 36930a96aa3bSJed Brown 36940a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 36950a96aa3bSJed Brown PetscInt k; 36960a96aa3bSJed Brown 36970a96aa3bSJed Brown for (k = 0; k < 3; k++) treeCoords[j][k] = conn->vertices[3 * conn->tree_to_vertex[P4EST_CHILDREN * t + j] + k]; 36980a96aa3bSJed Brown } 36990a96aa3bSJed Brown 37000a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 37010a96aa3bSJed Brown PetscInt k; 37020a96aa3bSJed Brown PetscReal prod = 1.; 37030a96aa3bSJed Brown 37040a96aa3bSJed Brown for (k = 0; k < P4EST_DIM; k++) prod *= (j & (1 << k)) ? eta[k] : (1. - eta[k]); 37050a96aa3bSJed Brown for (k = 0; k < 3; k++) coordGuess[k] += prod * treeCoords[j][k]; 37060a96aa3bSJed Brown } 37070a96aa3bSJed Brown 37080a96aa3bSJed Brown for (j = 0; j < numRounds; j++) { 37090a96aa3bSJed Brown PetscInt dir; 37100a96aa3bSJed Brown 37110a96aa3bSJed Brown for (dir = 0; dir < P4EST_DIM; dir++) { 37120a96aa3bSJed Brown PetscInt k; 37130a96aa3bSJed Brown PetscReal diff[3]; 37140a96aa3bSJed Brown PetscReal dXdeta[3] = {0.}; 37150a96aa3bSJed Brown PetscReal rhs, scale, update; 37160a96aa3bSJed Brown 37170a96aa3bSJed Brown for (k = 0; k < 3; k++) diff[k] = coordP4est[k] - coordGuess[k]; 37180a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 37190a96aa3bSJed Brown PetscInt l; 37200a96aa3bSJed Brown PetscReal prod = 1.; 37210a96aa3bSJed Brown 37220a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) { 37230a96aa3bSJed Brown if (l == dir) { 37240a96aa3bSJed Brown prod *= (k & (1 << l)) ? 1. : -1.; 37250a96aa3bSJed Brown } else { 37260a96aa3bSJed Brown prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 37270a96aa3bSJed Brown } 37280a96aa3bSJed Brown } 37290a96aa3bSJed Brown for (l = 0; l < 3; l++) dXdeta[l] += prod * treeCoords[k][l]; 37300a96aa3bSJed Brown } 37310a96aa3bSJed Brown rhs = 0.; 37320a96aa3bSJed Brown scale = 0; 37330a96aa3bSJed Brown for (k = 0; k < 3; k++) { 37340a96aa3bSJed Brown rhs += diff[k] * dXdeta[k]; 37350a96aa3bSJed Brown scale += dXdeta[k] * dXdeta[k]; 37360a96aa3bSJed Brown } 37370a96aa3bSJed Brown update = rhs / scale; 37380a96aa3bSJed Brown eta[dir] += update; 37390a96aa3bSJed Brown eta[dir] = PetscMin(eta[dir],1.); 37400a96aa3bSJed Brown eta[dir] = PetscMax(eta[dir],0.); 37410a96aa3bSJed Brown 37420a96aa3bSJed Brown coordGuess[0] = coordGuess[1] = coordGuess[2] = 0.; 37430a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 37440a96aa3bSJed Brown PetscInt l; 37450a96aa3bSJed Brown PetscReal prod = 1.; 37460a96aa3bSJed Brown 37470a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 37480a96aa3bSJed Brown for (l = 0; l < 3; l++) coordGuess[l] += prod * treeCoords[k][l]; 37490a96aa3bSJed Brown } 37500a96aa3bSJed Brown } 37510a96aa3bSJed Brown } 37520a96aa3bSJed Brown for (j = 0; j < 3; j++) coordP4est[j] = (double) eta[j]; 37530a96aa3bSJed Brown 37540a96aa3bSJed Brown if (geom) { 37550a96aa3bSJed Brown (geom->X)(geom,t,coordP4est,coordP4estMapped); 37560a96aa3bSJed Brown for (j = 0; j < coordDim; j++) coord[j] = (PetscScalar) coordP4estMapped[j]; 37570a96aa3bSJed Brown } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not coded"); 37580a96aa3bSJed Brown } 37590a96aa3bSJed Brown } 37600a96aa3bSJed Brown } 37619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,cell,PETSC_TRUE,&closureSize,&closure)); 37620a96aa3bSJed Brown PetscFunctionReturn(0); 37630a96aa3bSJed Brown } 37640a96aa3bSJed Brown 37650a96aa3bSJed Brown static PetscErrorCode DMPforestMapCoordinates(DM dm, DM plex) 37660a96aa3bSJed Brown { 37670a96aa3bSJed Brown DM_Forest *forest; 37680a96aa3bSJed Brown DM_Forest_pforest *pforest; 37690a96aa3bSJed Brown p4est_geometry_t *geom; 37700a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd; 37710a96aa3bSJed Brown Vec coordLocalVec; 37720a96aa3bSJed Brown PetscScalar *coords; 37730a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 37740a96aa3bSJed Brown p4est_tree_t *trees; 37750a96aa3bSJed Brown PetscErrorCode (*map)(DM,PetscInt, PetscInt, const PetscReal [], PetscReal [], void*); 37760a96aa3bSJed Brown void *mapCtx; 37770a96aa3bSJed Brown 37780a96aa3bSJed Brown PetscFunctionBegin; 37790a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 37800a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 37810a96aa3bSJed Brown geom = pforest->topo->geom; 37829566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx)); 37830a96aa3bSJed Brown if (!geom && !map) PetscFunctionReturn(0); 37849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(plex,&coordLocalVec)); 37859566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordLocalVec,&coords)); 37860a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 37870a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 37880a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 37890a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 37900a96aa3bSJed Brown trees = (p4est_tree_t*) pforest->forest->trees->array; 37910a96aa3bSJed Brown if (map) { /* apply the map directly to the existing coordinates */ 37920a96aa3bSJed Brown PetscSection coordSec; 37930a96aa3bSJed Brown PetscInt coordStart, coordEnd, p, coordDim, p4estCoordDim, cStart, cEnd, cEndInterior; 37940a96aa3bSJed Brown DM base; 37950a96aa3bSJed Brown 37969566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex,0,&cStart,&cEnd)); 37979566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(plex,&cEndInterior,NULL)); 37980a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 37999566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 38009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex,&coordSec)); 38019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec,&coordStart,&coordEnd)); 38029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex,&coordDim)); 38030a96aa3bSJed Brown p4estCoordDim = PetscMin(coordDim,3); 38040a96aa3bSJed Brown for (p = coordStart; p < coordEnd; p++) { 38050a96aa3bSJed Brown PetscInt *star = NULL, starSize; 38060a96aa3bSJed Brown PetscInt dof, off, cell = -1, coarsePoint = -1; 38070a96aa3bSJed Brown PetscInt nCoords, i; 38089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec,p,&dof)); 380908401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Did not understand coordinate layout"); 38100a96aa3bSJed Brown nCoords = dof / coordDim; 38119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec,p,&off)); 38129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex,p,PETSC_FALSE,&starSize,&star)); 38130a96aa3bSJed Brown for (i = 0; i < starSize; i++) { 38140a96aa3bSJed Brown PetscInt point = star[2 * i]; 38150a96aa3bSJed Brown 38160a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 38170a96aa3bSJed Brown cell = point; 38180a96aa3bSJed Brown break; 38190a96aa3bSJed Brown } 38200a96aa3bSJed Brown } 38219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex,p,PETSC_FALSE,&starSize,&star)); 38220a96aa3bSJed Brown if (cell >= 0) { 38230a96aa3bSJed Brown if (cell < cLocalStart) { 38240a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 38250a96aa3bSJed Brown 38260a96aa3bSJed Brown coarsePoint = ghosts[cell].p.which_tree; 38270a96aa3bSJed Brown } else if (cell < cLocalEnd) { 38280a96aa3bSJed Brown cell -= cLocalStart; 38290a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 38300a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 38310a96aa3bSJed Brown 38320a96aa3bSJed Brown if (cell >= tree->quadrants_offset && (size_t) cell < tree->quadrants_offset + tree->quadrants.elem_count) { 38330a96aa3bSJed Brown coarsePoint = t; 38340a96aa3bSJed Brown break; 38350a96aa3bSJed Brown } 38360a96aa3bSJed Brown } 38370a96aa3bSJed Brown } else { 38380a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 38390a96aa3bSJed Brown 38400a96aa3bSJed Brown coarsePoint = ghosts[cell - cLocalEnd].p.which_tree; 38410a96aa3bSJed Brown } 38420a96aa3bSJed Brown } 38430a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 38440a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 38450a96aa3bSJed Brown PetscReal coordP4est[3] = {0.}; 38460a96aa3bSJed Brown PetscReal coordP4estMapped[3] = {0.}; 38470a96aa3bSJed Brown PetscInt j; 38480a96aa3bSJed Brown 38490a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coordP4est[j] = PetscRealPart(coord[j]); 38509566063dSJacob Faibussowitsch PetscCall((map)(base,coarsePoint,p4estCoordDim,coordP4est,coordP4estMapped,mapCtx)); 38510a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coord[j] = (PetscScalar) coordP4estMapped[j]; 38520a96aa3bSJed Brown } 38530a96aa3bSJed Brown } 38540a96aa3bSJed Brown } else { /* we have to transform coordinates back to the unit cube (where geom is defined), and then apply geom */ 38550a96aa3bSJed Brown PetscInt cStart, cEnd, cEndInterior; 38560a96aa3bSJed Brown 38579566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex,0,&cStart,&cEnd)); 38589566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(plex,&cEndInterior,NULL)); 38590a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 38600a96aa3bSJed Brown if (cLocalStart > 0) { 38610a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 38620a96aa3bSJed Brown PetscInt count; 38630a96aa3bSJed Brown 38640a96aa3bSJed Brown for (count = 0; count < cLocalStart; count++) { 38650a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count]; 38660a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 38670a96aa3bSJed Brown 38689566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex,geom,count,quad,t,pforest->topo->conn,coords)); 38690a96aa3bSJed Brown } 38700a96aa3bSJed Brown } 38710a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 38720a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 38730a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset, i; 38740a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 38750a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t*) tree->quadrants.array; 38760a96aa3bSJed Brown 38770a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 38780a96aa3bSJed Brown PetscInt count = i + offset; 38790a96aa3bSJed Brown 38809566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex,geom,count,&quads[i],t,pforest->topo->conn,coords)); 38810a96aa3bSJed Brown } 38820a96aa3bSJed Brown } 38830a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 38840a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 38850a96aa3bSJed Brown PetscInt numGhosts = (PetscInt) pforest->ghost->ghosts.elem_count; 38860a96aa3bSJed Brown PetscInt count; 38870a96aa3bSJed Brown 38880a96aa3bSJed Brown for (count = 0; count < numGhosts - cLocalStart; count++) { 38890a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 38900a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 38910a96aa3bSJed Brown 38929566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex,geom,count + cLocalEnd,quad,t,pforest->topo->conn,coords)); 38930a96aa3bSJed Brown } 38940a96aa3bSJed Brown } 38950a96aa3bSJed Brown } 38969566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordLocalVec,&coords)); 38970a96aa3bSJed Brown PetscFunctionReturn(0); 38980a96aa3bSJed Brown } 38990a96aa3bSJed Brown 3900*852b71a7SToby Isaac static PetscErrorCode PforestQuadrantIsInterior (p4est_quadrant_t *quad, PetscBool *is_interior) 3901*852b71a7SToby Isaac { 3902*852b71a7SToby Isaac PetscFunctionBegin; 3903*852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN (quad->level); 3904*852b71a7SToby Isaac if ((quad->x > 0) && (quad->x + h < P4EST_ROOT_LEN) 3905*852b71a7SToby Isaac #ifdef P4_TO_P8 3906*852b71a7SToby Isaac && (quad->z > 0) && (quad->z + h < P4EST_ROOT_LEN) 3907*852b71a7SToby Isaac #endif 3908*852b71a7SToby Isaac && (quad->y > 0) && (quad->y + h < P4EST_ROOT_LEN)) { 3909*852b71a7SToby Isaac *is_interior = PETSC_TRUE; 3910*852b71a7SToby Isaac } else { 3911*852b71a7SToby Isaac *is_interior = PETSC_FALSE; 3912*852b71a7SToby Isaac } 3913*852b71a7SToby Isaac PetscFunctionReturn(0); 3914*852b71a7SToby Isaac } 3915*852b71a7SToby Isaac 3916*852b71a7SToby Isaac /* We always use DG coordinates with p4est: if they do not match the vertex 3917*852b71a7SToby Isaac coordinates, add space for them in the section */ 3918*852b71a7SToby 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) 3919*852b71a7SToby Isaac { 3920*852b71a7SToby Isaac PetscBool is_interior; 3921*852b71a7SToby Isaac 3922*852b71a7SToby Isaac PetscFunctionBegin; 3923*852b71a7SToby Isaac PetscCall(PforestQuadrantIsInterior(quad, &is_interior)); 3924*852b71a7SToby Isaac if (is_interior) { // quads in the interior of a coarse cell can't touch periodic interfaces 3925*852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3926*852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3927*852b71a7SToby Isaac } else { 3928*852b71a7SToby Isaac PetscInt cSize; 3929*852b71a7SToby Isaac PetscScalar *values = NULL; 3930*852b71a7SToby Isaac PetscBool same_coords = PETSC_TRUE; 3931*852b71a7SToby Isaac 3932*852b71a7SToby Isaac PetscCall(DMPlexVecGetClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3933*852b71a7SToby Isaac PetscAssert(cSize == cDim * P4EST_CHILDREN, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected closure size"); 3934*852b71a7SToby Isaac for (int c = 0; c < P4EST_CHILDREN; c++) { 3935*852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3936*852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN (quad->level); 3937*852b71a7SToby Isaac double corner_coords[3]; 3938*852b71a7SToby Isaac double vert_coords[3]; 3939*852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 3940*852b71a7SToby Isaac 3941*852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) { 3942*852b71a7SToby Isaac vert_coords[d] = PetscRealPart(values[c * cDim + d]); 3943*852b71a7SToby Isaac } 3944*852b71a7SToby Isaac 3945*852b71a7SToby Isaac quad_coords[0] = quad->x; 3946*852b71a7SToby Isaac quad_coords[1] = quad->y; 3947*852b71a7SToby Isaac #ifdef P4_TO_P8 3948*852b71a7SToby Isaac quad_coords[2] = quad->z; 3949*852b71a7SToby Isaac #endif 3950*852b71a7SToby Isaac for (int d = 0; d < 3; d++) { 3951*852b71a7SToby Isaac quad_coords[d] += (corner & (1 << d)) ? h : 0; 3952*852b71a7SToby Isaac } 3953*852b71a7SToby Isaac #ifndef P4_TO_P8 3954*852b71a7SToby Isaac PetscStackCallP4est(p4est_qcoord_to_vertex,(pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 3955*852b71a7SToby Isaac #else 3956*852b71a7SToby Isaac PetscStackCallP4est(p4est_qcoord_to_vertex,(pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 3957*852b71a7SToby Isaac #endif 3958*852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) { 3959*852b71a7SToby Isaac if (fabs (vert_coords[d] - corner_coords[d]) > PETSC_SMALL) { 3960*852b71a7SToby Isaac same_coords = PETSC_FALSE; 3961*852b71a7SToby Isaac break; 3962*852b71a7SToby Isaac } 3963*852b71a7SToby Isaac } 3964*852b71a7SToby Isaac } 3965*852b71a7SToby Isaac if (same_coords) { 3966*852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0)); 3967*852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0)); 3968*852b71a7SToby Isaac } else { 3969*852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, cSize)); 3970*852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, cSize)); 3971*852b71a7SToby Isaac } 3972*852b71a7SToby Isaac PetscCall(DMPlexVecRestoreClosure(plex, oldSection, cVecOld, cell, &cSize, &values)); 3973*852b71a7SToby Isaac } 3974*852b71a7SToby Isaac PetscFunctionReturn(0); 3975*852b71a7SToby Isaac } 3976*852b71a7SToby Isaac 3977*852b71a7SToby Isaac static PetscErrorCode PforestLocalizeCell(DM plex, PetscInt cDim, DM_Forest_pforest *pforest, PetscSection newSection, PetscInt cell, PetscInt coarsePoint, p4est_quadrant_t *quad, PetscScalar coords[]) 3978*852b71a7SToby Isaac { 3979*852b71a7SToby Isaac PetscInt cdof, off; 3980*852b71a7SToby Isaac 3981*852b71a7SToby Isaac PetscFunctionBegin; 3982*852b71a7SToby Isaac PetscCall(PetscSectionGetDof(newSection, cell, &cdof)); 3983*852b71a7SToby Isaac if (!cdof) PetscFunctionReturn(0); 3984*852b71a7SToby Isaac 3985*852b71a7SToby Isaac PetscCall(PetscSectionGetOffset(newSection, cell, &off)); 3986*852b71a7SToby Isaac for (PetscInt c = 0, pos = off; c < P4EST_CHILDREN; c++) { 3987*852b71a7SToby Isaac p4est_qcoord_t quad_coords[3]; 3988*852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN (quad->level); 3989*852b71a7SToby Isaac double corner_coords[3]; 3990*852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c]; 3991*852b71a7SToby Isaac 3992*852b71a7SToby Isaac quad_coords[0] = quad->x; 3993*852b71a7SToby Isaac quad_coords[1] = quad->y; 3994*852b71a7SToby Isaac #ifdef P4_TO_P8 3995*852b71a7SToby Isaac quad_coords[2] = quad->z; 3996*852b71a7SToby Isaac #endif 3997*852b71a7SToby Isaac for (int d = 0; d < 3; d++) { 3998*852b71a7SToby Isaac quad_coords[d] += (corner & (1 << d)) ? h : 0; 3999*852b71a7SToby Isaac } 4000*852b71a7SToby Isaac #ifndef P4_TO_P8 4001*852b71a7SToby Isaac PetscStackCallP4est(p4est_qcoord_to_vertex,(pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords)); 4002*852b71a7SToby Isaac #else 4003*852b71a7SToby Isaac PetscStackCallP4est(p4est_qcoord_to_vertex,(pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords)); 4004*852b71a7SToby Isaac #endif 4005*852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) { 4006*852b71a7SToby Isaac coords[pos++] = corner_coords[d]; 4007*852b71a7SToby Isaac } 4008*852b71a7SToby Isaac for (PetscInt d = PetscMin(cDim, 3); d < cDim; d++) { 4009*852b71a7SToby Isaac coords[pos++] = 0.; 4010*852b71a7SToby Isaac } 4011*852b71a7SToby Isaac } 4012*852b71a7SToby Isaac PetscFunctionReturn(0); 4013*852b71a7SToby Isaac } 4014*852b71a7SToby Isaac 40150a96aa3bSJed Brown static PetscErrorCode DMPforestLocalizeCoordinates(DM dm, DM plex) 40160a96aa3bSJed Brown { 40170a96aa3bSJed Brown DM_Forest *forest; 40180a96aa3bSJed Brown DM_Forest_pforest *pforest; 40196858538eSMatthew G. Knepley DM base, cdm, cdmCell; 4020*852b71a7SToby Isaac Vec cVec, cVecOld; 4021*852b71a7SToby Isaac PetscSection oldSection, newSection; 40220a96aa3bSJed Brown PetscScalar *coords2; 40236858538eSMatthew G. Knepley const PetscReal *L; 40240a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, coarsePoint; 4025*852b71a7SToby Isaac PetscInt cDim, newStart, newEnd; 4026*852b71a7SToby Isaac PetscInt v, vStart, vEnd, cp, cStart, cEnd, cEndInterior; 40270a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 40280a96aa3bSJed Brown p4est_tree_t *trees; 40296858538eSMatthew G. Knepley PetscBool baseLocalized = PETSC_FALSE; 40300a96aa3bSJed Brown 40310a96aa3bSJed Brown PetscFunctionBegin; 40326858538eSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm,NULL,&L)); 40330a96aa3bSJed Brown /* we localize on all cells if we don't have a base DM or the base DM coordinates have not been localized */ 40349566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cDim)); 40359566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 40366858538eSMatthew G. Knepley if (base) PetscCall(DMGetCoordinatesLocalized(base,&baseLocalized)); 40370a96aa3bSJed Brown if (!baseLocalized) base = NULL; 40386858538eSMatthew G. Knepley if (!baseLocalized && !L) PetscFunctionReturn(0); 40399566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &newStart, &newEnd)); 40400a96aa3bSJed Brown 40419566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) dm), &newSection)); 40429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(newSection, 1)); 40439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(newSection, 0, cDim)); 40449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSection, newStart, newEnd)); 40450a96aa3bSJed Brown 40469566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &oldSection)); 40479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd)); 4048*852b71a7SToby Isaac PetscCall(DMGetCoordinatesLocal(plex, &cVecOld)); 40490a96aa3bSJed Brown 40500a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 40510a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 40520a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 40530a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 40540a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 40550a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 40560a96aa3bSJed Brown trees = (p4est_tree_t*) pforest->forest->trees->array; 40570a96aa3bSJed Brown 40589566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 40599566063dSJacob Faibussowitsch PetscCall(DMPlexGetGhostCellStratum(plex, &cEndInterior, NULL)); 40600a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 4061*852b71a7SToby Isaac cp = 0; 40620a96aa3bSJed Brown if (cLocalStart > 0) { 40630a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 4064*852b71a7SToby Isaac PetscInt cell; 40650a96aa3bSJed Brown 4066*852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 4067*852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 4068*852b71a7SToby Isaac 40690a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 4070*852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 40710a96aa3bSJed Brown } 40720a96aa3bSJed Brown } 40730a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 40740a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 40750a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 40760a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 4077*852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 40780a96aa3bSJed Brown PetscInt i; 40790a96aa3bSJed Brown 40800a96aa3bSJed Brown if (!numQuads) continue; 40810a96aa3bSJed Brown coarsePoint = t; 4082*852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 4083*852b71a7SToby Isaac PetscInt cell = i + offset; 4084*852b71a7SToby Isaac p4est_quadrant_t * quad = &quads[i]; 40850a96aa3bSJed Brown 4086*852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 40870a96aa3bSJed Brown } 40880a96aa3bSJed Brown } 40890a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 40900a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 40910a96aa3bSJed Brown PetscInt numGhosts = (PetscInt) pforest->ghost->ghosts.elem_count; 40920a96aa3bSJed Brown PetscInt count; 40930a96aa3bSJed Brown 4094*852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 40950a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 40960a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 4097*852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 40980a96aa3bSJed Brown 4099*852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad)); 41000a96aa3bSJed Brown } 41010a96aa3bSJed Brown } 4102*852b71a7SToby Isaac PetscAssert(cp == cEnd - cStart,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of fine cells %" PetscInt_FMT " != %" PetscInt_FMT,cp,cEnd-cStart); 41030a96aa3bSJed Brown 41049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSection)); 41056858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(plex, &cdm)); 41066858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 41076858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(plex, cdmCell)); 41086858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 41096858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(plex, cDim, newSection)); 41109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &v)); 41119566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &cVec)); 41129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject) cVec, "coordinates")); 41139566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(cVec, cDim)); 41149566063dSJacob Faibussowitsch PetscCall(VecSetSizes(cVec, v, PETSC_DETERMINE)); 41159566063dSJacob Faibussowitsch PetscCall(VecSetType(cVec, VECSTANDARD)); 41169566063dSJacob Faibussowitsch PetscCall(VecSet(cVec, PETSC_MIN_REAL)); 41170a96aa3bSJed Brown 41180a96aa3bSJed Brown /* Localize coordinates on cells if needed */ 41196858538eSMatthew G. Knepley PetscCall(VecGetArray(cVec, &coords2)); 4120*852b71a7SToby Isaac cp = 0; 4121*852b71a7SToby Isaac if (cLocalStart > 0) { 4122*852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 4123*852b71a7SToby Isaac PetscInt cell; 4124*852b71a7SToby Isaac 4125*852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) { 4126*852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell]; 4127*852b71a7SToby Isaac 4128*852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 4129*852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 4130*852b71a7SToby Isaac } 4131*852b71a7SToby Isaac } 41320a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 41330a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 41340a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 41350a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 4136*852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 4137*852b71a7SToby Isaac PetscInt i; 41380a96aa3bSJed Brown 41390a96aa3bSJed Brown if (!numQuads) continue; 4140*852b71a7SToby Isaac coarsePoint = t; 4141*852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) { 4142*852b71a7SToby Isaac PetscInt cell = i + offset; 41430a96aa3bSJed Brown p4est_quadrant_t * quad = &quads[i]; 41440a96aa3bSJed Brown 4145*852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 4146*852b71a7SToby Isaac } 4147*852b71a7SToby Isaac } 4148*852b71a7SToby Isaac if (cLocalEnd - cLocalStart < cEnd - cStart) { 4149*852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 4150*852b71a7SToby Isaac PetscInt numGhosts = (PetscInt) pforest->ghost->ghosts.elem_count; 4151*852b71a7SToby Isaac PetscInt count; 41520a96aa3bSJed Brown 4153*852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) { 4154*852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 4155*852b71a7SToby Isaac coarsePoint = quad->p.which_tree; 4156*852b71a7SToby Isaac PetscInt cell = count + cLocalEnd; 41570a96aa3bSJed Brown 4158*852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2)); 41590a96aa3bSJed Brown } 41600a96aa3bSJed Brown } 41619566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cVec, &coords2)); 41626858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(plex, cVec)); 41639566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cVec)); 41649566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newSection)); 41650a96aa3bSJed Brown PetscFunctionReturn(0); 41660a96aa3bSJed Brown } 41670a96aa3bSJed Brown 41680a96aa3bSJed Brown #define DMForestClearAdaptivityForest_pforest _append_pforest(DMForestClearAdaptivityForest) 41690a96aa3bSJed Brown static PetscErrorCode DMForestClearAdaptivityForest_pforest(DM dm) 41700a96aa3bSJed Brown { 41710a96aa3bSJed Brown DM_Forest *forest; 41720a96aa3bSJed Brown DM_Forest_pforest *pforest; 41730a96aa3bSJed Brown 41740a96aa3bSJed Brown PetscFunctionBegin; 41750a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 41760a96aa3bSJed Brown pforest = (DM_Forest_pforest *) forest->data; 41779566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&(pforest->pointAdaptToSelfSF))); 41789566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&(pforest->pointSelfToAdaptSF))); 41799566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids)); 41809566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids)); 41810a96aa3bSJed Brown PetscFunctionReturn(0); 41820a96aa3bSJed Brown } 41830a96aa3bSJed Brown 41840a96aa3bSJed Brown static PetscErrorCode DMConvert_pforest_plex(DM dm, DMType newtype, DM *plex) 41850a96aa3bSJed Brown { 41860a96aa3bSJed Brown DM_Forest *forest; 41870a96aa3bSJed Brown DM_Forest_pforest *pforest; 41880a96aa3bSJed Brown DM refTree, newPlex, base; 41890a96aa3bSJed Brown PetscInt adjDim, adjCodim, coordDim; 41900a96aa3bSJed Brown MPI_Comm comm; 41910a96aa3bSJed Brown PetscBool isPforest; 41920a96aa3bSJed Brown PetscInt dim; 41930a96aa3bSJed Brown PetscInt overlap; 41940a96aa3bSJed Brown p4est_connect_type_t ctype; 41950a96aa3bSJed Brown p4est_locidx_t first_local_quad = -1; 41960a96aa3bSJed Brown sc_array_t *points_per_dim, *cone_sizes, *cones, *cone_orientations, *coords, *children, *parents, *childids, *leaves, *remotes; 41970a96aa3bSJed Brown PetscSection parentSection; 41980a96aa3bSJed Brown PetscSF pointSF; 41990a96aa3bSJed Brown size_t zz, count; 42000a96aa3bSJed Brown PetscInt pStart, pEnd; 42010a96aa3bSJed Brown DMLabel ghostLabelBase = NULL; 42020a96aa3bSJed Brown 42030a96aa3bSJed Brown PetscFunctionBegin; 42040a96aa3bSJed Brown 42050a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 42060a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 42079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMPFOREST,&isPforest)); 420828b400f6SJacob Faibussowitsch PetscCheck(isPforest,comm,PETSC_ERR_ARG_WRONG,"Expected DM type %s, got %s",DMPFOREST,((PetscObject)dm)->type_name); 42099566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm,&dim)); 421063a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM,comm,PETSC_ERR_ARG_WRONG,"Expected DM dimension %d, got %" PetscInt_FMT,P4EST_DIM,dim); 42110a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 42120a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 42139566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 42140a96aa3bSJed Brown if (base) { 42159566063dSJacob Faibussowitsch PetscCall(DMGetLabel(base,"ghost",&ghostLabelBase)); 42160a96aa3bSJed Brown } 42170a96aa3bSJed Brown if (!pforest->plex) { 42180a96aa3bSJed Brown PetscMPIInt size; 42190a96aa3bSJed Brown 42209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 42219566063dSJacob Faibussowitsch PetscCall(DMCreate(comm,&newPlex)); 42229566063dSJacob Faibussowitsch PetscCall(DMSetType(newPlex,DMPLEX)); 42239566063dSJacob Faibussowitsch PetscCall(DMSetMatType(newPlex,dm->mattype)); 42240a96aa3bSJed Brown /* share labels */ 42259566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, newPlex, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 42269566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyDimension(dm,&adjDim)); 42279566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyCodimension(dm,&adjCodim)); 42289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm,&coordDim)); 42290a96aa3bSJed Brown if (adjDim == 0) { 42300a96aa3bSJed Brown ctype = P4EST_CONNECT_FULL; 42310a96aa3bSJed Brown } else if (adjCodim == 1) { 42320a96aa3bSJed Brown ctype = P4EST_CONNECT_FACE; 42330a96aa3bSJed Brown #if defined(P4_TO_P8) 42340a96aa3bSJed Brown } else if (adjDim == 1) { 42350a96aa3bSJed Brown ctype = P8EST_CONNECT_EDGE; 42360a96aa3bSJed Brown #endif 42370a96aa3bSJed Brown } else { 423863a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONG,"Invalid adjacency dimension %" PetscInt_FMT,adjDim); 42390a96aa3bSJed Brown } 424063a3b9bcSJacob 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); 42419566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm,&overlap)); 424260667520SVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(newPlex,NULL,overlap)); 42430a96aa3bSJed Brown 42440a96aa3bSJed Brown points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 42450a96aa3bSJed Brown cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 42460a96aa3bSJed Brown cones = sc_array_new(sizeof(p4est_locidx_t)); 42470a96aa3bSJed Brown cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 42480a96aa3bSJed Brown coords = sc_array_new(3 * sizeof(double)); 42490a96aa3bSJed Brown children = sc_array_new(sizeof(p4est_locidx_t)); 42500a96aa3bSJed Brown parents = sc_array_new(sizeof(p4est_locidx_t)); 42510a96aa3bSJed Brown childids = sc_array_new(sizeof(p4est_locidx_t)); 42520a96aa3bSJed Brown leaves = sc_array_new(sizeof(p4est_locidx_t)); 42530a96aa3bSJed Brown remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 42540a96aa3bSJed Brown 42550a96aa3bSJed Brown PetscStackCallP4est(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)); 42560a96aa3bSJed Brown 42570a96aa3bSJed Brown pforest->cLocalStart = (PetscInt) first_local_quad; 42580a96aa3bSJed Brown pforest->cLocalEnd = pforest->cLocalStart + (PetscInt) pforest->forest->local_num_quadrants; 42599566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim)); 42609566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes)); 42619566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones)); 42629566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations)); 42639566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, coordDim)); 42649566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(children)); 42659566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(parents)); 42669566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(childids)); 42679566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(leaves)); 42689566063dSJacob Faibussowitsch PetscCall(locidx_pair_to_PetscSFNode(remotes)); 42690a96aa3bSJed Brown 42709566063dSJacob Faibussowitsch PetscCall(DMSetDimension(newPlex,P4EST_DIM)); 42719566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(newPlex,coordDim)); 42729566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(newPlex,P4EST_DIM - 1)); 42739566063dSJacob 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)); 42749566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(newPlex)); 42759566063dSJacob Faibussowitsch PetscCall(DMCreateReferenceTree_pforest(comm,&refTree)); 42769566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlex,refTree)); 42779566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm,&parentSection)); 42789566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(newPlex,&pStart,&pEnd)); 42799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection,pStart,pEnd)); 42800a96aa3bSJed Brown count = children->elem_count; 42810a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 42820a96aa3bSJed Brown PetscInt child = *((PetscInt*) sc_array_index(children,zz)); 42830a96aa3bSJed Brown 42849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(parentSection,child,1)); 42850a96aa3bSJed Brown } 42869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection)); 42879566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(newPlex,parentSection,(PetscInt*)parents->array,(PetscInt*)childids->array)); 42889566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection)); 42899566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm,&pointSF)); 42900a96aa3bSJed Brown /* 42910a96aa3bSJed Brown These arrays defining the sf are from the p4est library, but the code there shows the leaves being populated in increasing order. 42920a96aa3bSJed Brown https://gitlab.com/petsc/petsc/merge_requests/2248#note_240186391 42930a96aa3bSJed Brown */ 42949566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(pointSF,pEnd - pStart,(PetscInt)leaves->elem_count,(PetscInt*)leaves->array,PETSC_COPY_VALUES,(PetscSFNode*)remotes->array,PETSC_COPY_VALUES)); 42959566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(newPlex,pointSF)); 42969566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm,pointSF)); 42970a96aa3bSJed Brown { 42980a96aa3bSJed Brown DM coordDM; 42990a96aa3bSJed Brown 43009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM)); 43019566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(coordDM,pointSF)); 43020a96aa3bSJed Brown } 43039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointSF)); 43040a96aa3bSJed Brown sc_array_destroy (points_per_dim); 43050a96aa3bSJed Brown sc_array_destroy (cone_sizes); 43060a96aa3bSJed Brown sc_array_destroy (cones); 43070a96aa3bSJed Brown sc_array_destroy (cone_orientations); 43080a96aa3bSJed Brown sc_array_destroy (coords); 43090a96aa3bSJed Brown sc_array_destroy (children); 43100a96aa3bSJed Brown sc_array_destroy (parents); 43110a96aa3bSJed Brown sc_array_destroy (childids); 43120a96aa3bSJed Brown sc_array_destroy (leaves); 43130a96aa3bSJed Brown sc_array_destroy (remotes); 43140a96aa3bSJed Brown 43150a96aa3bSJed Brown { 43160a96aa3bSJed Brown const PetscReal *maxCell, *L; 43170a96aa3bSJed Brown 43186858538eSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm,&maxCell,&L)); 43196858538eSMatthew G. Knepley PetscCall(DMSetPeriodicity(newPlex,maxCell,L)); 43209566063dSJacob Faibussowitsch PetscCall(DMPforestLocalizeCoordinates(dm,newPlex)); 43210a96aa3bSJed Brown } 43220a96aa3bSJed Brown 43230a96aa3bSJed Brown if (overlap > 0) { /* the p4est routine can't set all of the coordinates in its routine if there is overlap */ 43240a96aa3bSJed Brown Vec coordsGlobal, coordsLocal; 43250a96aa3bSJed Brown const PetscScalar *globalArray; 43260a96aa3bSJed Brown PetscScalar *localArray; 43270a96aa3bSJed Brown PetscSF coordSF; 43280a96aa3bSJed Brown DM coordDM; 43290a96aa3bSJed Brown 43309566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM)); 43319566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(coordDM,&coordSF)); 43329566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(newPlex, &coordsGlobal)); 43339566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coordsLocal)); 43349566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordsGlobal, &globalArray)); 43359566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordsLocal, &localArray)); 43369566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coordSF,MPIU_SCALAR,globalArray,localArray,MPI_REPLACE)); 43379566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coordSF,MPIU_SCALAR,globalArray,localArray,MPI_REPLACE)); 43389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordsLocal, &localArray)); 43399566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordsGlobal, &globalArray)); 43409566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(newPlex, coordsLocal)); 43410a96aa3bSJed Brown } 43429566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates(dm,newPlex)); 43430a96aa3bSJed Brown 43440a96aa3bSJed Brown pforest->plex = newPlex; 43450a96aa3bSJed Brown 43460a96aa3bSJed Brown /* copy labels */ 43479566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsFinalize(dm,newPlex)); 43480a96aa3bSJed Brown 43490a96aa3bSJed Brown if (ghostLabelBase || pforest->ghostName) { /* we have to do this after copying labels because the labels drive the construction of ghost cells */ 43500a96aa3bSJed Brown PetscInt numAdded; 43510a96aa3bSJed Brown DM newPlexGhosted; 43520a96aa3bSJed Brown void *ctx; 43530a96aa3bSJed Brown 43549566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(newPlex,pforest->ghostName,&numAdded,&newPlexGhosted)); 43559566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(newPlex,&ctx)); 43569566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(newPlexGhosted,ctx)); 43570a96aa3bSJed Brown /* we want the sf for the ghost dm to be the one for the p4est dm as well */ 43589566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(newPlexGhosted,&pointSF)); 43599566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm,pointSF)); 43609566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newPlex)); 43619566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlexGhosted,refTree)); 43629566063dSJacob Faibussowitsch PetscCall(DMForestClearAdaptivityForest_pforest(dm)); 43630a96aa3bSJed Brown newPlex = newPlexGhosted; 43640a96aa3bSJed Brown 43650a96aa3bSJed Brown /* share the labels back */ 43669566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 43679566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(newPlex, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 43680a96aa3bSJed Brown pforest->plex = newPlex; 43690a96aa3bSJed Brown } 43709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&refTree)); 43710a96aa3bSJed Brown if (dm->setfromoptionscalled) { 43725f80ce2aSJacob Faibussowitsch 4373d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)newPlex); 43749566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject,newPlex)); 43759566063dSJacob Faibussowitsch PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)newPlex)); 4376d0609cedSBarry Smith PetscOptionsEnd(); 43770a96aa3bSJed Brown } 43789566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(newPlex,NULL,"-dm_p4est_plex_view")); 43790a96aa3bSJed Brown { 43806858538eSMatthew G. Knepley DM cdm; 43810a96aa3bSJed Brown PetscSection coordsSec; 43820a96aa3bSJed Brown Vec coords; 43830a96aa3bSJed Brown PetscInt cDim; 43840a96aa3bSJed Brown 43859566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(newPlex, &cDim)); 43869566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(newPlex, &coordsSec)); 43879566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dm,cDim, coordsSec)); 43889566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coords)); 43899566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 43906858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex, &cdm)); 43916858538eSMatthew G. Knepley if (cdm) PetscCall(DMSetCellCoordinateDM(dm, cdm)); 43926858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(newPlex, &coordsSec)); 43936858538eSMatthew G. Knepley if (coordsSec) PetscCall(DMSetCellCoordinateSection(dm, cDim, coordsSec)); 43946858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(newPlex, &coords)); 43956858538eSMatthew G. Knepley if (coords) PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 43960a96aa3bSJed Brown } 43970a96aa3bSJed Brown } 43980a96aa3bSJed Brown newPlex = pforest->plex; 43990a96aa3bSJed Brown if (plex) { 44009566063dSJacob Faibussowitsch PetscCall(DMClone(newPlex,plex)); 44016858538eSMatthew G. Knepley #if 0 44029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM)); 44039566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(*plex,coordDM)); 44046858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex,&coordDM)); 44056858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*plex,coordDM)); 44066858538eSMatthew G. Knepley #endif 44079566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm,*plex)); 44080a96aa3bSJed Brown } 44090a96aa3bSJed Brown PetscFunctionReturn(0); 44100a96aa3bSJed Brown } 44110a96aa3bSJed Brown 44120a96aa3bSJed Brown static PetscErrorCode DMSetFromOptions_pforest(PetscOptionItems *PetscOptionsObject,DM dm) 44130a96aa3bSJed Brown { 44140a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 44150a96aa3bSJed Brown char stringBuffer[256]; 44160a96aa3bSJed Brown PetscBool flg; 44170a96aa3bSJed Brown 44180a96aa3bSJed Brown PetscFunctionBegin; 44199566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions_Forest(PetscOptionsObject,dm)); 4420d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject,"DM" P4EST_STRING " options"); 44219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_p4est_partition_for_coarsening","partition forest to allow for coarsening","DMP4estSetPartitionForCoarsening",pforest->partition_for_coarsening,&(pforest->partition_for_coarsening),NULL)); 44229566063dSJacob 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)); 4423d0609cedSBarry Smith PetscOptionsHeadEnd(); 44240a96aa3bSJed Brown if (flg) { 44259566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName)); 44269566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(stringBuffer,&pforest->ghostName)); 44270a96aa3bSJed Brown } 44280a96aa3bSJed Brown PetscFunctionReturn(0); 44290a96aa3bSJed Brown } 44300a96aa3bSJed Brown 44310a96aa3bSJed Brown #if !defined(P4_TO_P8) 44320a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP4estGetPartitionForCoarsening 44330a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP4estSetPartitionForCoarsening 44340a96aa3bSJed Brown #else 44350a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP8estGetPartitionForCoarsening 44360a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP8estSetPartitionForCoarsening 44370a96aa3bSJed Brown #endif 44380a96aa3bSJed Brown 44390a96aa3bSJed Brown PETSC_EXTERN PetscErrorCode DMPforestGetPartitionForCoarsening(DM dm, PetscBool *flg) 44400a96aa3bSJed Brown { 44410a96aa3bSJed Brown DM_Forest_pforest *pforest; 44420a96aa3bSJed Brown 44430a96aa3bSJed Brown PetscFunctionBegin; 44440a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 44450a96aa3bSJed Brown pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 44460a96aa3bSJed Brown *flg = pforest->partition_for_coarsening; 44470a96aa3bSJed Brown PetscFunctionReturn(0); 44480a96aa3bSJed Brown } 44490a96aa3bSJed Brown 44500a96aa3bSJed Brown PETSC_EXTERN PetscErrorCode DMPforestSetPartitionForCoarsening(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 pforest->partition_for_coarsening = flg; 44580a96aa3bSJed Brown PetscFunctionReturn(0); 44590a96aa3bSJed Brown } 44600a96aa3bSJed Brown 44610a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM dm,DM *plex) 44620a96aa3bSJed Brown { 44630a96aa3bSJed Brown DM_Forest_pforest *pforest; 44640a96aa3bSJed Brown 44650a96aa3bSJed Brown PetscFunctionBegin; 44660a96aa3bSJed Brown if (plex) *plex = NULL; 44679566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 44680a96aa3bSJed Brown pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 44690a96aa3bSJed Brown if (!pforest->plex) { 44709566063dSJacob Faibussowitsch PetscCall(DMConvert_pforest_plex(dm,DMPLEX,NULL)); 44710a96aa3bSJed Brown } 44729566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm,pforest->plex)); 44730a96aa3bSJed Brown if (plex) *plex = pforest->plex; 44740a96aa3bSJed Brown PetscFunctionReturn(0); 44750a96aa3bSJed Brown } 44760a96aa3bSJed Brown 44770a96aa3bSJed Brown #define DMCreateInterpolation_pforest _append_pforest(DMCreateInterpolation) 44780a96aa3bSJed Brown static PetscErrorCode DMCreateInterpolation_pforest(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 44790a96aa3bSJed Brown { 44800a96aa3bSJed Brown PetscSection gsc, gsf; 44810a96aa3bSJed Brown PetscInt m, n; 44820a96aa3bSJed Brown DM cdm; 44830a96aa3bSJed Brown 44840a96aa3bSJed Brown PetscFunctionBegin; 44859566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 44869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 44879566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 44889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 44890a96aa3bSJed Brown 44909566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmFine), interpolation)); 44919566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 44929566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, MATAIJ)); 44930a96aa3bSJed Brown 44949566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 449508401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse,PetscObjectComm((PetscObject)dmFine),PETSC_ERR_SUP,"Only interpolation from coarse DM for now"); 44960a96aa3bSJed Brown 44970a96aa3bSJed Brown { 44980a96aa3bSJed Brown DM plexF, plexC; 44990a96aa3bSJed Brown PetscSF sf; 45000a96aa3bSJed Brown PetscInt *cids; 45010a96aa3bSJed Brown PetscInt dofPerDim[4] = {1,1,1,1}; 45020a96aa3bSJed Brown 45039566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse,&plexC)); 45049566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine,&plexF)); 45059566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 45069566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 45079566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInterpolatorTree(plexC, plexF, sf, cids, *interpolation)); 45089566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 45099566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 45100a96aa3bSJed Brown } 45119566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 45120a96aa3bSJed Brown /* Use naive scaling */ 45139566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 45140a96aa3bSJed Brown PetscFunctionReturn(0); 45150a96aa3bSJed Brown } 45160a96aa3bSJed Brown 45170a96aa3bSJed Brown #define DMCreateInjection_pforest _append_pforest(DMCreateInjection) 45180a96aa3bSJed Brown static PetscErrorCode DMCreateInjection_pforest(DM dmCoarse, DM dmFine, Mat *injection) 45190a96aa3bSJed Brown { 45200a96aa3bSJed Brown PetscSection gsc, gsf; 45210a96aa3bSJed Brown PetscInt m, n; 45220a96aa3bSJed Brown DM cdm; 45230a96aa3bSJed Brown 45240a96aa3bSJed Brown PetscFunctionBegin; 45259566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 45269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &n)); 45279566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 45289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &m)); 45290a96aa3bSJed Brown 45309566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject) dmFine), injection)); 45319566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*injection, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 45329566063dSJacob Faibussowitsch PetscCall(MatSetType(*injection, MATAIJ)); 45330a96aa3bSJed Brown 45349566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 453508401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse,PetscObjectComm((PetscObject)dmFine),PETSC_ERR_SUP,"Only injection to coarse DM for now"); 45360a96aa3bSJed Brown 45370a96aa3bSJed Brown { 45380a96aa3bSJed Brown DM plexF, plexC; 45390a96aa3bSJed Brown PetscSF sf; 45400a96aa3bSJed Brown PetscInt *cids; 45410a96aa3bSJed Brown PetscInt dofPerDim[4] = {1,1,1,1}; 45420a96aa3bSJed Brown 45439566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse,&plexC)); 45449566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine,&plexF)); 45459566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids)); 45469566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 45479566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorTree(plexC, plexF, sf, cids, *injection)); 45489566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 45499566063dSJacob Faibussowitsch PetscCall(PetscFree(cids)); 45500a96aa3bSJed Brown } 45519566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*injection, NULL, "-inject_mat_view")); 45520a96aa3bSJed Brown /* Use naive scaling */ 45530a96aa3bSJed Brown PetscFunctionReturn(0); 45540a96aa3bSJed Brown } 45550a96aa3bSJed Brown 45560a96aa3bSJed Brown #define DMForestTransferVecFromBase_pforest _append_pforest(DMForestTransferVecFromBase) 45570a96aa3bSJed Brown static PetscErrorCode DMForestTransferVecFromBase_pforest(DM dm, Vec vecIn, Vec vecOut) 45580a96aa3bSJed Brown { 45590a96aa3bSJed Brown DM dmIn, dmVecIn, base, basec, plex, coarseDM; 45600a96aa3bSJed Brown DM *hierarchy; 45610a96aa3bSJed Brown PetscSF sfRed = NULL; 45620a96aa3bSJed Brown PetscDS ds; 45630a96aa3bSJed Brown Vec vecInLocal, vecOutLocal; 45640a96aa3bSJed Brown DMLabel subpointMap; 45650a96aa3bSJed Brown PetscInt minLevel, mh, n_hi, i; 45660a96aa3bSJed Brown PetscBool hiforest, *hierarchy_forest; 45670a96aa3bSJed Brown 45680a96aa3bSJed Brown PetscFunctionBegin; 45699566063dSJacob Faibussowitsch PetscCall(VecGetDM(vecIn,&dmVecIn)); 45709566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmVecIn,&ds)); 457128b400f6SJacob Faibussowitsch PetscCheck(ds,PetscObjectComm((PetscObject)dmVecIn),PETSC_ERR_SUP,"Cannot transfer without a PetscDS object"); 45720a96aa3bSJed Brown { /* we cannot stick user contexts into function callbacks for DMProjectFieldLocal! */ 45730a96aa3bSJed Brown PetscSection section; 45740a96aa3bSJed Brown PetscInt Nf; 45750a96aa3bSJed Brown 45769566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn,§ion)); 45779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section,&Nf)); 457863a3b9bcSJacob 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); 45790a96aa3bSJed Brown } 45809566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm,&minLevel)); 458163a3b9bcSJacob Faibussowitsch PetscCheck(!minLevel,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot transfer with minimum refinement set to %" PetscInt_FMT ". Rerun with DMForestSetMinimumRefinement(dm,0)",minLevel); 45829566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm,&base)); 458328b400f6SJacob Faibussowitsch PetscCheck(base,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing base DM"); 45840a96aa3bSJed Brown 45859566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut,0.0)); 45860a96aa3bSJed Brown if (dmVecIn == base) { /* sequential runs */ 45879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 45880a96aa3bSJed Brown } else { 45890a96aa3bSJed Brown PetscSection secIn, secInRed; 45900a96aa3bSJed Brown Vec vecInRed, vecInLocal; 45910a96aa3bSJed Brown 45929566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)base,"_base_migration_sf",(PetscObject*)&sfRed)); 459328b400f6SJacob Faibussowitsch PetscCheck(sfRed,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not the DM set with DMForestSetBaseDM()"); 45949566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmVecIn),&secInRed)); 45959566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF,&vecInRed)); 45969566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn,&secIn)); 45979566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmVecIn,&vecInLocal)); 45989566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmVecIn,vecIn,INSERT_VALUES,vecInLocal)); 45999566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmVecIn,vecIn,INSERT_VALUES,vecInLocal)); 46009566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dmVecIn,sfRed,secIn,vecInLocal,secInRed,vecInRed)); 46019566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmVecIn,&vecInLocal)); 46029566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secInRed)); 46030a96aa3bSJed Brown vecIn = vecInRed; 46040a96aa3bSJed Brown } 46050a96aa3bSJed Brown 46060a96aa3bSJed Brown /* we first search through the AdaptivityForest hierarchy 46070a96aa3bSJed Brown once we found the first disconnected forest, we upsweep the DM hierarchy */ 46080a96aa3bSJed Brown hiforest = PETSC_TRUE; 46090a96aa3bSJed Brown 46100a96aa3bSJed Brown /* upsweep to the coarsest DM */ 46110a96aa3bSJed Brown n_hi = 0; 46120a96aa3bSJed Brown coarseDM = dm; 46130a96aa3bSJed Brown do { 46140a96aa3bSJed Brown PetscBool isforest; 46150a96aa3bSJed Brown 46160a96aa3bSJed Brown dmIn = coarseDM; 46170a96aa3bSJed Brown /* need to call DMSetUp to have the hierarchy recursively setup */ 46189566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmIn)); 46199566063dSJacob Faibussowitsch PetscCall(DMIsForest(dmIn,&isforest)); 462028b400f6SJacob Faibussowitsch PetscCheck(isforest,PetscObjectComm((PetscObject)dmIn),PETSC_ERR_SUP,"Cannot currently transfer through a mixed hierarchy! Found DM type %s",((PetscObject)dmIn)->type_name); 46210a96aa3bSJed Brown coarseDM = NULL; 46220a96aa3bSJed Brown if (hiforest) { 46239566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn,&coarseDM)); 46240a96aa3bSJed Brown } 46250a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 46260a96aa3bSJed Brown hiforest = PETSC_FALSE; 46279566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn,&coarseDM)); 46280a96aa3bSJed Brown } 46290a96aa3bSJed Brown n_hi++; 46300a96aa3bSJed Brown } while (coarseDM); 46310a96aa3bSJed Brown 46329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n_hi,&hierarchy,n_hi,&hierarchy_forest)); 46330a96aa3bSJed Brown 46340a96aa3bSJed Brown i = 0; 46350a96aa3bSJed Brown hiforest = PETSC_TRUE; 46360a96aa3bSJed Brown coarseDM = dm; 46370a96aa3bSJed Brown do { 46380a96aa3bSJed Brown dmIn = coarseDM; 46390a96aa3bSJed Brown coarseDM = NULL; 46400a96aa3bSJed Brown if (hiforest) { 46419566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn,&coarseDM)); 46420a96aa3bSJed Brown } 46430a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 46440a96aa3bSJed Brown hiforest = PETSC_FALSE; 46459566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn,&coarseDM)); 46460a96aa3bSJed Brown } 46470a96aa3bSJed Brown i++; 46480a96aa3bSJed Brown hierarchy[n_hi - i] = dmIn; 46490a96aa3bSJed Brown } while (coarseDM); 46500a96aa3bSJed Brown 46510a96aa3bSJed Brown /* project base vector on the coarsest forest (minimum refinement = 0) */ 46529566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn,&plex)); 46530a96aa3bSJed Brown 46540a96aa3bSJed Brown /* Check this plex is compatible with the base */ 46550a96aa3bSJed Brown { 46560a96aa3bSJed Brown IS gnum[2]; 46570a96aa3bSJed Brown PetscInt ncells[2],gncells[2]; 46580a96aa3bSJed Brown 46599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(base,&gnum[0])); 46609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(plex,&gnum[1])); 46619566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[0],NULL,&ncells[0])); 46629566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[1],NULL,&ncells[1])); 46631c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(ncells,gncells,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm))); 466463a3b9bcSJacob 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); 46650a96aa3bSJed Brown } 46660a96aa3bSJed Brown 46679566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmIn,"_forest_base_subpoint_map",&subpointMap)); 466828b400f6SJacob Faibussowitsch PetscCheck(subpointMap,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing _forest_base_subpoint_map label"); 46690a96aa3bSJed Brown 46709566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(base,&mh)); 46719566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(plex,mh)); 46720a96aa3bSJed Brown 46739566063dSJacob Faibussowitsch PetscCall(DMClone(base,&basec)); 46749566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmVecIn,basec)); 46750a96aa3bSJed Brown if (sfRed) { 46769566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn)); 46770a96aa3bSJed Brown vecInLocal = vecIn; 46780a96aa3bSJed Brown } else { 46799566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(basec,&vecInLocal)); 46809566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(basec,vecIn,INSERT_VALUES,vecInLocal)); 46819566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(basec,vecIn,INSERT_VALUES,vecInLocal)); 46820a96aa3bSJed Brown } 46830a96aa3bSJed Brown 46849566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn,&vecOutLocal)); 46850a96aa3bSJed Brown { /* get degrees of freedom ordered onto dmIn */ 46860a96aa3bSJed Brown PetscSF basetocoarse; 46870a96aa3bSJed Brown PetscInt bStart, bEnd, nroots; 46880a96aa3bSJed Brown PetscInt iStart, iEnd, nleaves, leaf; 46890a96aa3bSJed Brown PetscMPIInt rank; 46900a96aa3bSJed Brown PetscSFNode *remotes; 46910a96aa3bSJed Brown PetscSection secIn, secOut; 46920a96aa3bSJed Brown PetscInt *remoteOffsets; 46930a96aa3bSJed Brown PetscSF transferSF; 46940a96aa3bSJed Brown const PetscScalar *inArray; 46950a96aa3bSJed Brown PetscScalar *outArray; 46960a96aa3bSJed Brown 46979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)basec), &rank)); 46989566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(basec, &bStart, &bEnd)); 46990a96aa3bSJed Brown nroots = PetscMax(bEnd - bStart, 0); 47009566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &iStart, &iEnd)); 47010a96aa3bSJed Brown nleaves = PetscMax(iEnd - iStart, 0); 47020a96aa3bSJed Brown 47039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotes)); 47040a96aa3bSJed Brown for (leaf = iStart; leaf < iEnd; leaf++) { 47050a96aa3bSJed Brown PetscInt index; 47060a96aa3bSJed Brown 47070a96aa3bSJed Brown remotes[leaf - iStart].rank = rank; 47089566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, leaf, &index)); 47090a96aa3bSJed Brown remotes[leaf - iStart].index = index; 47100a96aa3bSJed Brown } 47110a96aa3bSJed Brown 47129566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)basec), &basetocoarse)); 47139566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(basetocoarse, nroots, nleaves, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 47149566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(basetocoarse)); 47159566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(basec,&secIn)); 47169566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmIn),&secOut)); 47179566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(basetocoarse, secIn, &remoteOffsets, secOut)); 47189566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(basetocoarse, secIn, remoteOffsets, secOut, &transferSF)); 47199566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 47209566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(vecOutLocal, &outArray)); 47219566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecInLocal, &inArray)); 47229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferSF, MPIU_SCALAR, inArray, outArray,MPI_REPLACE)); 47239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferSF, MPIU_SCALAR, inArray, outArray,MPI_REPLACE)); 47249566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecInLocal, &inArray)); 47259566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(vecOutLocal, &outArray)); 47269566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferSF)); 47279566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secOut)); 47289566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&basetocoarse)); 47290a96aa3bSJed Brown } 47309566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecInLocal)); 47319566063dSJacob Faibussowitsch PetscCall(DMDestroy(&basec)); 47329566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecIn)); 47330a96aa3bSJed Brown 47340a96aa3bSJed Brown /* output */ 47350a96aa3bSJed Brown if (n_hi > 1) { /* downsweep the stored hierarchy */ 47360a96aa3bSJed Brown Vec vecOut1, vecOut2; 47370a96aa3bSJed Brown DM fineDM; 47380a96aa3bSJed Brown 47399566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmIn,&vecOut1)); 47409566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn,vecOutLocal,INSERT_VALUES,vecOut1)); 47419566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn,&vecOutLocal)); 47420a96aa3bSJed Brown for (i = 1; i < n_hi-1; i++) { 47430a96aa3bSJed Brown fineDM = hierarchy[i]; 47449566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(fineDM,&vecOut2)); 47459566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn,vecOut1,fineDM,vecOut2,PETSC_TRUE,0.0)); 47469566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn,&vecOut1)); 47470a96aa3bSJed Brown vecOut1 = vecOut2; 47480a96aa3bSJed Brown dmIn = fineDM; 47490a96aa3bSJed Brown } 47509566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn,vecOut1,dm,vecOut,PETSC_TRUE,0.0)); 47519566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn,&vecOut1)); 47520a96aa3bSJed Brown } else { 47539566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn,vecOutLocal,INSERT_VALUES,vecOut)); 47549566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn,&vecOutLocal)); 47550a96aa3bSJed Brown } 47569566063dSJacob Faibussowitsch PetscCall(PetscFree2(hierarchy,hierarchy_forest)); 47570a96aa3bSJed Brown PetscFunctionReturn(0); 47580a96aa3bSJed Brown } 47590a96aa3bSJed Brown 47600a96aa3bSJed Brown #define DMForestTransferVec_pforest _append_pforest(DMForestTransferVec) 47610a96aa3bSJed Brown static PetscErrorCode DMForestTransferVec_pforest(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time) 47620a96aa3bSJed Brown { 47630a96aa3bSJed Brown DM adaptIn, adaptOut, plexIn, plexOut; 47640a96aa3bSJed Brown DM_Forest *forestIn, *forestOut, *forestAdaptIn, *forestAdaptOut; 47650a96aa3bSJed Brown PetscInt dofPerDim[] = {1, 1, 1, 1}; 47660a96aa3bSJed Brown PetscSF inSF = NULL, outSF = NULL; 47670a96aa3bSJed Brown PetscInt *inCids = NULL, *outCids = NULL; 47680a96aa3bSJed Brown DMAdaptFlag purposeIn, purposeOut; 47690a96aa3bSJed Brown 47700a96aa3bSJed Brown PetscFunctionBegin; 47710a96aa3bSJed Brown forestOut = (DM_Forest *) dmOut->data; 47720a96aa3bSJed Brown forestIn = (DM_Forest *) dmIn->data; 47730a96aa3bSJed Brown 47749566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmOut,&adaptOut)); 47759566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmOut,&purposeOut)); 47760a96aa3bSJed Brown forestAdaptOut = adaptOut ? (DM_Forest *) adaptOut->data : NULL; 47770a96aa3bSJed Brown 47789566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn,&adaptIn)); 47799566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmIn,&purposeIn)); 47800a96aa3bSJed Brown forestAdaptIn = adaptIn ? (DM_Forest *) adaptIn->data : NULL; 47810a96aa3bSJed Brown 47820a96aa3bSJed Brown if (forestAdaptOut == forestIn) { 47830a96aa3bSJed Brown switch (purposeOut) { 47840a96aa3bSJed Brown case DM_ADAPT_REFINE: 47859566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids)); 47869566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47870a96aa3bSJed Brown break; 47880a96aa3bSJed Brown case DM_ADAPT_COARSEN: 47890a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 47909566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_TRUE,&outCids)); 47919566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 47920a96aa3bSJed Brown break; 47930a96aa3bSJed Brown default: 47949566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids)); 47959566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_FALSE,&outCids)); 47969566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 47979566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 47980a96aa3bSJed Brown } 47990a96aa3bSJed Brown } else if (forestAdaptIn == forestOut) { 48000a96aa3bSJed Brown switch (purposeIn) { 48010a96aa3bSJed Brown case DM_ADAPT_REFINE: 48029566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_TRUE,&inCids)); 48039566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 48040a96aa3bSJed Brown break; 48050a96aa3bSJed Brown case DM_ADAPT_COARSEN: 48060a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 48079566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids)); 48089566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 48090a96aa3bSJed Brown break; 48100a96aa3bSJed Brown default: 48119566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids)); 48129566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_FALSE,&outCids)); 48139566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF)); 48149566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF)); 48150a96aa3bSJed Brown } 48160a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dmIn),PETSC_ERR_SUP,"Only support transfer from pre-adaptivity to post-adaptivity right now"); 48179566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn,&plexIn)); 48189566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmOut,&plexOut)); 48190a96aa3bSJed Brown 48209566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree(plexIn,vecIn,plexOut,vecOut,inSF,outSF,inCids,outCids,useBCs,time)); 48219566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 48229566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 48239566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&inSF)); 48249566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&outSF)); 48259566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids)); 48269566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids)); 48270a96aa3bSJed Brown PetscFunctionReturn(0); 48280a96aa3bSJed Brown } 48290a96aa3bSJed Brown 48300a96aa3bSJed Brown #define DMCreateCoordinateDM_pforest _append_pforest(DMCreateCoordinateDM) 48310a96aa3bSJed Brown static PetscErrorCode DMCreateCoordinateDM_pforest(DM dm,DM *cdm) 48320a96aa3bSJed Brown { 48330a96aa3bSJed Brown DM plex; 48340a96aa3bSJed Brown 48350a96aa3bSJed Brown PetscFunctionBegin; 48360a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 48379566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 48389566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(plex,cdm)); 48399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*cdm)); 48400a96aa3bSJed Brown PetscFunctionReturn(0); 48410a96aa3bSJed Brown } 48420a96aa3bSJed Brown 48430a96aa3bSJed Brown #define VecViewLocal_pforest _append_pforest(VecViewLocal) 48440a96aa3bSJed Brown static PetscErrorCode VecViewLocal_pforest(Vec vec,PetscViewer viewer) 48450a96aa3bSJed Brown { 48460a96aa3bSJed Brown DM dm, plex; 48470a96aa3bSJed Brown 48480a96aa3bSJed Brown PetscFunctionBegin; 48499566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 48509566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 48519566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 48529566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(vec,viewer)); 48539566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 48540a96aa3bSJed Brown PetscFunctionReturn(0); 48550a96aa3bSJed Brown } 48560a96aa3bSJed Brown 48570a96aa3bSJed Brown #define VecView_pforest _append_pforest(VecView) 48580a96aa3bSJed Brown static PetscErrorCode VecView_pforest(Vec vec,PetscViewer viewer) 48590a96aa3bSJed Brown { 48600a96aa3bSJed Brown DM dm, plex; 48610a96aa3bSJed Brown 48620a96aa3bSJed Brown PetscFunctionBegin; 48639566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 48649566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 48659566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 48669566063dSJacob Faibussowitsch PetscCall(VecView_Plex(vec,viewer)); 48679566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 48680a96aa3bSJed Brown PetscFunctionReturn(0); 48690a96aa3bSJed Brown } 48700a96aa3bSJed Brown 48710a96aa3bSJed Brown #define VecView_pforest_Native _infix_pforest(VecView,_Native) 48720a96aa3bSJed Brown static PetscErrorCode VecView_pforest_Native(Vec vec,PetscViewer viewer) 48730a96aa3bSJed Brown { 48740a96aa3bSJed Brown DM dm, plex; 48750a96aa3bSJed Brown 48760a96aa3bSJed Brown PetscFunctionBegin; 48779566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 48789566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 48799566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 48809566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Native(vec,viewer)); 48819566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 48820a96aa3bSJed Brown PetscFunctionReturn(0); 48830a96aa3bSJed Brown } 48840a96aa3bSJed Brown 48850a96aa3bSJed Brown #define VecLoad_pforest _append_pforest(VecLoad) 48860a96aa3bSJed Brown static PetscErrorCode VecLoad_pforest(Vec vec,PetscViewer viewer) 48870a96aa3bSJed Brown { 48880a96aa3bSJed Brown DM dm, plex; 48890a96aa3bSJed Brown 48900a96aa3bSJed Brown PetscFunctionBegin; 48919566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 48929566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 48939566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 48949566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex(vec,viewer)); 48959566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 48960a96aa3bSJed Brown PetscFunctionReturn(0); 48970a96aa3bSJed Brown } 48980a96aa3bSJed Brown 48990a96aa3bSJed Brown #define VecLoad_pforest_Native _infix_pforest(VecLoad,_Native) 49000a96aa3bSJed Brown static PetscErrorCode VecLoad_pforest_Native(Vec vec,PetscViewer viewer) 49010a96aa3bSJed Brown { 49020a96aa3bSJed Brown DM dm, plex; 49030a96aa3bSJed Brown 49040a96aa3bSJed Brown PetscFunctionBegin; 49059566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec,&dm)); 49069566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49079566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,plex)); 49089566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_Native(vec,viewer)); 49099566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec,dm)); 49100a96aa3bSJed Brown PetscFunctionReturn(0); 49110a96aa3bSJed Brown } 49120a96aa3bSJed Brown 49130a96aa3bSJed Brown #define DMCreateGlobalVector_pforest _append_pforest(DMCreateGlobalVector) 49140a96aa3bSJed Brown static PetscErrorCode DMCreateGlobalVector_pforest(DM dm,Vec *vec) 49150a96aa3bSJed Brown { 49160a96aa3bSJed Brown PetscFunctionBegin; 49179566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm,vec)); 49189566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 49199566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_pforest)); 49209566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_pforest_Native)); 49219566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_pforest)); 49229566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_pforest_Native)); 49230a96aa3bSJed Brown PetscFunctionReturn(0); 49240a96aa3bSJed Brown } 49250a96aa3bSJed Brown 49260a96aa3bSJed Brown #define DMCreateLocalVector_pforest _append_pforest(DMCreateLocalVector) 49270a96aa3bSJed Brown static PetscErrorCode DMCreateLocalVector_pforest(DM dm,Vec *vec) 49280a96aa3bSJed Brown { 49290a96aa3bSJed Brown PetscFunctionBegin; 49309566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm,vec)); 49319566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecViewLocal_pforest)); 49320a96aa3bSJed Brown PetscFunctionReturn(0); 49330a96aa3bSJed Brown } 49340a96aa3bSJed Brown 49350a96aa3bSJed Brown #define DMCreateMatrix_pforest _append_pforest(DMCreateMatrix) 49360a96aa3bSJed Brown static PetscErrorCode DMCreateMatrix_pforest(DM dm,Mat *mat) 49370a96aa3bSJed Brown { 49380a96aa3bSJed Brown DM plex; 49390a96aa3bSJed Brown 49400a96aa3bSJed Brown PetscFunctionBegin; 49410a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49429566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49430a96aa3bSJed Brown if (plex->prealloc_only != dm->prealloc_only) plex->prealloc_only = dm->prealloc_only; /* maybe this should go into forest->plex */ 49449566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(plex,mat)); 49459566063dSJacob Faibussowitsch PetscCall(MatSetDM(*mat,dm)); 49460a96aa3bSJed Brown PetscFunctionReturn(0); 49470a96aa3bSJed Brown } 49480a96aa3bSJed Brown 49490a96aa3bSJed Brown #define DMProjectFunctionLocal_pforest _append_pforest(DMProjectFunctionLocal) 49500a96aa3bSJed Brown static PetscErrorCode DMProjectFunctionLocal_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs) (PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void*), void **ctxs, InsertMode mode, Vec localX) 49510a96aa3bSJed Brown { 49520a96aa3bSJed Brown DM plex; 49530a96aa3bSJed Brown 49540a96aa3bSJed Brown PetscFunctionBegin; 49550a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49569566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49579566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLocal(plex,time,funcs,ctxs,mode,localX)); 49580a96aa3bSJed Brown PetscFunctionReturn(0); 49590a96aa3bSJed Brown } 49600a96aa3bSJed Brown 49610a96aa3bSJed Brown #define DMProjectFunctionLabelLocal_pforest _append_pforest(DMProjectFunctionLabelLocal) 49620a96aa3bSJed 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) 49630a96aa3bSJed Brown { 49640a96aa3bSJed Brown DM plex; 49650a96aa3bSJed Brown 49660a96aa3bSJed Brown PetscFunctionBegin; 49670a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49689566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49699566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLabelLocal(plex,time,label,numIds,ids,Ncc,comps,funcs,ctxs,mode,localX)); 49700a96aa3bSJed Brown PetscFunctionReturn(0); 49710a96aa3bSJed Brown } 49720a96aa3bSJed Brown 49730a96aa3bSJed Brown #define DMProjectFieldLocal_pforest _append_pforest(DMProjectFieldLocal) 49740a96aa3bSJed Brown PetscErrorCode DMProjectFieldLocal_pforest(DM dm, PetscReal time, Vec localU,void (**funcs) (PetscInt, PetscInt, PetscInt, 49750a96aa3bSJed Brown const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 49760a96aa3bSJed Brown const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 49770a96aa3bSJed Brown PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),InsertMode mode, Vec localX) 49780a96aa3bSJed Brown { 49790a96aa3bSJed Brown DM plex; 49800a96aa3bSJed Brown 49810a96aa3bSJed Brown PetscFunctionBegin; 49820a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49839566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49849566063dSJacob Faibussowitsch PetscCall(DMProjectFieldLocal(plex,time,localU,funcs,mode,localX)); 49850a96aa3bSJed Brown PetscFunctionReturn(0); 49860a96aa3bSJed Brown } 49870a96aa3bSJed Brown 49880a96aa3bSJed Brown #define DMComputeL2Diff_pforest _append_pforest(DMComputeL2Diff) 49890a96aa3bSJed Brown PetscErrorCode DMComputeL2Diff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs) (PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void*), void **ctxs, Vec X, PetscReal *diff) 49900a96aa3bSJed Brown { 49910a96aa3bSJed Brown DM plex; 49920a96aa3bSJed Brown 49930a96aa3bSJed Brown PetscFunctionBegin; 49940a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49959566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 49969566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(plex,time,funcs,ctxs,X,diff)); 49970a96aa3bSJed Brown PetscFunctionReturn(0); 49980a96aa3bSJed Brown } 49990a96aa3bSJed Brown 50000a96aa3bSJed Brown #define DMComputeL2FieldDiff_pforest _append_pforest(DMComputeL2FieldDiff) 50010a96aa3bSJed Brown PetscErrorCode DMComputeL2FieldDiff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs) (PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void*), void **ctxs, Vec X, PetscReal diff[]) 50020a96aa3bSJed Brown { 50030a96aa3bSJed Brown DM plex; 50040a96aa3bSJed Brown 50050a96aa3bSJed Brown PetscFunctionBegin; 50060a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 50079566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 50089566063dSJacob Faibussowitsch PetscCall(DMComputeL2FieldDiff(plex,time,funcs,ctxs,X,diff)); 50090a96aa3bSJed Brown PetscFunctionReturn(0); 50100a96aa3bSJed Brown } 50110a96aa3bSJed Brown 50120a96aa3bSJed Brown #define DMCreatelocalsection_pforest _append_pforest(DMCreatelocalsection) 50130a96aa3bSJed Brown static PetscErrorCode DMCreatelocalsection_pforest(DM dm) 50140a96aa3bSJed Brown { 50150a96aa3bSJed Brown DM plex; 50160a96aa3bSJed Brown PetscSection section; 50170a96aa3bSJed Brown 50180a96aa3bSJed Brown PetscFunctionBegin; 50190a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 50209566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 50219566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(plex,§ion)); 50229566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(dm,section)); 50230a96aa3bSJed Brown PetscFunctionReturn(0); 50240a96aa3bSJed Brown } 50250a96aa3bSJed Brown 50260a96aa3bSJed Brown #define DMCreateDefaultConstraints_pforest _append_pforest(DMCreateDefaultConstraints) 50270a96aa3bSJed Brown static PetscErrorCode DMCreateDefaultConstraints_pforest(DM dm) 50280a96aa3bSJed Brown { 50290a96aa3bSJed Brown DM plex; 50300a96aa3bSJed Brown Mat mat; 503179769bd5SJed Brown Vec bias; 50320a96aa3bSJed Brown PetscSection section; 50330a96aa3bSJed Brown 50340a96aa3bSJed Brown PetscFunctionBegin; 50350a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 50369566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 50379566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(plex,§ion,&mat,&bias)); 50389566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm,section,mat,bias)); 50390a96aa3bSJed Brown PetscFunctionReturn(0); 50400a96aa3bSJed Brown } 50410a96aa3bSJed Brown 50420a96aa3bSJed Brown #define DMGetDimPoints_pforest _append_pforest(DMGetDimPoints) 50430a96aa3bSJed Brown static PetscErrorCode DMGetDimPoints_pforest(DM dm, PetscInt dim, PetscInt *cStart, PetscInt *cEnd) 50440a96aa3bSJed Brown { 50450a96aa3bSJed Brown DM plex; 50460a96aa3bSJed Brown 50470a96aa3bSJed Brown PetscFunctionBegin; 50480a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 50499566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 50509566063dSJacob Faibussowitsch PetscCall(DMGetDimPoints(plex,dim,cStart,cEnd)); 50510a96aa3bSJed Brown PetscFunctionReturn(0); 50520a96aa3bSJed Brown } 50530a96aa3bSJed Brown 50540a96aa3bSJed Brown /* Need to forward declare */ 50550a96aa3bSJed Brown #define DMInitialize_pforest _append_pforest(DMInitialize) 50560a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm); 50570a96aa3bSJed Brown 50580a96aa3bSJed Brown #define DMClone_pforest _append_pforest(DMClone) 50590a96aa3bSJed Brown static PetscErrorCode DMClone_pforest(DM dm, DM *newdm) 50600a96aa3bSJed Brown { 50610a96aa3bSJed Brown PetscFunctionBegin; 50629566063dSJacob Faibussowitsch PetscCall(DMClone_Forest(dm,newdm)); 50639566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(*newdm)); 50640a96aa3bSJed Brown PetscFunctionReturn(0); 50650a96aa3bSJed Brown } 50660a96aa3bSJed Brown 50670a96aa3bSJed Brown #define DMForestCreateCellChart_pforest _append_pforest(DMForestCreateCellChart) 50680a96aa3bSJed Brown static PetscErrorCode DMForestCreateCellChart_pforest(DM dm, PetscInt *cStart, PetscInt *cEnd) 50690a96aa3bSJed Brown { 50700a96aa3bSJed Brown DM_Forest *forest; 50710a96aa3bSJed Brown DM_Forest_pforest *pforest; 50720a96aa3bSJed Brown PetscInt overlap; 50730a96aa3bSJed Brown 50740a96aa3bSJed Brown PetscFunctionBegin; 50759566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 50760a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 50770a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 50780a96aa3bSJed Brown *cStart = 0; 50799566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm,&overlap)); 50800a96aa3bSJed Brown if (overlap && pforest->ghost) { 50810a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[pforest->forest->mpisize]; 50820a96aa3bSJed Brown } else { 50830a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants; 50840a96aa3bSJed Brown } 50850a96aa3bSJed Brown PetscFunctionReturn(0); 50860a96aa3bSJed Brown } 50870a96aa3bSJed Brown 50880a96aa3bSJed Brown #define DMForestCreateCellSF_pforest _append_pforest(DMForestCreateCellSF) 50890a96aa3bSJed Brown static PetscErrorCode DMForestCreateCellSF_pforest(DM dm, PetscSF *cellSF) 50900a96aa3bSJed Brown { 50910a96aa3bSJed Brown DM_Forest *forest; 50920a96aa3bSJed Brown DM_Forest_pforest *pforest; 50930a96aa3bSJed Brown PetscMPIInt rank; 50940a96aa3bSJed Brown PetscInt overlap; 50950a96aa3bSJed Brown PetscInt cStart, cEnd, cLocalStart, cLocalEnd; 50960a96aa3bSJed Brown PetscInt nRoots, nLeaves, *mine = NULL; 50970a96aa3bSJed Brown PetscSFNode *remote = NULL; 50980a96aa3bSJed Brown PetscSF sf; 50990a96aa3bSJed Brown 51000a96aa3bSJed Brown PetscFunctionBegin; 51019566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(dm,&cStart,&cEnd)); 51020a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 51030a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 51040a96aa3bSJed Brown nRoots = cEnd - cStart; 51050a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 51060a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 51070a96aa3bSJed Brown nLeaves = 0; 51089566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm,&overlap)); 51099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank)); 51100a96aa3bSJed Brown if (overlap && pforest->ghost) { 51110a96aa3bSJed Brown PetscSFNode *mirror; 51120a96aa3bSJed Brown p4est_quadrant_t *mirror_array; 51130a96aa3bSJed Brown PetscInt nMirror, nGhostPre, nSelf, q; 51140a96aa3bSJed Brown void **mirrorPtrs; 51150a96aa3bSJed Brown 51160a96aa3bSJed Brown nMirror = (PetscInt) pforest->ghost->mirrors.elem_count; 51170a96aa3bSJed Brown nSelf = cLocalEnd - cLocalStart; 51180a96aa3bSJed Brown nLeaves = nRoots - nSelf; 51190a96aa3bSJed Brown nGhostPre = (PetscInt) pforest->ghost->proc_offsets[rank]; 51209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves,&mine)); 51219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves,&remote)); 51229566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nMirror,&mirror,nMirror,&mirrorPtrs)); 51230a96aa3bSJed Brown mirror_array = (p4est_quadrant_t*) pforest->ghost->mirrors.array; 51240a96aa3bSJed Brown for (q = 0; q < nMirror; q++) { 51250a96aa3bSJed Brown p4est_quadrant_t *mir = &(mirror_array[q]); 51260a96aa3bSJed Brown 51270a96aa3bSJed Brown mirror[q].rank = rank; 51280a96aa3bSJed Brown mirror[q].index = (PetscInt) mir->p.piggy3.local_num + cLocalStart; 51290a96aa3bSJed Brown mirrorPtrs[q] = (void*) &(mirror[q]); 51300a96aa3bSJed Brown } 51310a96aa3bSJed Brown PetscStackCallP4est(p4est_ghost_exchange_custom,(pforest->forest,pforest->ghost,sizeof(PetscSFNode),mirrorPtrs,remote)); 51329566063dSJacob Faibussowitsch PetscCall(PetscFree2(mirror,mirrorPtrs)); 51330a96aa3bSJed Brown for (q = 0; q < nGhostPre; q++) mine[q] = q; 51340a96aa3bSJed Brown for (; q < nLeaves; q++) mine[q] = (q - nGhostPre) + cLocalEnd; 51350a96aa3bSJed Brown } 51369566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&sf)); 51379566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf,nRoots,nLeaves,mine,PETSC_OWN_POINTER,remote,PETSC_OWN_POINTER)); 51380a96aa3bSJed Brown *cellSF = sf; 51390a96aa3bSJed Brown PetscFunctionReturn(0); 51400a96aa3bSJed Brown } 51410a96aa3bSJed Brown 51420a96aa3bSJed Brown static PetscErrorCode DMCreateNeumannOverlap_pforest(DM dm, IS* ovl, Mat *J, PetscErrorCode (**setup)(Mat, PetscReal, Vec, Vec, PetscReal, IS, void*), void **setup_ctx) 51430a96aa3bSJed Brown { 51440a96aa3bSJed Brown DM plex; 51450a96aa3bSJed Brown 51460a96aa3bSJed Brown PetscFunctionBegin; 51479566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm,&plex)); 51489566063dSJacob Faibussowitsch PetscCall(DMCreateNeumannOverlap_Plex(plex,ovl,J,setup,setup_ctx)); 51490a96aa3bSJed Brown if (!*setup) { 51509566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", setup)); 51510a96aa3bSJed Brown if (*setup) { 51529566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*ovl, "_DM_Original_HPDDM", (PetscObject)dm)); 51530a96aa3bSJed Brown } 51540a96aa3bSJed Brown } 51550a96aa3bSJed Brown PetscFunctionReturn(0); 51560a96aa3bSJed Brown } 51570a96aa3bSJed Brown 51580a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm) 51590a96aa3bSJed Brown { 51600a96aa3bSJed Brown PetscFunctionBegin; 51610a96aa3bSJed Brown dm->ops->setup = DMSetUp_pforest; 51620a96aa3bSJed Brown dm->ops->view = DMView_pforest; 51630a96aa3bSJed Brown dm->ops->clone = DMClone_pforest; 51640a96aa3bSJed Brown dm->ops->createinterpolation = DMCreateInterpolation_pforest; 51650a96aa3bSJed Brown dm->ops->createinjection = DMCreateInjection_pforest; 51660a96aa3bSJed Brown dm->ops->setfromoptions = DMSetFromOptions_pforest; 51670a96aa3bSJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_pforest; 51680a96aa3bSJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_pforest; 51690a96aa3bSJed Brown dm->ops->createlocalvector = DMCreateLocalVector_pforest; 51700a96aa3bSJed Brown dm->ops->creatematrix = DMCreateMatrix_pforest; 51710a96aa3bSJed Brown dm->ops->projectfunctionlocal = DMProjectFunctionLocal_pforest; 51720a96aa3bSJed Brown dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_pforest; 51730a96aa3bSJed Brown dm->ops->projectfieldlocal = DMProjectFieldLocal_pforest; 51740a96aa3bSJed Brown dm->ops->createlocalsection = DMCreatelocalsection_pforest; 51750a96aa3bSJed Brown dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_pforest; 51760a96aa3bSJed Brown dm->ops->computel2diff = DMComputeL2Diff_pforest; 51770a96aa3bSJed Brown dm->ops->computel2fielddiff = DMComputeL2FieldDiff_pforest; 51780a96aa3bSJed Brown dm->ops->getdimpoints = DMGetDimPoints_pforest; 51790a96aa3bSJed Brown 51809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_plex_pforest) "_C",DMConvert_plex_pforest)); 51819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_pforest_plex) "_C",DMConvert_pforest_plex)); 51829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",DMCreateNeumannOverlap_pforest)); 51839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",DMForestGetPartitionOverlap)); 51840a96aa3bSJed Brown PetscFunctionReturn(0); 51850a96aa3bSJed Brown } 51860a96aa3bSJed Brown 51870a96aa3bSJed Brown #define DMCreate_pforest _append_pforest(DMCreate) 51880a96aa3bSJed Brown PETSC_EXTERN PetscErrorCode DMCreate_pforest(DM dm) 51890a96aa3bSJed Brown { 51900a96aa3bSJed Brown DM_Forest *forest; 51910a96aa3bSJed Brown DM_Forest_pforest *pforest; 51920a96aa3bSJed Brown 51930a96aa3bSJed Brown PetscFunctionBegin; 51949566063dSJacob Faibussowitsch PetscCall(PetscP4estInitialize()); 51959566063dSJacob Faibussowitsch PetscCall(DMCreate_Forest(dm)); 51969566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(dm)); 51979566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm,P4EST_DIM)); 51980a96aa3bSJed Brown 51990a96aa3bSJed Brown /* set forest defaults */ 52009566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm,"unit")); 52019566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(dm,0)); 52029566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(dm,0)); 52039566063dSJacob Faibussowitsch PetscCall(DMForestSetMaximumRefinement(dm,P4EST_QMAXLEVEL)); 52049566063dSJacob Faibussowitsch PetscCall(DMForestSetGradeFactor(dm,2)); 52059566063dSJacob Faibussowitsch PetscCall(DMForestSetAdjacencyDimension(dm,0)); 52069566063dSJacob Faibussowitsch PetscCall(DMForestSetPartitionOverlap(dm,0)); 52070a96aa3bSJed Brown 52080a96aa3bSJed Brown /* create p4est data */ 52099566063dSJacob Faibussowitsch PetscCall(PetscNewLog(dm,&pforest)); 52100a96aa3bSJed Brown 52110a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 52120a96aa3bSJed Brown forest->data = pforest; 52130a96aa3bSJed Brown forest->destroy = DMForestDestroy_pforest; 52140a96aa3bSJed Brown forest->ftemplate = DMForestTemplate_pforest; 52150a96aa3bSJed Brown forest->transfervec = DMForestTransferVec_pforest; 52160a96aa3bSJed Brown forest->transfervecfrombase = DMForestTransferVecFromBase_pforest; 52170a96aa3bSJed Brown forest->createcellchart = DMForestCreateCellChart_pforest; 52180a96aa3bSJed Brown forest->createcellsf = DMForestCreateCellSF_pforest; 52190a96aa3bSJed Brown forest->clearadaptivityforest = DMForestClearAdaptivityForest_pforest; 52200a96aa3bSJed Brown forest->getadaptivitysuccess = DMForestGetAdaptivitySuccess_pforest; 52210a96aa3bSJed Brown pforest->topo = NULL; 52220a96aa3bSJed Brown pforest->forest = NULL; 52230a96aa3bSJed Brown pforest->ghost = NULL; 52240a96aa3bSJed Brown pforest->lnodes = NULL; 52250a96aa3bSJed Brown pforest->partition_for_coarsening = PETSC_TRUE; 52260a96aa3bSJed Brown pforest->coarsen_hierarchy = PETSC_FALSE; 52270a96aa3bSJed Brown pforest->cLocalStart = -1; 52280a96aa3bSJed Brown pforest->cLocalEnd = -1; 52290a96aa3bSJed Brown pforest->labelsFinalized = PETSC_FALSE; 52300a96aa3bSJed Brown pforest->ghostName = NULL; 52310a96aa3bSJed Brown PetscFunctionReturn(0); 52320a96aa3bSJed Brown } 52330a96aa3bSJed Brown 52340a96aa3bSJed Brown #endif /* defined(PETSC_HAVE_P4EST) */ 5235