1*0a96aa3bSJed Brown #include <petscds.h> 2*0a96aa3bSJed Brown #include <petsc/private/dmimpl.h> 3*0a96aa3bSJed Brown #include <petsc/private/dmforestimpl.h> 4*0a96aa3bSJed Brown #include <petsc/private/dmpleximpl.h> 5*0a96aa3bSJed Brown #include <petsc/private/dmlabelimpl.h> 6*0a96aa3bSJed Brown #include <petsc/private/viewerimpl.h> 7*0a96aa3bSJed Brown #include <../src/sys/classes/viewer/impls/vtk/vtkvimpl.h> 8*0a96aa3bSJed Brown #include "petsc_p4est_package.h" 9*0a96aa3bSJed Brown 10*0a96aa3bSJed Brown #if defined(PETSC_HAVE_P4EST) 11*0a96aa3bSJed Brown 12*0a96aa3bSJed Brown #if !defined(P4_TO_P8) 13*0a96aa3bSJed Brown #include <p4est.h> 14*0a96aa3bSJed Brown #include <p4est_extended.h> 15*0a96aa3bSJed Brown #include <p4est_geometry.h> 16*0a96aa3bSJed Brown #include <p4est_ghost.h> 17*0a96aa3bSJed Brown #include <p4est_lnodes.h> 18*0a96aa3bSJed Brown #include <p4est_vtk.h> 19*0a96aa3bSJed Brown #include <p4est_plex.h> 20*0a96aa3bSJed Brown #include <p4est_bits.h> 21*0a96aa3bSJed Brown #include <p4est_algorithms.h> 22*0a96aa3bSJed Brown #else 23*0a96aa3bSJed Brown #include <p8est.h> 24*0a96aa3bSJed Brown #include <p8est_extended.h> 25*0a96aa3bSJed Brown #include <p8est_geometry.h> 26*0a96aa3bSJed Brown #include <p8est_ghost.h> 27*0a96aa3bSJed Brown #include <p8est_lnodes.h> 28*0a96aa3bSJed Brown #include <p8est_vtk.h> 29*0a96aa3bSJed Brown #include <p8est_plex.h> 30*0a96aa3bSJed Brown #include <p8est_bits.h> 31*0a96aa3bSJed Brown #include <p8est_algorithms.h> 32*0a96aa3bSJed Brown #endif 33*0a96aa3bSJed Brown 34*0a96aa3bSJed Brown typedef enum {PATTERN_HASH,PATTERN_FRACTAL,PATTERN_CORNER,PATTERN_CENTER,PATTERN_COUNT} DMRefinePattern; 35*0a96aa3bSJed Brown static const char *DMRefinePatternName[PATTERN_COUNT] = {"hash","fractal","corner","center"}; 36*0a96aa3bSJed Brown 37*0a96aa3bSJed Brown typedef struct _DMRefinePatternCtx 38*0a96aa3bSJed Brown { 39*0a96aa3bSJed Brown PetscInt corner; 40*0a96aa3bSJed Brown PetscBool fractal[P4EST_CHILDREN]; 41*0a96aa3bSJed Brown PetscReal hashLikelihood; 42*0a96aa3bSJed Brown PetscInt maxLevel; 43*0a96aa3bSJed Brown p4est_refine_t refine_fn; 44*0a96aa3bSJed Brown } 45*0a96aa3bSJed Brown DMRefinePatternCtx; 46*0a96aa3bSJed Brown 47*0a96aa3bSJed Brown static int DMRefinePattern_Corner(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 48*0a96aa3bSJed Brown { 49*0a96aa3bSJed Brown p4est_quadrant_t root, rootcorner; 50*0a96aa3bSJed Brown DMRefinePatternCtx *ctx; 51*0a96aa3bSJed Brown 52*0a96aa3bSJed Brown ctx = (DMRefinePatternCtx*) p4est->user_pointer; 53*0a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 54*0a96aa3bSJed Brown 55*0a96aa3bSJed Brown root.x = root.y = 0; 56*0a96aa3bSJed Brown #if defined(P4_TO_P8) 57*0a96aa3bSJed Brown root.z = 0; 58*0a96aa3bSJed Brown #endif 59*0a96aa3bSJed Brown root.level = 0; 60*0a96aa3bSJed Brown p4est_quadrant_corner_descendant(&root,&rootcorner,ctx->corner,quadrant->level); 61*0a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant,&rootcorner)) return 1; 62*0a96aa3bSJed Brown return 0; 63*0a96aa3bSJed Brown } 64*0a96aa3bSJed Brown 65*0a96aa3bSJed Brown static int DMRefinePattern_Center(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 66*0a96aa3bSJed Brown { 67*0a96aa3bSJed Brown int cid; 68*0a96aa3bSJed Brown p4est_quadrant_t ancestor, ancestorcorner; 69*0a96aa3bSJed Brown DMRefinePatternCtx *ctx; 70*0a96aa3bSJed Brown 71*0a96aa3bSJed Brown ctx = (DMRefinePatternCtx*) p4est->user_pointer; 72*0a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 73*0a96aa3bSJed Brown if (quadrant->level <= 1) return 1; 74*0a96aa3bSJed Brown 75*0a96aa3bSJed Brown p4est_quadrant_ancestor(quadrant,1,&ancestor); 76*0a96aa3bSJed Brown cid = p4est_quadrant_child_id(&ancestor); 77*0a96aa3bSJed Brown p4est_quadrant_corner_descendant(&ancestor,&ancestorcorner,P4EST_CHILDREN - 1 - cid,quadrant->level); 78*0a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant,&ancestorcorner)) return 1; 79*0a96aa3bSJed Brown return 0; 80*0a96aa3bSJed Brown } 81*0a96aa3bSJed Brown 82*0a96aa3bSJed Brown static int DMRefinePattern_Fractal(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 83*0a96aa3bSJed Brown { 84*0a96aa3bSJed Brown int cid; 85*0a96aa3bSJed Brown DMRefinePatternCtx *ctx; 86*0a96aa3bSJed Brown 87*0a96aa3bSJed Brown ctx = (DMRefinePatternCtx*) p4est->user_pointer; 88*0a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 89*0a96aa3bSJed Brown if (!quadrant->level) return 1; 90*0a96aa3bSJed Brown cid = p4est_quadrant_child_id(quadrant); 91*0a96aa3bSJed Brown if (ctx->fractal[cid ^ ((int) (quadrant->level % P4EST_CHILDREN))]) return 1; 92*0a96aa3bSJed Brown return 0; 93*0a96aa3bSJed Brown } 94*0a96aa3bSJed Brown 95*0a96aa3bSJed Brown /* simplified from MurmurHash3 by Austin Appleby */ 96*0a96aa3bSJed Brown #define DMPROT32(x, y) ((x << y) | (x >> (32 - y))) 97*0a96aa3bSJed Brown static uint32_t DMPforestHash(const uint32_t *blocks, uint32_t nblocks) 98*0a96aa3bSJed Brown { 99*0a96aa3bSJed Brown uint32_t c1 = 0xcc9e2d51; 100*0a96aa3bSJed Brown uint32_t c2 = 0x1b873593; 101*0a96aa3bSJed Brown uint32_t r1 = 15; 102*0a96aa3bSJed Brown uint32_t r2 = 13; 103*0a96aa3bSJed Brown uint32_t m = 5; 104*0a96aa3bSJed Brown uint32_t n = 0xe6546b64; 105*0a96aa3bSJed Brown uint32_t hash = 0; 106*0a96aa3bSJed Brown int len = nblocks * 4; 107*0a96aa3bSJed Brown uint32_t i; 108*0a96aa3bSJed Brown 109*0a96aa3bSJed Brown for (i = 0; i < nblocks; i++) { 110*0a96aa3bSJed Brown uint32_t k; 111*0a96aa3bSJed Brown 112*0a96aa3bSJed Brown k = blocks[i]; 113*0a96aa3bSJed Brown k *= c1; 114*0a96aa3bSJed Brown k = DMPROT32(k, r1); 115*0a96aa3bSJed Brown k *= c2; 116*0a96aa3bSJed Brown 117*0a96aa3bSJed Brown hash ^= k; 118*0a96aa3bSJed Brown hash = DMPROT32(hash, r2) * m + n; 119*0a96aa3bSJed Brown } 120*0a96aa3bSJed Brown 121*0a96aa3bSJed Brown hash ^= len; 122*0a96aa3bSJed Brown hash ^= (hash >> 16); 123*0a96aa3bSJed Brown hash *= 0x85ebca6b; 124*0a96aa3bSJed Brown hash ^= (hash >> 13); 125*0a96aa3bSJed Brown hash *= 0xc2b2ae35; 126*0a96aa3bSJed Brown hash ^= (hash >> 16); 127*0a96aa3bSJed Brown 128*0a96aa3bSJed Brown return hash; 129*0a96aa3bSJed Brown } 130*0a96aa3bSJed Brown 131*0a96aa3bSJed Brown #if defined(UINT32_MAX) 132*0a96aa3bSJed Brown #define DMP4EST_HASH_MAX UINT32_MAX 133*0a96aa3bSJed Brown #else 134*0a96aa3bSJed Brown #define DMP4EST_HASH_MAX ((uint32_t) 0xffffffff) 135*0a96aa3bSJed Brown #endif 136*0a96aa3bSJed Brown 137*0a96aa3bSJed Brown static int DMRefinePattern_Hash(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 138*0a96aa3bSJed Brown { 139*0a96aa3bSJed Brown uint32_t data[5]; 140*0a96aa3bSJed Brown uint32_t result; 141*0a96aa3bSJed Brown DMRefinePatternCtx *ctx; 142*0a96aa3bSJed Brown 143*0a96aa3bSJed Brown ctx = (DMRefinePatternCtx*) p4est->user_pointer; 144*0a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0; 145*0a96aa3bSJed Brown data[0] = ((uint32_t) quadrant->level) << 24; 146*0a96aa3bSJed Brown data[1] = (uint32_t) which_tree; 147*0a96aa3bSJed Brown data[2] = (uint32_t) quadrant->x; 148*0a96aa3bSJed Brown data[3] = (uint32_t) quadrant->y; 149*0a96aa3bSJed Brown #if defined(P4_TO_P8) 150*0a96aa3bSJed Brown data[4] = (uint32_t) quadrant->z; 151*0a96aa3bSJed Brown #endif 152*0a96aa3bSJed Brown 153*0a96aa3bSJed Brown result = DMPforestHash(data,2+P4EST_DIM); 154*0a96aa3bSJed Brown if (((double) result / (double) DMP4EST_HASH_MAX) < ctx->hashLikelihood) return 1; 155*0a96aa3bSJed Brown return 0; 156*0a96aa3bSJed Brown } 157*0a96aa3bSJed Brown 158*0a96aa3bSJed Brown #define DMConvert_pforest_plex _infix_pforest(DMConvert,_plex) 159*0a96aa3bSJed Brown static PetscErrorCode DMConvert_pforest_plex(DM,DMType,DM*); 160*0a96aa3bSJed Brown 161*0a96aa3bSJed Brown #define DMFTopology_pforest _append_pforest(DMFTopology) 162*0a96aa3bSJed Brown typedef struct { 163*0a96aa3bSJed Brown PetscInt refct; 164*0a96aa3bSJed Brown p4est_connectivity_t *conn; 165*0a96aa3bSJed Brown p4est_geometry_t *geom; 166*0a96aa3bSJed Brown PetscInt *tree_face_to_uniq; /* p4est does not explicitly enumerate facets, but we must to keep track of labels */ 167*0a96aa3bSJed Brown } DMFTopology_pforest; 168*0a96aa3bSJed Brown 169*0a96aa3bSJed Brown #define DM_Forest_pforest _append_pforest(DM_Forest) 170*0a96aa3bSJed Brown typedef struct { 171*0a96aa3bSJed Brown DMFTopology_pforest *topo; 172*0a96aa3bSJed Brown p4est_t *forest; 173*0a96aa3bSJed Brown p4est_ghost_t *ghost; 174*0a96aa3bSJed Brown p4est_lnodes_t *lnodes; 175*0a96aa3bSJed Brown PetscBool partition_for_coarsening; 176*0a96aa3bSJed Brown PetscBool coarsen_hierarchy; 177*0a96aa3bSJed Brown PetscBool labelsFinalized; 178*0a96aa3bSJed Brown PetscBool adaptivitySuccess; 179*0a96aa3bSJed Brown PetscInt cLocalStart; 180*0a96aa3bSJed Brown PetscInt cLocalEnd; 181*0a96aa3bSJed Brown DM plex; 182*0a96aa3bSJed Brown char *ghostName; 183*0a96aa3bSJed Brown PetscSF pointAdaptToSelfSF; 184*0a96aa3bSJed Brown PetscSF pointSelfToAdaptSF; 185*0a96aa3bSJed Brown PetscInt *pointAdaptToSelfCids; 186*0a96aa3bSJed Brown PetscInt *pointSelfToAdaptCids; 187*0a96aa3bSJed Brown } DM_Forest_pforest; 188*0a96aa3bSJed Brown 189*0a96aa3bSJed Brown #define DM_Forest_geometry_pforest _append_pforest(DM_Forest_geometry) 190*0a96aa3bSJed Brown typedef struct { 191*0a96aa3bSJed Brown DM base; 192*0a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void*); 193*0a96aa3bSJed Brown void *mapCtx; 194*0a96aa3bSJed Brown PetscInt coordDim; 195*0a96aa3bSJed Brown p4est_geometry_t *inner; 196*0a96aa3bSJed Brown } 197*0a96aa3bSJed Brown DM_Forest_geometry_pforest; 198*0a96aa3bSJed Brown 199*0a96aa3bSJed Brown #define GeometryMapping_pforest _append_pforest(GeometryMapping) 200*0a96aa3bSJed Brown static void GeometryMapping_pforest(p4est_geometry_t *geom, p4est_topidx_t which_tree, const double abc[3], double xyz[3]) 201*0a96aa3bSJed Brown { 202*0a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest*)geom->user; 203*0a96aa3bSJed Brown PetscReal PetscABC[3] = {0.}; 204*0a96aa3bSJed Brown PetscReal PetscXYZ[3] = {0.}; 205*0a96aa3bSJed Brown PetscInt i, d = PetscMin(3,geom_pforest->coordDim); 206*0a96aa3bSJed Brown double ABC[3]; 207*0a96aa3bSJed Brown PetscErrorCode ierr; 208*0a96aa3bSJed Brown 209*0a96aa3bSJed Brown (geom_pforest->inner->X)(geom_pforest->inner,which_tree,abc,ABC); 210*0a96aa3bSJed Brown 211*0a96aa3bSJed Brown for (i = 0; i < d; i++) PetscABC[i] = ABC[i]; 212*0a96aa3bSJed Brown ierr = (geom_pforest->map)(geom_pforest->base,(PetscInt) which_tree,geom_pforest->coordDim,PetscABC,PetscXYZ,geom_pforest->mapCtx);PETSC_P4EST_ASSERT(!ierr); 213*0a96aa3bSJed Brown for (i = 0; i < d; i++) xyz[i] = PetscXYZ[i]; 214*0a96aa3bSJed Brown } 215*0a96aa3bSJed Brown 216*0a96aa3bSJed Brown #define GeometryDestroy_pforest _append_pforest(GeometryDestroy) 217*0a96aa3bSJed Brown static void GeometryDestroy_pforest(p4est_geometry_t *geom) 218*0a96aa3bSJed Brown { 219*0a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest*)geom->user; 220*0a96aa3bSJed Brown PetscErrorCode ierr; 221*0a96aa3bSJed Brown 222*0a96aa3bSJed Brown p4est_geometry_destroy(geom_pforest->inner); 223*0a96aa3bSJed Brown ierr = PetscFree(geom->user);PETSC_P4EST_ASSERT(!ierr); 224*0a96aa3bSJed Brown ierr = PetscFree(geom);PETSC_P4EST_ASSERT(!ierr); 225*0a96aa3bSJed Brown } 226*0a96aa3bSJed Brown 227*0a96aa3bSJed Brown #define DMFTopologyDestroy_pforest _append_pforest(DMFTopologyDestroy) 228*0a96aa3bSJed Brown static PetscErrorCode DMFTopologyDestroy_pforest(DMFTopology_pforest **topo) 229*0a96aa3bSJed Brown { 230*0a96aa3bSJed Brown PetscErrorCode ierr; 231*0a96aa3bSJed Brown 232*0a96aa3bSJed Brown PetscFunctionBegin; 233*0a96aa3bSJed Brown if (!(*topo)) PetscFunctionReturn(0); 234*0a96aa3bSJed Brown if (--((*topo)->refct) > 0) { 235*0a96aa3bSJed Brown *topo = NULL; 236*0a96aa3bSJed Brown PetscFunctionReturn(0); 237*0a96aa3bSJed Brown } 238*0a96aa3bSJed Brown if ((*topo)->geom) PetscStackCallP4est(p4est_geometry_destroy,((*topo)->geom)); 239*0a96aa3bSJed Brown PetscStackCallP4est(p4est_connectivity_destroy,((*topo)->conn)); 240*0a96aa3bSJed Brown ierr = PetscFree((*topo)->tree_face_to_uniq);CHKERRQ(ierr); 241*0a96aa3bSJed Brown ierr = PetscFree(*topo);CHKERRQ(ierr); 242*0a96aa3bSJed Brown *topo = NULL; 243*0a96aa3bSJed Brown PetscFunctionReturn(0); 244*0a96aa3bSJed Brown } 245*0a96aa3bSJed Brown 246*0a96aa3bSJed Brown static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t*,PetscInt**); 247*0a96aa3bSJed Brown 248*0a96aa3bSJed Brown #define DMFTopologyCreateBrick_pforest _append_pforest(DMFTopologyCreateBrick) 249*0a96aa3bSJed Brown static PetscErrorCode DMFTopologyCreateBrick_pforest(DM dm,PetscInt N[], PetscInt P[], PetscReal B[],DMFTopology_pforest **topo, PetscBool useMorton) 250*0a96aa3bSJed Brown { 251*0a96aa3bSJed Brown double *vertices; 252*0a96aa3bSJed Brown PetscInt i, numVerts; 253*0a96aa3bSJed Brown PetscErrorCode ierr; 254*0a96aa3bSJed Brown 255*0a96aa3bSJed Brown PetscFunctionBegin; 256*0a96aa3bSJed Brown if (!useMorton) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Lexicographic ordering not implemented yet"); 257*0a96aa3bSJed Brown ierr = PetscNewLog(dm,topo);CHKERRQ(ierr); 258*0a96aa3bSJed Brown 259*0a96aa3bSJed Brown (*topo)->refct = 1; 260*0a96aa3bSJed Brown #if !defined(P4_TO_P8) 261*0a96aa3bSJed 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)); 262*0a96aa3bSJed Brown #else 263*0a96aa3bSJed 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)); 264*0a96aa3bSJed Brown #endif 265*0a96aa3bSJed Brown numVerts = (*topo)->conn->num_vertices; 266*0a96aa3bSJed Brown vertices = (*topo)->conn->vertices; 267*0a96aa3bSJed Brown for (i = 0; i < 3 * numVerts; i++) { 268*0a96aa3bSJed Brown PetscInt j = i % 3; 269*0a96aa3bSJed Brown 270*0a96aa3bSJed Brown vertices[i] = B[2 * j] + (vertices[i]/N[j]) * (B[2 * j + 1] - B[2 * j]); 271*0a96aa3bSJed Brown } 272*0a96aa3bSJed Brown (*topo)->geom = NULL; 273*0a96aa3bSJed Brown ierr = PforestConnectivityEnumerateFacets((*topo)->conn,&(*topo)->tree_face_to_uniq);CHKERRQ(ierr); 274*0a96aa3bSJed Brown PetscFunctionReturn(0); 275*0a96aa3bSJed Brown } 276*0a96aa3bSJed Brown 277*0a96aa3bSJed Brown #define DMFTopologyCreate_pforest _append_pforest(DMFTopologyCreate) 278*0a96aa3bSJed Brown static PetscErrorCode DMFTopologyCreate_pforest(DM dm, DMForestTopology topologyName, DMFTopology_pforest **topo) 279*0a96aa3bSJed Brown { 280*0a96aa3bSJed Brown const char *name = (const char*) topologyName; 281*0a96aa3bSJed Brown const char *prefix; 282*0a96aa3bSJed Brown PetscBool isBrick, isShell, isSphere, isMoebius; 283*0a96aa3bSJed Brown PetscErrorCode ierr; 284*0a96aa3bSJed Brown 285*0a96aa3bSJed Brown PetscFunctionBegin; 286*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 287*0a96aa3bSJed Brown PetscValidCharPointer(name,2); 288*0a96aa3bSJed Brown PetscValidPointer(topo,3); 289*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"brick",&isBrick);CHKERRQ(ierr); 290*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"shell",&isShell);CHKERRQ(ierr); 291*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"sphere",&isSphere);CHKERRQ(ierr); 292*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"moebius",&isMoebius);CHKERRQ(ierr); 293*0a96aa3bSJed Brown ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix);CHKERRQ(ierr); 294*0a96aa3bSJed Brown if (isBrick) { 295*0a96aa3bSJed Brown PetscBool flgN, flgP, flgM, flgB, useMorton = PETSC_TRUE, periodic = PETSC_FALSE; 296*0a96aa3bSJed Brown PetscInt N[3] = {2,2,2}, P[3] = {0,0,0}, nretN = P4EST_DIM, nretP = P4EST_DIM, nretB = 2 * P4EST_DIM, i; 297*0a96aa3bSJed Brown PetscReal B[6] = {0.0,1.0,0.0,1.0,0.0,1.0}; 298*0a96aa3bSJed Brown 299*0a96aa3bSJed Brown if (dm->setfromoptionscalled) { 300*0a96aa3bSJed Brown ierr = PetscOptionsGetIntArray(((PetscObject)dm)->options,prefix,"-dm_p4est_brick_size",N,&nretN,&flgN);CHKERRQ(ierr); 301*0a96aa3bSJed Brown ierr = PetscOptionsGetIntArray(((PetscObject)dm)->options,prefix,"-dm_p4est_brick_periodicity",P,&nretP,&flgP);CHKERRQ(ierr); 302*0a96aa3bSJed Brown ierr = PetscOptionsGetRealArray(((PetscObject)dm)->options,prefix,"-dm_p4est_brick_bounds",B,&nretB,&flgB);CHKERRQ(ierr); 303*0a96aa3bSJed Brown ierr = PetscOptionsGetBool(((PetscObject)dm)->options,prefix,"-dm_p4est_brick_use_morton_curve",&useMorton,&flgM);CHKERRQ(ierr); 304*0a96aa3bSJed Brown if (flgN && nretN != P4EST_DIM) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_SIZ,"Need to give %d sizes in -dm_p4est_brick_size, gave %d",P4EST_DIM,nretN); 305*0a96aa3bSJed Brown if (flgP && nretP != P4EST_DIM) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_SIZ,"Need to give %d periodicities in -dm_p4est_brick_periodicity, gave %d",P4EST_DIM,nretP); 306*0a96aa3bSJed Brown if (flgB && nretB != 2 * P4EST_DIM) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_SIZ,"Need to give %d bounds in -dm_p4est_brick_bounds, gave %d",P4EST_DIM,nretP); 307*0a96aa3bSJed Brown } 308*0a96aa3bSJed Brown for (i = 0; i < P4EST_DIM; i++) { 309*0a96aa3bSJed Brown P[i] = (P[i] ? DM_BOUNDARY_PERIODIC : DM_BOUNDARY_NONE); 310*0a96aa3bSJed Brown periodic = (PetscBool)(P[i] || periodic); 311*0a96aa3bSJed Brown if (!flgB) B[2 * i + 1] = N[i]; 312*0a96aa3bSJed Brown } 313*0a96aa3bSJed Brown ierr = DMFTopologyCreateBrick_pforest(dm,N,P,B,topo,useMorton);CHKERRQ(ierr); 314*0a96aa3bSJed Brown /* the maxCell trick is not robust enough, localize on all cells if periodic */ 315*0a96aa3bSJed Brown ierr = DMSetPeriodicity(dm,periodic,NULL,NULL,NULL);CHKERRQ(ierr); 316*0a96aa3bSJed Brown } else { 317*0a96aa3bSJed Brown ierr = PetscNewLog(dm,topo);CHKERRQ(ierr); 318*0a96aa3bSJed Brown 319*0a96aa3bSJed Brown (*topo)->refct = 1; 320*0a96aa3bSJed Brown PetscStackCallP4estReturn((*topo)->conn,p4est_connectivity_new_byname,(name)); 321*0a96aa3bSJed Brown (*topo)->geom = NULL; 322*0a96aa3bSJed Brown if (isMoebius) { 323*0a96aa3bSJed Brown ierr = DMSetCoordinateDim(dm,3);CHKERRQ(ierr); 324*0a96aa3bSJed Brown } 325*0a96aa3bSJed Brown #if defined(P4_TO_P8) 326*0a96aa3bSJed Brown if (isShell) { 327*0a96aa3bSJed Brown PetscReal R2 = 1., R1 = .55; 328*0a96aa3bSJed Brown 329*0a96aa3bSJed Brown if (dm->setfromoptionscalled) { 330*0a96aa3bSJed Brown ierr = PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_shell_outer_radius",&R2,NULL);CHKERRQ(ierr); 331*0a96aa3bSJed Brown ierr = PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_shell_inner_radius",&R1,NULL);CHKERRQ(ierr); 332*0a96aa3bSJed Brown } 333*0a96aa3bSJed Brown PetscStackCallP4estReturn((*topo)->geom,p8est_geometry_new_shell,((*topo)->conn,R2,R1)); 334*0a96aa3bSJed Brown } else if (isSphere) { 335*0a96aa3bSJed Brown PetscReal R2 = 1., R1 = 0.191728, R0 = 0.039856; 336*0a96aa3bSJed Brown 337*0a96aa3bSJed Brown if (dm->setfromoptionscalled) { 338*0a96aa3bSJed Brown ierr = PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_sphere_outer_radius",&R2,NULL);CHKERRQ(ierr); 339*0a96aa3bSJed Brown ierr = PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_sphere_inner_radius",&R1,NULL);CHKERRQ(ierr); 340*0a96aa3bSJed Brown ierr = PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_sphere_core_radius",&R0,NULL);CHKERRQ(ierr); 341*0a96aa3bSJed Brown } 342*0a96aa3bSJed Brown PetscStackCallP4estReturn((*topo)->geom,p8est_geometry_new_sphere,((*topo)->conn,R2,R1,R0)); 343*0a96aa3bSJed Brown } 344*0a96aa3bSJed Brown #endif 345*0a96aa3bSJed Brown ierr = PforestConnectivityEnumerateFacets((*topo)->conn,&(*topo)->tree_face_to_uniq);CHKERRQ(ierr); 346*0a96aa3bSJed Brown } 347*0a96aa3bSJed Brown PetscFunctionReturn(0); 348*0a96aa3bSJed Brown } 349*0a96aa3bSJed Brown 350*0a96aa3bSJed Brown #define DMConvert_plex_pforest _append_pforest(DMConvert_plex) 351*0a96aa3bSJed Brown static PetscErrorCode DMConvert_plex_pforest(DM dm, DMType newtype, DM *pforest) 352*0a96aa3bSJed Brown { 353*0a96aa3bSJed Brown MPI_Comm comm; 354*0a96aa3bSJed Brown PetscBool isPlex; 355*0a96aa3bSJed Brown PetscInt dim; 356*0a96aa3bSJed Brown void *ctx; 357*0a96aa3bSJed Brown PetscErrorCode ierr; 358*0a96aa3bSJed Brown 359*0a96aa3bSJed Brown PetscFunctionBegin; 360*0a96aa3bSJed Brown 361*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 362*0a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 363*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&isPlex);CHKERRQ(ierr); 364*0a96aa3bSJed Brown if (!isPlex) SETERRQ2(comm,PETSC_ERR_ARG_WRONG,"Expected DM type %s, got %s",DMPLEX,((PetscObject)dm)->type_name); 365*0a96aa3bSJed Brown ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 366*0a96aa3bSJed Brown if (dim != P4EST_DIM) SETERRQ2(comm,PETSC_ERR_ARG_WRONG,"Expected DM dimension %d, got %d",P4EST_DIM,dim); 367*0a96aa3bSJed Brown ierr = DMCreate(comm,pforest);CHKERRQ(ierr); 368*0a96aa3bSJed Brown ierr = DMSetType(*pforest,DMPFOREST);CHKERRQ(ierr); 369*0a96aa3bSJed Brown ierr = DMForestSetBaseDM(*pforest,dm);CHKERRQ(ierr); 370*0a96aa3bSJed Brown ierr = DMGetApplicationContext(dm,&ctx);CHKERRQ(ierr); 371*0a96aa3bSJed Brown ierr = DMSetApplicationContext(*pforest,ctx);CHKERRQ(ierr); 372*0a96aa3bSJed Brown ierr = DMCopyDisc(dm,*pforest);CHKERRQ(ierr); 373*0a96aa3bSJed Brown PetscFunctionReturn(0); 374*0a96aa3bSJed Brown } 375*0a96aa3bSJed Brown 376*0a96aa3bSJed Brown #define DMForestDestroy_pforest _append_pforest(DMForestDestroy) 377*0a96aa3bSJed Brown static PetscErrorCode DMForestDestroy_pforest(DM dm) 378*0a96aa3bSJed Brown { 379*0a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 380*0a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 381*0a96aa3bSJed Brown PetscErrorCode ierr; 382*0a96aa3bSJed Brown 383*0a96aa3bSJed Brown PetscFunctionBegin; 384*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 385*0a96aa3bSJed Brown if (pforest->lnodes) PetscStackCallP4est(p4est_lnodes_destroy,(pforest->lnodes)); 386*0a96aa3bSJed Brown pforest->lnodes = NULL; 387*0a96aa3bSJed Brown if (pforest->ghost) PetscStackCallP4est(p4est_ghost_destroy,(pforest->ghost)); 388*0a96aa3bSJed Brown pforest->ghost = NULL; 389*0a96aa3bSJed Brown if (pforest->forest) PetscStackCallP4est(p4est_destroy,(pforest->forest)); 390*0a96aa3bSJed Brown pforest->forest = NULL; 391*0a96aa3bSJed Brown ierr = DMFTopologyDestroy_pforest(&pforest->topo);CHKERRQ(ierr); 392*0a96aa3bSJed Brown ierr = PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_plex_pforest) "_C",NULL);CHKERRQ(ierr); 393*0a96aa3bSJed Brown ierr = PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_pforest_plex) "_C",NULL);CHKERRQ(ierr); 394*0a96aa3bSJed Brown ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",NULL);CHKERRQ(ierr); 395*0a96aa3bSJed Brown ierr = PetscFree(pforest->ghostName);CHKERRQ(ierr); 396*0a96aa3bSJed Brown ierr = DMDestroy(&pforest->plex);CHKERRQ(ierr); 397*0a96aa3bSJed Brown ierr = PetscSFDestroy(&pforest->pointAdaptToSelfSF);CHKERRQ(ierr); 398*0a96aa3bSJed Brown ierr = PetscSFDestroy(&pforest->pointSelfToAdaptSF);CHKERRQ(ierr); 399*0a96aa3bSJed Brown ierr = PetscFree(pforest->pointAdaptToSelfCids);CHKERRQ(ierr); 400*0a96aa3bSJed Brown ierr = PetscFree(pforest->pointSelfToAdaptCids);CHKERRQ(ierr); 401*0a96aa3bSJed Brown ierr = PetscFree(forest->data);CHKERRQ(ierr); 402*0a96aa3bSJed Brown PetscFunctionReturn(0); 403*0a96aa3bSJed Brown } 404*0a96aa3bSJed Brown 405*0a96aa3bSJed Brown #define DMForestTemplate_pforest _append_pforest(DMForestTemplate) 406*0a96aa3bSJed Brown static PetscErrorCode DMForestTemplate_pforest(DM dm, DM tdm) 407*0a96aa3bSJed Brown { 408*0a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 409*0a96aa3bSJed Brown DM_Forest_pforest *tpforest = (DM_Forest_pforest*) ((DM_Forest*) tdm->data)->data; 410*0a96aa3bSJed Brown PetscErrorCode ierr; 411*0a96aa3bSJed Brown 412*0a96aa3bSJed Brown PetscFunctionBegin; 413*0a96aa3bSJed Brown if (pforest->topo) pforest->topo->refct++; 414*0a96aa3bSJed Brown ierr = DMFTopologyDestroy_pforest(&(tpforest->topo));CHKERRQ(ierr); 415*0a96aa3bSJed Brown tpforest->topo = pforest->topo; 416*0a96aa3bSJed Brown PetscFunctionReturn(0); 417*0a96aa3bSJed Brown } 418*0a96aa3bSJed Brown 419*0a96aa3bSJed Brown #define DMPlexCreateConnectivity_pforest _append_pforest(DMPlexCreateConnectivity) 420*0a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM,p4est_connectivity_t**,PetscInt**); 421*0a96aa3bSJed Brown 422*0a96aa3bSJed Brown typedef struct _PforestAdaptCtx 423*0a96aa3bSJed Brown { 424*0a96aa3bSJed Brown PetscInt maxLevel; 425*0a96aa3bSJed Brown PetscInt minLevel; 426*0a96aa3bSJed Brown PetscInt currLevel; 427*0a96aa3bSJed Brown PetscBool anyChange; 428*0a96aa3bSJed Brown } 429*0a96aa3bSJed Brown PforestAdaptCtx; 430*0a96aa3bSJed Brown 431*0a96aa3bSJed Brown static int pforest_coarsen_currlevel(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 432*0a96aa3bSJed Brown { 433*0a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 434*0a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 435*0a96aa3bSJed Brown PetscInt currLevel = ctx->currLevel; 436*0a96aa3bSJed Brown 437*0a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 438*0a96aa3bSJed Brown return (int) ((PetscInt) quadrants[0]->level == currLevel); 439*0a96aa3bSJed Brown } 440*0a96aa3bSJed Brown 441*0a96aa3bSJed Brown static int pforest_coarsen_uniform(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 442*0a96aa3bSJed Brown { 443*0a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 444*0a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 445*0a96aa3bSJed Brown 446*0a96aa3bSJed Brown return (int) ((PetscInt) quadrants[0]->level > minLevel); 447*0a96aa3bSJed Brown } 448*0a96aa3bSJed Brown 449*0a96aa3bSJed Brown static int pforest_coarsen_flag_any(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 450*0a96aa3bSJed Brown { 451*0a96aa3bSJed Brown PetscInt i; 452*0a96aa3bSJed Brown PetscBool any = PETSC_FALSE; 453*0a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 454*0a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 455*0a96aa3bSJed Brown 456*0a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 457*0a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 458*0a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_KEEP) { 459*0a96aa3bSJed Brown any = PETSC_FALSE; 460*0a96aa3bSJed Brown break; 461*0a96aa3bSJed Brown } 462*0a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_COARSEN) { 463*0a96aa3bSJed Brown any = PETSC_TRUE; 464*0a96aa3bSJed Brown break; 465*0a96aa3bSJed Brown } 466*0a96aa3bSJed Brown } 467*0a96aa3bSJed Brown return any ? 1 : 0; 468*0a96aa3bSJed Brown } 469*0a96aa3bSJed Brown 470*0a96aa3bSJed Brown static int pforest_coarsen_flag_all(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[]) 471*0a96aa3bSJed Brown { 472*0a96aa3bSJed Brown PetscInt i; 473*0a96aa3bSJed Brown PetscBool all = PETSC_TRUE; 474*0a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 475*0a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel; 476*0a96aa3bSJed Brown 477*0a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0; 478*0a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 479*0a96aa3bSJed Brown if (quadrants[i]->p.user_int != DM_ADAPT_COARSEN) { 480*0a96aa3bSJed Brown all = PETSC_FALSE; 481*0a96aa3bSJed Brown break; 482*0a96aa3bSJed Brown } 483*0a96aa3bSJed Brown } 484*0a96aa3bSJed Brown return all ? 1 : 0; 485*0a96aa3bSJed Brown } 486*0a96aa3bSJed Brown 487*0a96aa3bSJed Brown static void pforest_init_determine(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 488*0a96aa3bSJed Brown { 489*0a96aa3bSJed Brown quadrant->p.user_int = DM_ADAPT_DETERMINE; 490*0a96aa3bSJed Brown } 491*0a96aa3bSJed Brown 492*0a96aa3bSJed Brown static int pforest_refine_uniform(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 493*0a96aa3bSJed Brown { 494*0a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 495*0a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 496*0a96aa3bSJed Brown 497*0a96aa3bSJed Brown return ((PetscInt) quadrant->level < maxLevel); 498*0a96aa3bSJed Brown } 499*0a96aa3bSJed Brown 500*0a96aa3bSJed Brown static int pforest_refine_flag(p4est_t * p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant) 501*0a96aa3bSJed Brown { 502*0a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx*) p4est->user_pointer; 503*0a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel; 504*0a96aa3bSJed Brown 505*0a96aa3bSJed Brown if ((PetscInt) quadrant->level >= maxLevel) return 0; 506*0a96aa3bSJed Brown 507*0a96aa3bSJed Brown return (quadrant->p.user_int == DM_ADAPT_REFINE); 508*0a96aa3bSJed Brown } 509*0a96aa3bSJed Brown 510*0a96aa3bSJed 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) 511*0a96aa3bSJed Brown { 512*0a96aa3bSJed Brown PetscMPIInt rank = p4estFrom->mpirank; 513*0a96aa3bSJed Brown p4est_topidx_t t; 514*0a96aa3bSJed Brown PetscInt toFineLeaves = 0, fromFineLeaves = 0; 515*0a96aa3bSJed Brown 516*0a96aa3bSJed Brown PetscFunctionBegin; 517*0a96aa3bSJed Brown for (t = flt; t <= llt; t++) { /* count roots and leaves */ 518*0a96aa3bSJed Brown p4est_tree_t *treeFrom = &(((p4est_tree_t*) p4estFrom->trees->array)[t]); 519*0a96aa3bSJed Brown p4est_tree_t *treeTo = &(((p4est_tree_t*) p4estTo->trees->array)[t]); 520*0a96aa3bSJed Brown p4est_quadrant_t *firstFrom = &treeFrom->first_desc; 521*0a96aa3bSJed Brown p4est_quadrant_t *firstTo = &treeTo->first_desc; 522*0a96aa3bSJed Brown PetscInt numFrom = (PetscInt) treeFrom->quadrants.elem_count; 523*0a96aa3bSJed Brown PetscInt numTo = (PetscInt) treeTo->quadrants.elem_count; 524*0a96aa3bSJed Brown p4est_quadrant_t *quadsFrom = (p4est_quadrant_t*) treeFrom->quadrants.array; 525*0a96aa3bSJed Brown p4est_quadrant_t *quadsTo = (p4est_quadrant_t*) treeTo->quadrants.array; 526*0a96aa3bSJed Brown PetscInt currentFrom, currentTo; 527*0a96aa3bSJed Brown PetscInt treeOffsetFrom = (PetscInt) treeFrom->quadrants_offset; 528*0a96aa3bSJed Brown PetscInt treeOffsetTo = (PetscInt) treeTo->quadrants_offset; 529*0a96aa3bSJed Brown int comp; 530*0a96aa3bSJed Brown 531*0a96aa3bSJed Brown PetscStackCallP4estReturn(comp,p4est_quadrant_is_equal,(firstFrom,firstTo)); 532*0a96aa3bSJed Brown if (!comp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"non-matching partitions"); 533*0a96aa3bSJed Brown 534*0a96aa3bSJed Brown for (currentFrom = 0, currentTo = 0; currentFrom < numFrom && currentTo < numTo;) { 535*0a96aa3bSJed Brown p4est_quadrant_t *quadFrom = &quadsFrom[currentFrom]; 536*0a96aa3bSJed Brown p4est_quadrant_t *quadTo = &quadsTo[currentTo]; 537*0a96aa3bSJed Brown 538*0a96aa3bSJed Brown if (quadFrom->level == quadTo->level) { 539*0a96aa3bSJed Brown if (toLeaves) { 540*0a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 541*0a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 542*0a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 543*0a96aa3bSJed Brown } 544*0a96aa3bSJed Brown toFineLeaves++; 545*0a96aa3bSJed Brown currentFrom++; 546*0a96aa3bSJed Brown currentTo++; 547*0a96aa3bSJed Brown } else { 548*0a96aa3bSJed Brown int fromIsAncestor; 549*0a96aa3bSJed Brown 550*0a96aa3bSJed Brown PetscStackCallP4estReturn(fromIsAncestor,p4est_quadrant_is_ancestor,(quadFrom,quadTo)); 551*0a96aa3bSJed Brown if (fromIsAncestor) { 552*0a96aa3bSJed Brown p4est_quadrant_t lastDesc; 553*0a96aa3bSJed Brown 554*0a96aa3bSJed Brown if (toLeaves) { 555*0a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset; 556*0a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank; 557*0a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset; 558*0a96aa3bSJed Brown } 559*0a96aa3bSJed Brown toFineLeaves++; 560*0a96aa3bSJed Brown currentTo++; 561*0a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_last_descendant,(quadFrom,&lastDesc,quadTo->level)); 562*0a96aa3bSJed Brown PetscStackCallP4estReturn(comp,p4est_quadrant_is_equal,(quadTo,&lastDesc)); 563*0a96aa3bSJed Brown if (comp) currentFrom++; 564*0a96aa3bSJed Brown } else { 565*0a96aa3bSJed Brown p4est_quadrant_t lastDesc; 566*0a96aa3bSJed Brown 567*0a96aa3bSJed Brown if (fromLeaves) { 568*0a96aa3bSJed Brown fromLeaves[fromFineLeaves] = currentFrom + treeOffsetFrom + FromOffset; 569*0a96aa3bSJed Brown toRoots[fromFineLeaves].rank = rank; 570*0a96aa3bSJed Brown toRoots[fromFineLeaves].index = currentTo + treeOffsetTo + ToOffset; 571*0a96aa3bSJed Brown } 572*0a96aa3bSJed Brown fromFineLeaves++; 573*0a96aa3bSJed Brown currentFrom++; 574*0a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_last_descendant,(quadTo,&lastDesc,quadFrom->level)); 575*0a96aa3bSJed Brown PetscStackCallP4estReturn(comp,p4est_quadrant_is_equal,(quadFrom,&lastDesc)); 576*0a96aa3bSJed Brown if (comp) currentTo++; 577*0a96aa3bSJed Brown } 578*0a96aa3bSJed Brown } 579*0a96aa3bSJed Brown } 580*0a96aa3bSJed Brown } 581*0a96aa3bSJed Brown *toFineLeavesCount = toFineLeaves; 582*0a96aa3bSJed Brown *fromFineLeavesCount = fromFineLeaves; 583*0a96aa3bSJed Brown PetscFunctionReturn(0); 584*0a96aa3bSJed Brown } 585*0a96aa3bSJed Brown 586*0a96aa3bSJed Brown /* Compute the maximum level across all the trees */ 587*0a96aa3bSJed Brown static PetscErrorCode DMPforestGetRefinementLevel(DM dm, PetscInt *lev) 588*0a96aa3bSJed Brown { 589*0a96aa3bSJed Brown p4est_topidx_t t, flt, llt; 590*0a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 591*0a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 592*0a96aa3bSJed Brown PetscInt maxlevelloc = 0; 593*0a96aa3bSJed Brown p4est_t *p4est; 594*0a96aa3bSJed Brown PetscErrorCode ierr; 595*0a96aa3bSJed Brown 596*0a96aa3bSJed Brown PetscFunctionBegin; 597*0a96aa3bSJed Brown if (!pforest) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Missing DM_Forest_pforest"); 598*0a96aa3bSJed Brown if (!pforest->forest) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Missing p4est_t"); 599*0a96aa3bSJed Brown p4est = pforest->forest; 600*0a96aa3bSJed Brown flt = p4est->first_local_tree; 601*0a96aa3bSJed Brown llt = p4est->last_local_tree; 602*0a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 603*0a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4est->trees->array)[t]); 604*0a96aa3bSJed Brown maxlevelloc = PetscMax((PetscInt)tree->maxlevel,maxlevelloc); 605*0a96aa3bSJed Brown } 606*0a96aa3bSJed Brown ierr = MPIU_Allreduce(&maxlevelloc,lev,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 607*0a96aa3bSJed Brown PetscFunctionReturn(0); 608*0a96aa3bSJed Brown } 609*0a96aa3bSJed Brown 610*0a96aa3bSJed Brown /* Puts identity in coarseToFine */ 611*0a96aa3bSJed Brown /* assumes a matching partition */ 612*0a96aa3bSJed Brown static PetscErrorCode DMPforestComputeLocalCellTransferSF(MPI_Comm comm, p4est_t *p4estFrom, PetscInt FromOffset, p4est_t *p4estTo, PetscInt ToOffset, PetscSF *fromCoarseToFine, PetscSF *toCoarseFromFine) 613*0a96aa3bSJed Brown { 614*0a96aa3bSJed Brown p4est_topidx_t flt, llt; 615*0a96aa3bSJed Brown PetscSF fromCoarse, toCoarse; 616*0a96aa3bSJed Brown PetscInt numRootsFrom, numRootsTo, numLeavesFrom, numLeavesTo; 617*0a96aa3bSJed Brown PetscInt *fromLeaves = NULL, *toLeaves = NULL; 618*0a96aa3bSJed Brown PetscSFNode *fromRoots = NULL, *toRoots = NULL; 619*0a96aa3bSJed Brown PetscErrorCode ierr; 620*0a96aa3bSJed Brown 621*0a96aa3bSJed Brown PetscFunctionBegin; 622*0a96aa3bSJed Brown flt = p4estFrom->first_local_tree; 623*0a96aa3bSJed Brown llt = p4estFrom->last_local_tree; 624*0a96aa3bSJed Brown ierr = PetscSFCreate(comm,&fromCoarse);CHKERRQ(ierr); 625*0a96aa3bSJed Brown if (toCoarseFromFine) { 626*0a96aa3bSJed Brown ierr = PetscSFCreate(comm,&toCoarse);CHKERRQ(ierr); 627*0a96aa3bSJed Brown } 628*0a96aa3bSJed Brown numRootsFrom = p4estFrom->local_num_quadrants + FromOffset; 629*0a96aa3bSJed Brown numRootsTo = p4estTo->local_num_quadrants + ToOffset; 630*0a96aa3bSJed Brown ierr = DMPforestComputeLocalCellTransferSF_loop(p4estFrom,FromOffset,p4estTo,ToOffset,flt,llt,&numLeavesTo,NULL,NULL,&numLeavesFrom,NULL,NULL);CHKERRQ(ierr); 631*0a96aa3bSJed Brown ierr = PetscMalloc1(numLeavesTo,&toLeaves);CHKERRQ(ierr); 632*0a96aa3bSJed Brown ierr = PetscMalloc1(numLeavesTo,&fromRoots);CHKERRQ(ierr); 633*0a96aa3bSJed Brown if (toCoarseFromFine) { 634*0a96aa3bSJed Brown ierr = PetscMalloc1(numLeavesFrom,&fromLeaves);CHKERRQ(ierr); 635*0a96aa3bSJed Brown ierr = PetscMalloc1(numLeavesFrom,&fromRoots);CHKERRQ(ierr); 636*0a96aa3bSJed Brown } 637*0a96aa3bSJed Brown ierr = DMPforestComputeLocalCellTransferSF_loop(p4estFrom,FromOffset,p4estTo,ToOffset,flt,llt,&numLeavesTo,toLeaves,fromRoots,&numLeavesFrom,fromLeaves,toRoots);CHKERRQ(ierr); 638*0a96aa3bSJed Brown if (!ToOffset && (numLeavesTo == numRootsTo)) { /* compress */ 639*0a96aa3bSJed Brown ierr = PetscFree(toLeaves);CHKERRQ(ierr); 640*0a96aa3bSJed Brown ierr = PetscSFSetGraph(fromCoarse,numRootsFrom,numLeavesTo,NULL,PETSC_OWN_POINTER,fromRoots,PETSC_OWN_POINTER);CHKERRQ(ierr); 641*0a96aa3bSJed Brown } else { /* generic */ 642*0a96aa3bSJed Brown ierr = PetscSFSetGraph(fromCoarse,numRootsFrom,numLeavesTo,toLeaves,PETSC_OWN_POINTER,fromRoots,PETSC_OWN_POINTER);CHKERRQ(ierr); 643*0a96aa3bSJed Brown } 644*0a96aa3bSJed Brown *fromCoarseToFine = fromCoarse; 645*0a96aa3bSJed Brown if (toCoarseFromFine) { 646*0a96aa3bSJed Brown ierr = PetscSFSetGraph(toCoarse,numRootsTo,numLeavesFrom,fromLeaves,PETSC_OWN_POINTER,toRoots,PETSC_OWN_POINTER);CHKERRQ(ierr); 647*0a96aa3bSJed Brown *toCoarseFromFine = toCoarse; 648*0a96aa3bSJed Brown } 649*0a96aa3bSJed Brown PetscFunctionReturn(0); 650*0a96aa3bSJed Brown } 651*0a96aa3bSJed Brown 652*0a96aa3bSJed Brown /* range of processes whose B sections overlap this ranks A section */ 653*0a96aa3bSJed Brown static PetscErrorCode DMPforestComputeOverlappingRanks(PetscMPIInt size, PetscMPIInt rank, p4est_t *p4estA, p4est_t *p4estB, PetscInt *startB, PetscInt *endB) 654*0a96aa3bSJed Brown { 655*0a96aa3bSJed Brown p4est_quadrant_t * myCoarseStart = &(p4estA->global_first_position[rank]); 656*0a96aa3bSJed Brown p4est_quadrant_t * myCoarseEnd = &(p4estA->global_first_position[rank+1]); 657*0a96aa3bSJed Brown p4est_quadrant_t * globalFirstB = p4estB->global_first_position; 658*0a96aa3bSJed Brown 659*0a96aa3bSJed Brown PetscFunctionBegin; 660*0a96aa3bSJed Brown *startB = -1; 661*0a96aa3bSJed Brown *endB = -1; 662*0a96aa3bSJed Brown if (p4estA->local_num_quadrants) { 663*0a96aa3bSJed Brown PetscInt lo, hi, guess; 664*0a96aa3bSJed Brown /* binary search to find interval containing myCoarseStart */ 665*0a96aa3bSJed Brown lo = 0; 666*0a96aa3bSJed Brown hi = size; 667*0a96aa3bSJed Brown guess = rank; 668*0a96aa3bSJed Brown while (1) { 669*0a96aa3bSJed Brown int startCompMy, myCompEnd; 670*0a96aa3bSJed Brown 671*0a96aa3bSJed Brown PetscStackCallP4estReturn(startCompMy,p4est_quadrant_compare_piggy,(&globalFirstB[guess],myCoarseStart)); 672*0a96aa3bSJed Brown PetscStackCallP4estReturn(myCompEnd,p4est_quadrant_compare_piggy,(myCoarseStart,&globalFirstB[guess+1])); 673*0a96aa3bSJed Brown if (startCompMy <= 0 && myCompEnd < 0) { 674*0a96aa3bSJed Brown *startB = guess; 675*0a96aa3bSJed Brown break; 676*0a96aa3bSJed Brown } else if (startCompMy > 0) { /* guess is to high */ 677*0a96aa3bSJed Brown hi = guess; 678*0a96aa3bSJed Brown } else { /* guess is to low */ 679*0a96aa3bSJed Brown lo = guess + 1; 680*0a96aa3bSJed Brown } 681*0a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 682*0a96aa3bSJed Brown } 683*0a96aa3bSJed Brown /* reset bounds, but not guess */ 684*0a96aa3bSJed Brown lo = 0; 685*0a96aa3bSJed Brown hi = size; 686*0a96aa3bSJed Brown while (1) { 687*0a96aa3bSJed Brown int startCompMy, myCompEnd; 688*0a96aa3bSJed Brown 689*0a96aa3bSJed Brown PetscStackCallP4estReturn(startCompMy,p4est_quadrant_compare_piggy,(&globalFirstB[guess],myCoarseEnd)); 690*0a96aa3bSJed Brown PetscStackCallP4estReturn(myCompEnd,p4est_quadrant_compare_piggy,(myCoarseEnd,&globalFirstB[guess+1])); 691*0a96aa3bSJed Brown if (startCompMy < 0 && myCompEnd <= 0) { /* notice that the comparison operators are different from above */ 692*0a96aa3bSJed Brown *endB = guess + 1; 693*0a96aa3bSJed Brown break; 694*0a96aa3bSJed Brown } else if (startCompMy >= 0) { /* guess is to high */ 695*0a96aa3bSJed Brown hi = guess; 696*0a96aa3bSJed Brown } else { /* guess is to low */ 697*0a96aa3bSJed Brown lo = guess + 1; 698*0a96aa3bSJed Brown } 699*0a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 700*0a96aa3bSJed Brown } 701*0a96aa3bSJed Brown } 702*0a96aa3bSJed Brown PetscFunctionReturn(0); 703*0a96aa3bSJed Brown } 704*0a96aa3bSJed Brown 705*0a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM,DM*); 706*0a96aa3bSJed Brown 707*0a96aa3bSJed Brown #define DMSetUp_pforest _append_pforest(DMSetUp) 708*0a96aa3bSJed Brown static PetscErrorCode DMSetUp_pforest(DM dm) 709*0a96aa3bSJed Brown { 710*0a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 711*0a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 712*0a96aa3bSJed Brown DM base, adaptFrom; 713*0a96aa3bSJed Brown DMForestTopology topoName; 714*0a96aa3bSJed Brown PetscSF preCoarseToFine = NULL, coarseToPreFine = NULL; 715*0a96aa3bSJed Brown PforestAdaptCtx ctx; 716*0a96aa3bSJed Brown PetscErrorCode ierr; 717*0a96aa3bSJed Brown 718*0a96aa3bSJed Brown PetscFunctionBegin; 719*0a96aa3bSJed Brown ctx.minLevel = PETSC_MAX_INT; 720*0a96aa3bSJed Brown ctx.maxLevel = 0; 721*0a96aa3bSJed Brown ctx.currLevel = 0; 722*0a96aa3bSJed Brown ctx.anyChange = PETSC_FALSE; 723*0a96aa3bSJed Brown /* sanity check */ 724*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(dm,&adaptFrom);CHKERRQ(ierr); 725*0a96aa3bSJed Brown ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr); 726*0a96aa3bSJed Brown ierr = DMForestGetTopology(dm,&topoName);CHKERRQ(ierr); 727*0a96aa3bSJed Brown if (!adaptFrom && !base && !topoName) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"A forest needs a topology, a base DM, or a DM to adapt from"); 728*0a96aa3bSJed Brown 729*0a96aa3bSJed Brown /* === Step 1: DMFTopology === */ 730*0a96aa3bSJed Brown if (adaptFrom) { /* reference already created topology */ 731*0a96aa3bSJed Brown PetscBool ispforest; 732*0a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest*) adaptFrom->data; 733*0a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest*) aforest->data; 734*0a96aa3bSJed Brown 735*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject)adaptFrom,DMPFOREST,&ispforest);CHKERRQ(ierr); 736*0a96aa3bSJed Brown if (!ispforest) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_NOTSAMETYPE,"Trying to adapt from %s, which is not %s",((PetscObject)adaptFrom)->type_name,DMPFOREST); 737*0a96aa3bSJed Brown if (!apforest->topo) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"The pre-adaptation forest must have a topology"); 738*0a96aa3bSJed Brown ierr = DMSetUp(adaptFrom);CHKERRQ(ierr); 739*0a96aa3bSJed Brown ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr); 740*0a96aa3bSJed Brown ierr = DMForestGetTopology(dm,&topoName);CHKERRQ(ierr); 741*0a96aa3bSJed Brown } else if (base) { /* construct a connectivity from base */ 742*0a96aa3bSJed Brown PetscBool isPlex, isDA; 743*0a96aa3bSJed Brown 744*0a96aa3bSJed Brown ierr = PetscObjectGetName((PetscObject)base,&topoName);CHKERRQ(ierr); 745*0a96aa3bSJed Brown ierr = DMForestSetTopology(dm,topoName);CHKERRQ(ierr); 746*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject)base,DMPLEX,&isPlex);CHKERRQ(ierr); 747*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject)base,DMDA,&isDA);CHKERRQ(ierr); 748*0a96aa3bSJed Brown if (isPlex) { 749*0a96aa3bSJed Brown MPI_Comm comm = PetscObjectComm((PetscObject)dm); 750*0a96aa3bSJed Brown PetscInt depth; 751*0a96aa3bSJed Brown PetscMPIInt size; 752*0a96aa3bSJed Brown p4est_connectivity_t *conn = NULL; 753*0a96aa3bSJed Brown DMFTopology_pforest *topo; 754*0a96aa3bSJed Brown PetscInt *tree_face_to_uniq = NULL; 755*0a96aa3bSJed Brown PetscErrorCode ierr; 756*0a96aa3bSJed Brown 757*0a96aa3bSJed Brown ierr = DMPlexGetDepth(base,&depth);CHKERRQ(ierr); 758*0a96aa3bSJed Brown if (depth == 1) { 759*0a96aa3bSJed Brown DM connDM; 760*0a96aa3bSJed Brown 761*0a96aa3bSJed Brown ierr = DMPlexInterpolate(base,&connDM);CHKERRQ(ierr); 762*0a96aa3bSJed Brown base = connDM; 763*0a96aa3bSJed Brown ierr = DMForestSetBaseDM(dm,base);CHKERRQ(ierr); 764*0a96aa3bSJed Brown ierr = DMDestroy(&connDM);CHKERRQ(ierr); 765*0a96aa3bSJed Brown } else if (depth != P4EST_DIM) SETERRQ2(comm,PETSC_ERR_ARG_WRONG,"Base plex is neither interpolated nor uninterpolated? depth %D, expected 2 or %d",depth,P4EST_DIM + 1); 766*0a96aa3bSJed Brown ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 767*0a96aa3bSJed Brown if (size > 1) { 768*0a96aa3bSJed Brown DM dmRedundant; 769*0a96aa3bSJed Brown PetscSF sf; 770*0a96aa3bSJed Brown 771*0a96aa3bSJed Brown ierr = DMPlexGetRedundantDM(base,&sf,&dmRedundant);CHKERRQ(ierr); 772*0a96aa3bSJed Brown if (!dmRedundant) SETERRQ(comm,PETSC_ERR_PLIB,"Could not create redundant DM"); 773*0a96aa3bSJed Brown ierr = PetscObjectCompose((PetscObject)dmRedundant,"_base_migration_sf",(PetscObject)sf);CHKERRQ(ierr); 774*0a96aa3bSJed Brown ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 775*0a96aa3bSJed Brown base = dmRedundant; 776*0a96aa3bSJed Brown ierr = DMForestSetBaseDM(dm,base);CHKERRQ(ierr); 777*0a96aa3bSJed Brown ierr = DMDestroy(&dmRedundant);CHKERRQ(ierr); 778*0a96aa3bSJed Brown } 779*0a96aa3bSJed Brown ierr = DMViewFromOptions(base,NULL,"-dm_p4est_base_view");CHKERRQ(ierr); 780*0a96aa3bSJed Brown ierr = DMPlexCreateConnectivity_pforest(base,&conn,&tree_face_to_uniq);CHKERRQ(ierr); 781*0a96aa3bSJed Brown ierr = PetscNewLog(dm,&topo);CHKERRQ(ierr); 782*0a96aa3bSJed Brown topo->refct = 1; 783*0a96aa3bSJed Brown topo->conn = conn; 784*0a96aa3bSJed Brown topo->geom = NULL; 785*0a96aa3bSJed Brown { 786*0a96aa3bSJed Brown PetscErrorCode (*map)(DM,PetscInt,PetscInt,const PetscReal[],PetscReal[],void*); 787*0a96aa3bSJed Brown void *mapCtx; 788*0a96aa3bSJed Brown 789*0a96aa3bSJed Brown ierr = DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx);CHKERRQ(ierr); 790*0a96aa3bSJed Brown if (map) { 791*0a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest; 792*0a96aa3bSJed Brown p4est_geometry_t *geom; 793*0a96aa3bSJed Brown 794*0a96aa3bSJed Brown ierr = PetscNew(&geom_pforest);CHKERRQ(ierr); 795*0a96aa3bSJed Brown ierr = DMGetCoordinateDim(dm,&geom_pforest->coordDim);CHKERRQ(ierr); 796*0a96aa3bSJed Brown geom_pforest->map = map; 797*0a96aa3bSJed Brown geom_pforest->mapCtx = mapCtx; 798*0a96aa3bSJed Brown PetscStackCallP4estReturn(geom_pforest->inner,p4est_geometry_new_connectivity,(conn)); 799*0a96aa3bSJed Brown ierr = PetscNew(&geom);CHKERRQ(ierr); 800*0a96aa3bSJed Brown geom->name = topoName; 801*0a96aa3bSJed Brown geom->user = geom_pforest; 802*0a96aa3bSJed Brown geom->X = GeometryMapping_pforest; 803*0a96aa3bSJed Brown geom->destroy = GeometryDestroy_pforest; 804*0a96aa3bSJed Brown topo->geom = geom; 805*0a96aa3bSJed Brown } 806*0a96aa3bSJed Brown } 807*0a96aa3bSJed Brown topo->tree_face_to_uniq = tree_face_to_uniq; 808*0a96aa3bSJed Brown pforest->topo = topo; 809*0a96aa3bSJed Brown } else if (isDA) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Not implemented yet"); 810*0a96aa3bSJed Brown #if 0 811*0a96aa3bSJed Brown PetscInt N[3], P[3]; 812*0a96aa3bSJed Brown 813*0a96aa3bSJed Brown /* get the sizes, periodicities */ 814*0a96aa3bSJed Brown /* ... */ 815*0a96aa3bSJed Brown /* don't use Morton order */ 816*0a96aa3bSJed Brown ierr = DMFTopologyCreateBrick_pforest(dm,N,P,&pforest->topo,PETSC_FALSE);CHKERRQ(ierr); 817*0a96aa3bSJed Brown #endif 818*0a96aa3bSJed Brown { 819*0a96aa3bSJed Brown PetscInt numLabels, l; 820*0a96aa3bSJed Brown 821*0a96aa3bSJed Brown ierr = DMGetNumLabels(base,&numLabels);CHKERRQ(ierr); 822*0a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 823*0a96aa3bSJed Brown PetscBool isDepth, isGhost, isVTK, isDim, isCellType; 824*0a96aa3bSJed Brown DMLabel label, labelNew; 825*0a96aa3bSJed Brown PetscInt defVal; 826*0a96aa3bSJed Brown const char *name; 827*0a96aa3bSJed Brown 828*0a96aa3bSJed Brown ierr = DMGetLabelName(base, l, &name);CHKERRQ(ierr); 829*0a96aa3bSJed Brown ierr = DMGetLabelByNum(base, l, &label);CHKERRQ(ierr); 830*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"depth",&isDepth);CHKERRQ(ierr); 831*0a96aa3bSJed Brown if (isDepth) continue; 832*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"dim",&isDim);CHKERRQ(ierr); 833*0a96aa3bSJed Brown if (isDim) continue; 834*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"celltype",&isCellType);CHKERRQ(ierr); 835*0a96aa3bSJed Brown if (isCellType) continue; 836*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"ghost",&isGhost);CHKERRQ(ierr); 837*0a96aa3bSJed Brown if (isGhost) continue; 838*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"vtk",&isVTK);CHKERRQ(ierr); 839*0a96aa3bSJed Brown if (isVTK) continue; 840*0a96aa3bSJed Brown ierr = DMCreateLabel(dm,name);CHKERRQ(ierr); 841*0a96aa3bSJed Brown ierr = DMGetLabel(dm,name,&labelNew);CHKERRQ(ierr); 842*0a96aa3bSJed Brown ierr = DMLabelGetDefaultValue(label,&defVal);CHKERRQ(ierr); 843*0a96aa3bSJed Brown ierr = DMLabelSetDefaultValue(labelNew,defVal);CHKERRQ(ierr); 844*0a96aa3bSJed Brown } 845*0a96aa3bSJed Brown /* map dm points (internal plex) to base 846*0a96aa3bSJed Brown we currently create the subpoint_map for the entire hierarchy, starting from the finest forest 847*0a96aa3bSJed Brown and propagating back to the coarsest 848*0a96aa3bSJed Brown This is not an optimal approach, since we need the map only on the coarsest level 849*0a96aa3bSJed Brown during DMForestTransferVecFromBase */ 850*0a96aa3bSJed Brown ierr = DMForestGetMinimumRefinement(dm,&l);CHKERRQ(ierr); 851*0a96aa3bSJed Brown if (!l) { 852*0a96aa3bSJed Brown ierr = DMCreateLabel(dm,"_forest_base_subpoint_map");CHKERRQ(ierr); 853*0a96aa3bSJed Brown } 854*0a96aa3bSJed Brown } 855*0a96aa3bSJed Brown } else { /* construct from topology name */ 856*0a96aa3bSJed Brown DMFTopology_pforest *topo; 857*0a96aa3bSJed Brown 858*0a96aa3bSJed Brown ierr = DMFTopologyCreate_pforest(dm,topoName,&topo);CHKERRQ(ierr); 859*0a96aa3bSJed Brown pforest->topo = topo; 860*0a96aa3bSJed Brown /* TODO: construct base? */ 861*0a96aa3bSJed Brown } 862*0a96aa3bSJed Brown 863*0a96aa3bSJed Brown /* === Step 2: get the leaves of the forest === */ 864*0a96aa3bSJed Brown if (adaptFrom) { /* start with the old forest */ 865*0a96aa3bSJed Brown DMLabel adaptLabel; 866*0a96aa3bSJed Brown PetscInt defaultValue; 867*0a96aa3bSJed Brown PetscInt numValues, numValuesGlobal, cLocalStart, count; 868*0a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest*) adaptFrom->data; 869*0a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest*) aforest->data; 870*0a96aa3bSJed Brown PetscBool computeAdaptSF; 871*0a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 872*0a96aa3bSJed Brown 873*0a96aa3bSJed Brown flt = apforest->forest->first_local_tree; 874*0a96aa3bSJed Brown llt = apforest->forest->last_local_tree; 875*0a96aa3bSJed Brown cLocalStart = apforest->cLocalStart; 876*0a96aa3bSJed Brown ierr = DMForestGetComputeAdaptivitySF(dm,&computeAdaptSF);CHKERRQ(ierr); 877*0a96aa3bSJed Brown PetscStackCallP4estReturn(pforest->forest,p4est_copy,(apforest->forest, 0)); /* 0 indicates no data copying */ 878*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityLabel(dm,&adaptLabel);CHKERRQ(ierr); 879*0a96aa3bSJed Brown if (adaptLabel) { 880*0a96aa3bSJed Brown /* apply the refinement/coarsening by flags, plus minimum/maximum refinement */ 881*0a96aa3bSJed Brown ierr = DMLabelGetNumValues(adaptLabel,&numValues);CHKERRQ(ierr); 882*0a96aa3bSJed Brown ierr = MPI_Allreduce(&numValues,&numValuesGlobal,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)adaptFrom));CHKERRMPI(ierr); 883*0a96aa3bSJed Brown ierr = DMLabelGetDefaultValue(adaptLabel,&defaultValue);CHKERRQ(ierr); 884*0a96aa3bSJed Brown if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN_LAST) { /* uniform coarsen of the last level only (equivalent to DM_ADAPT_COARSEN for conforming grids) */ 885*0a96aa3bSJed Brown ierr = DMForestGetMinimumRefinement(dm,&ctx.minLevel);CHKERRQ(ierr); 886*0a96aa3bSJed Brown ierr = DMPforestGetRefinementLevel(dm,&ctx.currLevel);CHKERRQ(ierr); 887*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 888*0a96aa3bSJed Brown PetscStackCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_currlevel,NULL)); 889*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 890*0a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 891*0a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 892*0a96aa3bSJed Brown if (computeAdaptSF) { 893*0a96aa3bSJed Brown ierr = DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),pforest->forest,0,apforest->forest,apforest->cLocalStart,&coarseToPreFine,NULL);CHKERRQ(ierr); 894*0a96aa3bSJed Brown } 895*0a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN) { /* uniform coarsen */ 896*0a96aa3bSJed Brown ierr = DMForestGetMinimumRefinement(dm,&ctx.minLevel);CHKERRQ(ierr); 897*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 898*0a96aa3bSJed Brown PetscStackCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_uniform,NULL)); 899*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 900*0a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 901*0a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 902*0a96aa3bSJed Brown if (computeAdaptSF) { 903*0a96aa3bSJed Brown ierr = DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),pforest->forest,0,apforest->forest,apforest->cLocalStart,&coarseToPreFine,NULL);CHKERRQ(ierr); 904*0a96aa3bSJed Brown } 905*0a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_REFINE) { /* uniform refine */ 906*0a96aa3bSJed Brown ierr = DMForestGetMaximumRefinement(dm,&ctx.maxLevel);CHKERRQ(ierr); 907*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 908*0a96aa3bSJed Brown PetscStackCallP4est(p4est_refine,(pforest->forest,0,pforest_refine_uniform,NULL)); 909*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 910*0a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 911*0a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */ 912*0a96aa3bSJed Brown if (computeAdaptSF) { 913*0a96aa3bSJed Brown ierr = DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),apforest->forest,apforest->cLocalStart,pforest->forest,0,&preCoarseToFine,NULL);CHKERRQ(ierr); 914*0a96aa3bSJed Brown } 915*0a96aa3bSJed Brown } else if (numValuesGlobal) { 916*0a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 917*0a96aa3bSJed Brown PetscInt *cellFlags; 918*0a96aa3bSJed Brown DMForestAdaptivityStrategy strategy; 919*0a96aa3bSJed Brown PetscSF cellSF; 920*0a96aa3bSJed Brown PetscInt c, cStart, cEnd; 921*0a96aa3bSJed Brown PetscBool adaptAny; 922*0a96aa3bSJed Brown 923*0a96aa3bSJed Brown ierr = DMForestGetMaximumRefinement(dm,&ctx.maxLevel);CHKERRQ(ierr); 924*0a96aa3bSJed Brown ierr = DMForestGetMinimumRefinement(dm,&ctx.minLevel);CHKERRQ(ierr); 925*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityStrategy(dm,&strategy);CHKERRQ(ierr); 926*0a96aa3bSJed Brown ierr = PetscStrncmp(strategy,"any",3,&adaptAny);CHKERRQ(ierr); 927*0a96aa3bSJed Brown ierr = DMForestGetCellChart(adaptFrom,&cStart,&cEnd);CHKERRQ(ierr); 928*0a96aa3bSJed Brown ierr = DMForestGetCellSF(adaptFrom,&cellSF);CHKERRQ(ierr); 929*0a96aa3bSJed Brown ierr = PetscMalloc1(cEnd-cStart,&cellFlags);CHKERRQ(ierr); 930*0a96aa3bSJed Brown for (c = cStart; c < cEnd; c++) {ierr = DMLabelGetValue(adaptLabel,c,&cellFlags[c-cStart]);CHKERRQ(ierr);} 931*0a96aa3bSJed Brown if (cellSF) { 932*0a96aa3bSJed Brown if (adaptAny) { 933*0a96aa3bSJed Brown ierr = PetscSFReduceBegin(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MAX);CHKERRQ(ierr); 934*0a96aa3bSJed Brown ierr = PetscSFReduceEnd(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MAX);CHKERRQ(ierr); 935*0a96aa3bSJed Brown } else { 936*0a96aa3bSJed Brown ierr = PetscSFReduceBegin(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MIN);CHKERRQ(ierr); 937*0a96aa3bSJed Brown ierr = PetscSFReduceEnd(cellSF,MPIU_INT,cellFlags,cellFlags,MPI_MIN);CHKERRQ(ierr); 938*0a96aa3bSJed Brown } 939*0a96aa3bSJed Brown } 940*0a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 941*0a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4est->trees->array)[t]); 942*0a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count, i; 943*0a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 944*0a96aa3bSJed Brown 945*0a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 946*0a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 947*0a96aa3bSJed Brown q->p.user_int = cellFlags[count++]; 948*0a96aa3bSJed Brown } 949*0a96aa3bSJed Brown } 950*0a96aa3bSJed Brown ierr = PetscFree(cellFlags);CHKERRQ(ierr); 951*0a96aa3bSJed Brown 952*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) &ctx; 953*0a96aa3bSJed Brown if (adaptAny) { 954*0a96aa3bSJed Brown PetscStackCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_flag_any,pforest_init_determine)); 955*0a96aa3bSJed Brown } else { 956*0a96aa3bSJed Brown PetscStackCallP4est(p4est_coarsen,(pforest->forest,0,pforest_coarsen_flag_all,pforest_init_determine)); 957*0a96aa3bSJed Brown } 958*0a96aa3bSJed Brown PetscStackCallP4est(p4est_refine,(pforest->forest,0,pforest_refine_flag,NULL)); 959*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 960*0a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 961*0a96aa3bSJed Brown if (computeAdaptSF) { 962*0a96aa3bSJed Brown ierr = DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm),apforest->forest,apforest->cLocalStart,pforest->forest,0,&preCoarseToFine,&coarseToPreFine);CHKERRQ(ierr); 963*0a96aa3bSJed Brown } 964*0a96aa3bSJed Brown } 965*0a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) { 966*0a96aa3bSJed Brown p4est_tree_t *atree = &(((p4est_tree_t*) apforest->forest->trees->array)[t]); 967*0a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) pforest->forest->trees->array)[t]); 968*0a96aa3bSJed Brown PetscInt anumQuads = (PetscInt) atree->quadrants.elem_count, i; 969*0a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 970*0a96aa3bSJed Brown p4est_quadrant_t *aquads = (p4est_quadrant_t *) atree->quadrants.array; 971*0a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *) tree->quadrants.array; 972*0a96aa3bSJed Brown 973*0a96aa3bSJed Brown if (anumQuads != numQuads) { 974*0a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 975*0a96aa3bSJed Brown } else { 976*0a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 977*0a96aa3bSJed Brown p4est_quadrant_t *aq = &aquads[i]; 978*0a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i]; 979*0a96aa3bSJed Brown 980*0a96aa3bSJed Brown if (aq->level != q->level) { 981*0a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 982*0a96aa3bSJed Brown break; 983*0a96aa3bSJed Brown } 984*0a96aa3bSJed Brown } 985*0a96aa3bSJed Brown } 986*0a96aa3bSJed Brown if (ctx.anyChange) { 987*0a96aa3bSJed Brown break; 988*0a96aa3bSJed Brown } 989*0a96aa3bSJed Brown } 990*0a96aa3bSJed Brown } 991*0a96aa3bSJed Brown { 992*0a96aa3bSJed Brown PetscInt numLabels, l; 993*0a96aa3bSJed Brown 994*0a96aa3bSJed Brown ierr = DMGetNumLabels(adaptFrom,&numLabels);CHKERRQ(ierr); 995*0a96aa3bSJed Brown for (l = 0; l < numLabels; l++) { 996*0a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 997*0a96aa3bSJed Brown DMLabel label, labelNew; 998*0a96aa3bSJed Brown PetscInt defVal; 999*0a96aa3bSJed Brown const char *name; 1000*0a96aa3bSJed Brown 1001*0a96aa3bSJed Brown ierr = DMGetLabelName(adaptFrom, l, &name);CHKERRQ(ierr); 1002*0a96aa3bSJed Brown ierr = DMGetLabelByNum(adaptFrom, l, &label);CHKERRQ(ierr); 1003*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"depth",&isDepth);CHKERRQ(ierr); 1004*0a96aa3bSJed Brown if (isDepth) continue; 1005*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"celltype",&isCellType);CHKERRQ(ierr); 1006*0a96aa3bSJed Brown if (isCellType) continue; 1007*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"ghost",&isGhost);CHKERRQ(ierr); 1008*0a96aa3bSJed Brown if (isGhost) continue; 1009*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"vtk",&isVTK);CHKERRQ(ierr); 1010*0a96aa3bSJed Brown if (isVTK) continue; 1011*0a96aa3bSJed Brown ierr = DMCreateLabel(dm,name);CHKERRQ(ierr); 1012*0a96aa3bSJed Brown ierr = DMGetLabel(dm,name,&labelNew);CHKERRQ(ierr); 1013*0a96aa3bSJed Brown ierr = DMLabelGetDefaultValue(label,&defVal);CHKERRQ(ierr); 1014*0a96aa3bSJed Brown ierr = DMLabelSetDefaultValue(labelNew,defVal);CHKERRQ(ierr); 1015*0a96aa3bSJed Brown } 1016*0a96aa3bSJed Brown } 1017*0a96aa3bSJed Brown } else { /* initial */ 1018*0a96aa3bSJed Brown PetscInt initLevel, minLevel; 1019*0a96aa3bSJed Brown 1020*0a96aa3bSJed Brown ierr = DMForestGetInitialRefinement(dm,&initLevel);CHKERRQ(ierr); 1021*0a96aa3bSJed Brown ierr = DMForestGetMinimumRefinement(dm,&minLevel);CHKERRQ(ierr); 1022*0a96aa3bSJed Brown PetscStackCallP4estReturn(pforest->forest,p4est_new_ext,(PetscObjectComm((PetscObject)dm),pforest->topo->conn, 1023*0a96aa3bSJed Brown 0, /* minimum number of quadrants per processor */ 1024*0a96aa3bSJed Brown initLevel, /* level of refinement */ 1025*0a96aa3bSJed Brown 1, /* uniform refinement */ 1026*0a96aa3bSJed Brown 0, /* we don't allocate any per quadrant data */ 1027*0a96aa3bSJed Brown NULL, /* there is no special quadrant initialization */ 1028*0a96aa3bSJed Brown (void*)dm)); /* this dm is the user context */ 1029*0a96aa3bSJed Brown 1030*0a96aa3bSJed Brown if (initLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 1031*0a96aa3bSJed Brown if (dm->setfromoptionscalled) { 1032*0a96aa3bSJed Brown PetscBool flgPattern, flgFractal; 1033*0a96aa3bSJed Brown PetscInt corner = 0; 1034*0a96aa3bSJed Brown PetscInt corners[P4EST_CHILDREN], ncorner = P4EST_CHILDREN; 1035*0a96aa3bSJed Brown PetscReal likelihood = 1./ P4EST_DIM; 1036*0a96aa3bSJed Brown PetscInt pattern; 1037*0a96aa3bSJed Brown const char *prefix; 1038*0a96aa3bSJed Brown 1039*0a96aa3bSJed Brown ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix);CHKERRQ(ierr); 1040*0a96aa3bSJed Brown ierr = PetscOptionsGetEList(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_pattern",DMRefinePatternName,PATTERN_COUNT,&pattern,&flgPattern);CHKERRQ(ierr); 1041*0a96aa3bSJed Brown ierr = PetscOptionsGetInt(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_corner",&corner,NULL);CHKERRQ(ierr); 1042*0a96aa3bSJed Brown ierr = PetscOptionsGetIntArray(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_fractal_corners",corners,&ncorner,&flgFractal);CHKERRQ(ierr); 1043*0a96aa3bSJed Brown ierr = PetscOptionsGetReal(((PetscObject)dm)->options,prefix,"-dm_p4est_refine_hash_likelihood",&likelihood,NULL);CHKERRQ(ierr); 1044*0a96aa3bSJed Brown 1045*0a96aa3bSJed Brown if (flgPattern) { 1046*0a96aa3bSJed Brown DMRefinePatternCtx *ctx; 1047*0a96aa3bSJed Brown PetscInt maxLevel; 1048*0a96aa3bSJed Brown 1049*0a96aa3bSJed Brown ierr = DMForestGetMaximumRefinement(dm,&maxLevel);CHKERRQ(ierr); 1050*0a96aa3bSJed Brown ierr = PetscNewLog(dm,&ctx);CHKERRQ(ierr); 1051*0a96aa3bSJed Brown ctx->maxLevel = PetscMin(maxLevel,P4EST_QMAXLEVEL); 1052*0a96aa3bSJed Brown if (initLevel + ctx->maxLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE; 1053*0a96aa3bSJed Brown switch (pattern) { 1054*0a96aa3bSJed Brown case PATTERN_HASH: 1055*0a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Hash; 1056*0a96aa3bSJed Brown ctx->hashLikelihood = likelihood; 1057*0a96aa3bSJed Brown break; 1058*0a96aa3bSJed Brown case PATTERN_CORNER: 1059*0a96aa3bSJed Brown ctx->corner = corner; 1060*0a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Corner; 1061*0a96aa3bSJed Brown break; 1062*0a96aa3bSJed Brown case PATTERN_CENTER: 1063*0a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Center; 1064*0a96aa3bSJed Brown break; 1065*0a96aa3bSJed Brown case PATTERN_FRACTAL: 1066*0a96aa3bSJed Brown if (flgFractal) { 1067*0a96aa3bSJed Brown PetscInt i; 1068*0a96aa3bSJed Brown 1069*0a96aa3bSJed Brown for (i = 0; i < ncorner; i++) ctx->fractal[corners[i]] = PETSC_TRUE; 1070*0a96aa3bSJed Brown } else { 1071*0a96aa3bSJed Brown #if !defined(P4_TO_P8) 1072*0a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[1] = ctx->fractal[2] = PETSC_TRUE; 1073*0a96aa3bSJed Brown #else 1074*0a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[3] = ctx->fractal[5] = ctx->fractal[6] = PETSC_TRUE; 1075*0a96aa3bSJed Brown #endif 1076*0a96aa3bSJed Brown } 1077*0a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Fractal; 1078*0a96aa3bSJed Brown break; 1079*0a96aa3bSJed Brown default: 1080*0a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Not a valid refinement pattern"); 1081*0a96aa3bSJed Brown } 1082*0a96aa3bSJed Brown 1083*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) ctx; 1084*0a96aa3bSJed Brown PetscStackCallP4est(p4est_refine,(pforest->forest,1,ctx->refine_fn,NULL)); 1085*0a96aa3bSJed Brown PetscStackCallP4est(p4est_balance,(pforest->forest,P4EST_CONNECT_FULL,NULL)); 1086*0a96aa3bSJed Brown ierr = PetscFree(ctx);CHKERRQ(ierr); 1087*0a96aa3bSJed Brown pforest->forest->user_pointer = (void*) dm; 1088*0a96aa3bSJed Brown } 1089*0a96aa3bSJed Brown } 1090*0a96aa3bSJed Brown } 1091*0a96aa3bSJed Brown if (pforest->coarsen_hierarchy) { 1092*0a96aa3bSJed Brown PetscInt initLevel, currLevel, minLevel; 1093*0a96aa3bSJed Brown 1094*0a96aa3bSJed Brown ierr = DMPforestGetRefinementLevel(dm,&currLevel);CHKERRQ(ierr); 1095*0a96aa3bSJed Brown ierr = DMForestGetInitialRefinement(dm,&initLevel);CHKERRQ(ierr); 1096*0a96aa3bSJed Brown ierr = DMForestGetMinimumRefinement(dm,&minLevel);CHKERRQ(ierr); 1097*0a96aa3bSJed Brown if (currLevel > minLevel) { 1098*0a96aa3bSJed Brown DM_Forest_pforest *coarse_pforest; 1099*0a96aa3bSJed Brown DMLabel coarsen; 1100*0a96aa3bSJed Brown DM coarseDM; 1101*0a96aa3bSJed Brown 1102*0a96aa3bSJed Brown ierr = DMForestTemplate(dm,MPI_COMM_NULL,&coarseDM);CHKERRQ(ierr); 1103*0a96aa3bSJed Brown ierr = DMForestSetAdaptivityPurpose(coarseDM,DM_ADAPT_COARSEN);CHKERRQ(ierr); 1104*0a96aa3bSJed Brown ierr = DMLabelCreate(PETSC_COMM_SELF, "coarsen",&coarsen);CHKERRQ(ierr); 1105*0a96aa3bSJed Brown ierr = DMLabelSetDefaultValue(coarsen,DM_ADAPT_COARSEN);CHKERRQ(ierr); 1106*0a96aa3bSJed Brown ierr = DMForestSetAdaptivityLabel(coarseDM,coarsen);CHKERRQ(ierr); 1107*0a96aa3bSJed Brown ierr = DMLabelDestroy(&coarsen);CHKERRQ(ierr); 1108*0a96aa3bSJed Brown ierr = DMSetCoarseDM(dm,coarseDM);CHKERRQ(ierr); 1109*0a96aa3bSJed Brown ierr = PetscObjectDereference((PetscObject)coarseDM);CHKERRQ(ierr); 1110*0a96aa3bSJed Brown initLevel = currLevel == initLevel ? initLevel - 1 : initLevel; 1111*0a96aa3bSJed Brown ierr = DMForestSetInitialRefinement(coarseDM,initLevel);CHKERRQ(ierr); 1112*0a96aa3bSJed Brown ierr = DMForestSetMinimumRefinement(coarseDM,minLevel);CHKERRQ(ierr); 1113*0a96aa3bSJed Brown coarse_pforest = (DM_Forest_pforest*) ((DM_Forest*) coarseDM->data)->data; 1114*0a96aa3bSJed Brown coarse_pforest->coarsen_hierarchy = PETSC_TRUE; 1115*0a96aa3bSJed Brown } 1116*0a96aa3bSJed Brown } 1117*0a96aa3bSJed Brown 1118*0a96aa3bSJed Brown { /* repartitioning and overlap */ 1119*0a96aa3bSJed Brown PetscMPIInt size, rank; 1120*0a96aa3bSJed Brown 1121*0a96aa3bSJed Brown ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);CHKERRMPI(ierr); 1122*0a96aa3bSJed Brown ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr); 1123*0a96aa3bSJed Brown if ((size > 1) && (pforest->partition_for_coarsening || forest->cellWeights || forest->weightCapacity != 1. || forest->weightsFactor != 1.)) { 1124*0a96aa3bSJed Brown PetscBool copyForest = PETSC_FALSE; 1125*0a96aa3bSJed Brown p4est_t *forest_copy = NULL; 1126*0a96aa3bSJed Brown p4est_gloidx_t shipped = 0; 1127*0a96aa3bSJed Brown 1128*0a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) copyForest = PETSC_TRUE; 1129*0a96aa3bSJed Brown if (copyForest) PetscStackCallP4estReturn(forest_copy,p4est_copy,(pforest->forest,0)); 1130*0a96aa3bSJed Brown 1131*0a96aa3bSJed Brown if (!forest->cellWeights && forest->weightCapacity == 1. && forest->weightsFactor == 1.) { 1132*0a96aa3bSJed Brown PetscStackCallP4estReturn(shipped,p4est_partition_ext,(pforest->forest,(int)pforest->partition_for_coarsening,NULL)); 1133*0a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Non-uniform partition cases not implemented yet"); 1134*0a96aa3bSJed Brown if (shipped) ctx.anyChange = PETSC_TRUE; 1135*0a96aa3bSJed Brown if (forest_copy) { 1136*0a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 1137*0a96aa3bSJed Brown PetscSF repartSF; /* repartSF has roots in the old partition */ 1138*0a96aa3bSJed Brown PetscInt pStart = -1, pEnd = -1, p; 1139*0a96aa3bSJed Brown PetscInt numRoots, numLeaves; 1140*0a96aa3bSJed Brown PetscSFNode *repartRoots; 1141*0a96aa3bSJed Brown p4est_gloidx_t postStart = pforest->forest->global_first_quadrant[rank]; 1142*0a96aa3bSJed Brown p4est_gloidx_t postEnd = pforest->forest->global_first_quadrant[rank+1]; 1143*0a96aa3bSJed Brown p4est_gloidx_t partOffset = postStart; 1144*0a96aa3bSJed Brown 1145*0a96aa3bSJed Brown numRoots = (PetscInt) (forest_copy->global_first_quadrant[rank + 1] - forest_copy->global_first_quadrant[rank]); 1146*0a96aa3bSJed Brown numLeaves = (PetscInt) (postEnd - postStart); 1147*0a96aa3bSJed Brown ierr = DMPforestComputeOverlappingRanks(size,rank,pforest->forest,forest_copy,&pStart,&pEnd);CHKERRQ(ierr); 1148*0a96aa3bSJed Brown ierr = PetscMalloc1((PetscInt) pforest->forest->local_num_quadrants,&repartRoots);CHKERRQ(ierr); 1149*0a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 1150*0a96aa3bSJed Brown p4est_gloidx_t preStart = forest_copy->global_first_quadrant[p]; 1151*0a96aa3bSJed Brown p4est_gloidx_t preEnd = forest_copy->global_first_quadrant[p+1]; 1152*0a96aa3bSJed Brown PetscInt q; 1153*0a96aa3bSJed Brown 1154*0a96aa3bSJed Brown if (preEnd == preStart) continue; 1155*0a96aa3bSJed Brown if (preStart > postStart) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Bad partition overlap computation"); 1156*0a96aa3bSJed Brown preEnd = preEnd > postEnd ? postEnd : preEnd; 1157*0a96aa3bSJed Brown for (q = partOffset; q < preEnd; q++) { 1158*0a96aa3bSJed Brown repartRoots[q - postStart].rank = p; 1159*0a96aa3bSJed Brown repartRoots[q - postStart].index = partOffset - preStart; 1160*0a96aa3bSJed Brown } 1161*0a96aa3bSJed Brown partOffset = preEnd; 1162*0a96aa3bSJed Brown } 1163*0a96aa3bSJed Brown ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&repartSF);CHKERRQ(ierr); 1164*0a96aa3bSJed Brown ierr = PetscSFSetGraph(repartSF,numRoots,numLeaves,NULL,PETSC_OWN_POINTER,repartRoots,PETSC_OWN_POINTER);CHKERRQ(ierr); 1165*0a96aa3bSJed Brown ierr = PetscSFSetUp(repartSF);CHKERRQ(ierr); 1166*0a96aa3bSJed Brown if (preCoarseToFine) { 1167*0a96aa3bSJed Brown PetscSF repartSFembed, preCoarseToFineNew; 1168*0a96aa3bSJed Brown PetscInt nleaves; 1169*0a96aa3bSJed Brown const PetscInt *leaves; 1170*0a96aa3bSJed Brown 1171*0a96aa3bSJed Brown ierr = PetscSFSetUp(preCoarseToFine);CHKERRQ(ierr); 1172*0a96aa3bSJed Brown ierr = PetscSFGetGraph(preCoarseToFine,NULL,&nleaves,&leaves,NULL);CHKERRQ(ierr); 1173*0a96aa3bSJed Brown if (leaves) { 1174*0a96aa3bSJed Brown ierr = PetscSFCreateEmbeddedRootSF(repartSF,nleaves,leaves,&repartSFembed);CHKERRQ(ierr); 1175*0a96aa3bSJed Brown } else { 1176*0a96aa3bSJed Brown repartSFembed = repartSF; 1177*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)repartSFembed);CHKERRQ(ierr); 1178*0a96aa3bSJed Brown } 1179*0a96aa3bSJed Brown ierr = PetscSFCompose(preCoarseToFine,repartSFembed,&preCoarseToFineNew);CHKERRQ(ierr); 1180*0a96aa3bSJed Brown ierr = PetscSFDestroy(&preCoarseToFine);CHKERRQ(ierr); 1181*0a96aa3bSJed Brown ierr = PetscSFDestroy(&repartSFembed);CHKERRQ(ierr); 1182*0a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 1183*0a96aa3bSJed Brown } 1184*0a96aa3bSJed Brown if (coarseToPreFine) { 1185*0a96aa3bSJed Brown PetscSF repartSFinv, coarseToPreFineNew; 1186*0a96aa3bSJed Brown 1187*0a96aa3bSJed Brown ierr = PetscSFCreateInverseSF(repartSF,&repartSFinv);CHKERRQ(ierr); 1188*0a96aa3bSJed Brown ierr = PetscSFCompose(repartSFinv,coarseToPreFine,&coarseToPreFineNew);CHKERRQ(ierr); 1189*0a96aa3bSJed Brown ierr = PetscSFDestroy(&coarseToPreFine);CHKERRQ(ierr); 1190*0a96aa3bSJed Brown ierr = PetscSFDestroy(&repartSFinv);CHKERRQ(ierr); 1191*0a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 1192*0a96aa3bSJed Brown } 1193*0a96aa3bSJed Brown ierr = PetscSFDestroy(&repartSF);CHKERRQ(ierr); 1194*0a96aa3bSJed Brown } 1195*0a96aa3bSJed Brown PetscStackCallP4est(p4est_destroy,(forest_copy)); 1196*0a96aa3bSJed Brown } 1197*0a96aa3bSJed Brown } 1198*0a96aa3bSJed Brown if (size > 1) { 1199*0a96aa3bSJed Brown PetscInt overlap; 1200*0a96aa3bSJed Brown 1201*0a96aa3bSJed Brown ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr); 1202*0a96aa3bSJed Brown 1203*0a96aa3bSJed Brown if (adaptFrom) { 1204*0a96aa3bSJed Brown PetscInt aoverlap; 1205*0a96aa3bSJed Brown 1206*0a96aa3bSJed Brown ierr = DMForestGetPartitionOverlap(adaptFrom,&aoverlap);CHKERRQ(ierr); 1207*0a96aa3bSJed Brown if (aoverlap != overlap) { 1208*0a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE; 1209*0a96aa3bSJed Brown } 1210*0a96aa3bSJed Brown } 1211*0a96aa3bSJed Brown 1212*0a96aa3bSJed Brown if (overlap > 0) { 1213*0a96aa3bSJed Brown PetscInt i, cLocalStart; 1214*0a96aa3bSJed Brown PetscInt cEnd; 1215*0a96aa3bSJed Brown PetscSF preCellSF = NULL, cellSF = NULL; 1216*0a96aa3bSJed Brown 1217*0a96aa3bSJed Brown PetscStackCallP4estReturn(pforest->ghost,p4est_ghost_new,(pforest->forest,P4EST_CONNECT_FULL)); 1218*0a96aa3bSJed Brown PetscStackCallP4estReturn(pforest->lnodes,p4est_lnodes_new,(pforest->forest,pforest->ghost,-P4EST_DIM)); 1219*0a96aa3bSJed Brown PetscStackCallP4est(p4est_ghost_support_lnodes,(pforest->forest,pforest->lnodes,pforest->ghost)); 1220*0a96aa3bSJed Brown for (i = 1; i < overlap; i++) PetscStackCallP4est(p4est_ghost_expand_by_lnodes,(pforest->forest,pforest->lnodes,pforest->ghost)); 1221*0a96aa3bSJed Brown 1222*0a96aa3bSJed Brown cLocalStart = pforest->cLocalStart = pforest->ghost->proc_offsets[rank]; 1223*0a96aa3bSJed Brown cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[size]; 1224*0a96aa3bSJed Brown 1225*0a96aa3bSJed Brown /* shift sfs by cLocalStart, expand by cell SFs */ 1226*0a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) { 1227*0a96aa3bSJed Brown if (adaptFrom) {ierr = DMForestGetCellSF(adaptFrom,&preCellSF);CHKERRQ(ierr);} 1228*0a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 1229*0a96aa3bSJed Brown ierr = DMForestGetCellSF(dm,&cellSF);CHKERRQ(ierr); 1230*0a96aa3bSJed Brown } 1231*0a96aa3bSJed Brown if (preCoarseToFine) { 1232*0a96aa3bSJed Brown PetscSF preCoarseToFineNew; 1233*0a96aa3bSJed Brown PetscInt nleaves, nroots, *leavesNew, i, nleavesNew; 1234*0a96aa3bSJed Brown const PetscInt *leaves; 1235*0a96aa3bSJed Brown const PetscSFNode *remotes; 1236*0a96aa3bSJed Brown PetscSFNode *remotesAll; 1237*0a96aa3bSJed Brown 1238*0a96aa3bSJed Brown ierr = PetscSFSetUp(preCoarseToFine);CHKERRQ(ierr); 1239*0a96aa3bSJed Brown ierr = PetscSFGetGraph(preCoarseToFine,&nroots,&nleaves,&leaves,&remotes);CHKERRQ(ierr); 1240*0a96aa3bSJed Brown ierr = PetscMalloc1(cEnd,&remotesAll);CHKERRQ(ierr); 1241*0a96aa3bSJed Brown for (i = 0; i < cEnd; i++) { 1242*0a96aa3bSJed Brown remotesAll[i].rank = -1; 1243*0a96aa3bSJed Brown remotesAll[i].index = -1; 1244*0a96aa3bSJed Brown } 1245*0a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesAll[(leaves ? leaves[i] : i) + cLocalStart] = remotes[i]; 1246*0a96aa3bSJed Brown ierr = PetscSFSetUp(cellSF);CHKERRQ(ierr); 1247*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(cellSF,MPIU_2INT,remotesAll,remotesAll,MPI_REPLACE);CHKERRQ(ierr); 1248*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(cellSF,MPIU_2INT,remotesAll,remotesAll,MPI_REPLACE);CHKERRQ(ierr); 1249*0a96aa3bSJed Brown nleavesNew = 0; 1250*0a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 1251*0a96aa3bSJed Brown if (remotesAll[i].rank >= 0) nleavesNew++; 1252*0a96aa3bSJed Brown } 1253*0a96aa3bSJed Brown ierr = PetscMalloc1(nleavesNew,&leavesNew);CHKERRQ(ierr); 1254*0a96aa3bSJed Brown nleavesNew = 0; 1255*0a96aa3bSJed Brown for (i = 0; i < nleaves; i++) { 1256*0a96aa3bSJed Brown if (remotesAll[i].rank >= 0) { 1257*0a96aa3bSJed Brown leavesNew[nleavesNew] = i; 1258*0a96aa3bSJed Brown if (i > nleavesNew) remotesAll[nleavesNew] = remotesAll[i]; 1259*0a96aa3bSJed Brown nleavesNew++; 1260*0a96aa3bSJed Brown } 1261*0a96aa3bSJed Brown } 1262*0a96aa3bSJed Brown ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&preCoarseToFineNew);CHKERRQ(ierr); 1263*0a96aa3bSJed Brown if (nleavesNew < cEnd) { 1264*0a96aa3bSJed Brown ierr = PetscSFSetGraph(preCoarseToFineNew,nroots,nleavesNew,leavesNew,PETSC_OWN_POINTER,remotesAll,PETSC_COPY_VALUES);CHKERRQ(ierr); 1265*0a96aa3bSJed Brown } else { /* all cells are leaves */ 1266*0a96aa3bSJed Brown ierr = PetscFree(leavesNew);CHKERRQ(ierr); 1267*0a96aa3bSJed Brown ierr = PetscSFSetGraph(preCoarseToFineNew,nroots,nleavesNew,NULL,PETSC_OWN_POINTER,remotesAll,PETSC_COPY_VALUES);CHKERRQ(ierr); 1268*0a96aa3bSJed Brown } 1269*0a96aa3bSJed Brown ierr = PetscFree(remotesAll);CHKERRQ(ierr); 1270*0a96aa3bSJed Brown ierr = PetscSFDestroy(&preCoarseToFine);CHKERRQ(ierr); 1271*0a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 1272*0a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew; 1273*0a96aa3bSJed Brown } 1274*0a96aa3bSJed Brown if (coarseToPreFine) { 1275*0a96aa3bSJed Brown PetscSF coarseToPreFineNew; 1276*0a96aa3bSJed Brown PetscInt nleaves, nroots, i, nleavesCellSF, nleavesExpanded, *leavesNew; 1277*0a96aa3bSJed Brown const PetscInt *leaves; 1278*0a96aa3bSJed Brown const PetscSFNode *remotes; 1279*0a96aa3bSJed Brown PetscSFNode *remotesNew, *remotesNewRoot, *remotesExpanded; 1280*0a96aa3bSJed Brown 1281*0a96aa3bSJed Brown ierr = PetscSFSetUp(coarseToPreFine);CHKERRQ(ierr); 1282*0a96aa3bSJed Brown ierr = PetscSFGetGraph(coarseToPreFine,&nroots,&nleaves,&leaves,&remotes);CHKERRQ(ierr); 1283*0a96aa3bSJed Brown ierr = PetscSFGetGraph(preCellSF,NULL,&nleavesCellSF,NULL,NULL);CHKERRQ(ierr); 1284*0a96aa3bSJed Brown ierr = PetscMalloc1(nroots,&remotesNewRoot);CHKERRQ(ierr); 1285*0a96aa3bSJed Brown ierr = PetscMalloc1(nleaves,&remotesNew);CHKERRQ(ierr); 1286*0a96aa3bSJed Brown for (i = 0; i < nroots; i++) { 1287*0a96aa3bSJed Brown remotesNewRoot[i].rank = rank; 1288*0a96aa3bSJed Brown remotesNewRoot[i].index = i + cLocalStart; 1289*0a96aa3bSJed Brown } 1290*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(coarseToPreFine,MPIU_2INT,remotesNewRoot,remotesNew,MPI_REPLACE);CHKERRQ(ierr); 1291*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(coarseToPreFine,MPIU_2INT,remotesNewRoot,remotesNew,MPI_REPLACE);CHKERRQ(ierr); 1292*0a96aa3bSJed Brown ierr = PetscFree(remotesNewRoot);CHKERRQ(ierr); 1293*0a96aa3bSJed Brown ierr = PetscMalloc1(nleavesCellSF,&remotesExpanded);CHKERRQ(ierr); 1294*0a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 1295*0a96aa3bSJed Brown remotesExpanded[i].rank = -1; 1296*0a96aa3bSJed Brown remotesExpanded[i].index = -1; 1297*0a96aa3bSJed Brown } 1298*0a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesExpanded[leaves ? leaves[i] : i] = remotesNew[i]; 1299*0a96aa3bSJed Brown ierr = PetscFree(remotesNew);CHKERRQ(ierr); 1300*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(preCellSF,MPIU_2INT,remotesExpanded,remotesExpanded,MPI_REPLACE);CHKERRQ(ierr); 1301*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(preCellSF,MPIU_2INT,remotesExpanded,remotesExpanded,MPI_REPLACE);CHKERRQ(ierr); 1302*0a96aa3bSJed Brown 1303*0a96aa3bSJed Brown nleavesExpanded = 0; 1304*0a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 1305*0a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) nleavesExpanded++; 1306*0a96aa3bSJed Brown } 1307*0a96aa3bSJed Brown ierr = PetscMalloc1(nleavesExpanded,&leavesNew);CHKERRQ(ierr); 1308*0a96aa3bSJed Brown nleavesExpanded = 0; 1309*0a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) { 1310*0a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) { 1311*0a96aa3bSJed Brown leavesNew[nleavesExpanded] = i; 1312*0a96aa3bSJed Brown if (i > nleavesExpanded) remotesExpanded[nleavesExpanded] = remotes[i]; 1313*0a96aa3bSJed Brown nleavesExpanded++; 1314*0a96aa3bSJed Brown } 1315*0a96aa3bSJed Brown } 1316*0a96aa3bSJed Brown ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&coarseToPreFineNew);CHKERRQ(ierr); 1317*0a96aa3bSJed Brown if (nleavesExpanded < nleavesCellSF) { 1318*0a96aa3bSJed Brown ierr = PetscSFSetGraph(coarseToPreFineNew,cEnd,nleavesExpanded,leavesNew,PETSC_OWN_POINTER,remotesExpanded,PETSC_COPY_VALUES);CHKERRQ(ierr); 1319*0a96aa3bSJed Brown } else { 1320*0a96aa3bSJed Brown ierr = PetscFree(leavesNew);CHKERRQ(ierr); 1321*0a96aa3bSJed Brown ierr = PetscSFSetGraph(coarseToPreFineNew,cEnd,nleavesExpanded,NULL,PETSC_OWN_POINTER,remotesExpanded,PETSC_COPY_VALUES);CHKERRQ(ierr); 1322*0a96aa3bSJed Brown } 1323*0a96aa3bSJed Brown ierr = PetscFree(remotesExpanded);CHKERRQ(ierr); 1324*0a96aa3bSJed Brown ierr = PetscSFDestroy(&coarseToPreFine);CHKERRQ(ierr); 1325*0a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew; 1326*0a96aa3bSJed Brown } 1327*0a96aa3bSJed Brown } 1328*0a96aa3bSJed Brown } 1329*0a96aa3bSJed Brown } 1330*0a96aa3bSJed Brown forest->preCoarseToFine = preCoarseToFine; 1331*0a96aa3bSJed Brown forest->coarseToPreFine = coarseToPreFine; 1332*0a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE; 1333*0a96aa3bSJed Brown ierr = MPI_Allreduce(&ctx.anyChange,&(pforest->adaptivitySuccess),1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1334*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,NULL);CHKERRQ(ierr); 1335*0a96aa3bSJed Brown PetscFunctionReturn(0); 1336*0a96aa3bSJed Brown } 1337*0a96aa3bSJed Brown 1338*0a96aa3bSJed Brown #define DMForestGetAdaptivitySuccess_pforest _append_pforest(DMForestGetAdaptivitySuccess) 1339*0a96aa3bSJed Brown static PetscErrorCode DMForestGetAdaptivitySuccess_pforest(DM dm, PetscBool *success) 1340*0a96aa3bSJed Brown { 1341*0a96aa3bSJed Brown DM_Forest *forest; 1342*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 1343*0a96aa3bSJed Brown 1344*0a96aa3bSJed Brown PetscFunctionBegin; 1345*0a96aa3bSJed Brown forest = (DM_Forest *) dm->data; 1346*0a96aa3bSJed Brown pforest = (DM_Forest_pforest *) forest->data; 1347*0a96aa3bSJed Brown *success = pforest->adaptivitySuccess; 1348*0a96aa3bSJed Brown PetscFunctionReturn(0); 1349*0a96aa3bSJed Brown } 1350*0a96aa3bSJed Brown 1351*0a96aa3bSJed Brown #define DMView_ASCII_pforest _append_pforest(DMView_ASCII) 1352*0a96aa3bSJed Brown static PetscErrorCode DMView_ASCII_pforest(PetscObject odm, PetscViewer viewer) 1353*0a96aa3bSJed Brown { 1354*0a96aa3bSJed Brown DM dm = (DM) odm; 1355*0a96aa3bSJed Brown PetscErrorCode ierr; 1356*0a96aa3bSJed Brown 1357*0a96aa3bSJed Brown PetscFunctionBegin; 1358*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1359*0a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1360*0a96aa3bSJed Brown ierr = DMSetUp(dm);CHKERRQ(ierr); 1361*0a96aa3bSJed Brown switch (viewer->format) { 1362*0a96aa3bSJed Brown case PETSC_VIEWER_DEFAULT: 1363*0a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO: 1364*0a96aa3bSJed Brown { 1365*0a96aa3bSJed Brown PetscInt dim; 1366*0a96aa3bSJed Brown const char *name; 1367*0a96aa3bSJed Brown 1368*0a96aa3bSJed Brown ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1369*0a96aa3bSJed Brown ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1370*0a96aa3bSJed Brown if (name) {ierr = PetscViewerASCIIPrintf(viewer, "Forest %s in %D dimensions:\n", name, dim);CHKERRQ(ierr);} 1371*0a96aa3bSJed Brown else {ierr = PetscViewerASCIIPrintf(viewer, "Forest in %D dimensions:\n", dim);CHKERRQ(ierr);} 1372*0a96aa3bSJed Brown } 1373*0a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO_DETAIL: 1374*0a96aa3bSJed Brown case PETSC_VIEWER_LOAD_BALANCE: 1375*0a96aa3bSJed Brown { 1376*0a96aa3bSJed Brown DM plex; 1377*0a96aa3bSJed Brown 1378*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm, &plex);CHKERRQ(ierr); 1379*0a96aa3bSJed Brown ierr = DMView(plex, viewer);CHKERRQ(ierr); 1380*0a96aa3bSJed Brown } 1381*0a96aa3bSJed Brown break; 1382*0a96aa3bSJed Brown default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 1383*0a96aa3bSJed Brown } 1384*0a96aa3bSJed Brown PetscFunctionReturn(0); 1385*0a96aa3bSJed Brown } 1386*0a96aa3bSJed Brown 1387*0a96aa3bSJed Brown #define DMView_VTK_pforest _append_pforest(DMView_VTK) 1388*0a96aa3bSJed Brown static PetscErrorCode DMView_VTK_pforest(PetscObject odm, PetscViewer viewer) 1389*0a96aa3bSJed Brown { 1390*0a96aa3bSJed Brown DM dm = (DM) odm; 1391*0a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 1392*0a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 1393*0a96aa3bSJed Brown PetscBool isvtk; 1394*0a96aa3bSJed Brown PetscReal vtkScale = 1. - PETSC_MACHINE_EPSILON; 1395*0a96aa3bSJed Brown PetscViewer_VTK *vtk = (PetscViewer_VTK*)viewer->data; 1396*0a96aa3bSJed Brown const char *name; 1397*0a96aa3bSJed Brown char *filenameStrip = NULL; 1398*0a96aa3bSJed Brown PetscBool hasExt; 1399*0a96aa3bSJed Brown size_t len; 1400*0a96aa3bSJed Brown p4est_geometry_t *geom; 1401*0a96aa3bSJed Brown PetscErrorCode ierr; 1402*0a96aa3bSJed Brown 1403*0a96aa3bSJed Brown PetscFunctionBegin; 1404*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1405*0a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1406*0a96aa3bSJed Brown ierr = DMSetUp(dm);CHKERRQ(ierr); 1407*0a96aa3bSJed Brown geom = pforest->topo->geom; 1408*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1409*0a96aa3bSJed Brown if (!isvtk) SETERRQ1(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name); 1410*0a96aa3bSJed Brown switch (viewer->format) { 1411*0a96aa3bSJed Brown case PETSC_VIEWER_VTK_VTU: 1412*0a96aa3bSJed Brown if (!pforest->forest) SETERRQ (PetscObjectComm(odm),PETSC_ERR_ARG_WRONG,"DM has not been setup with a valid forest"); 1413*0a96aa3bSJed Brown name = vtk->filename; 1414*0a96aa3bSJed Brown ierr = PetscStrlen(name,&len);CHKERRQ(ierr); 1415*0a96aa3bSJed Brown ierr = PetscStrcasecmp(name+len-4,".vtu",&hasExt);CHKERRQ(ierr); 1416*0a96aa3bSJed Brown if (hasExt) { 1417*0a96aa3bSJed Brown ierr = PetscStrallocpy(name,&filenameStrip);CHKERRQ(ierr); 1418*0a96aa3bSJed Brown filenameStrip[len-4]='\0'; 1419*0a96aa3bSJed Brown name = filenameStrip; 1420*0a96aa3bSJed Brown } 1421*0a96aa3bSJed Brown if (!pforest->topo->geom) PetscStackCallP4estReturn(geom,p4est_geometry_new_connectivity,(pforest->topo->conn)); 1422*0a96aa3bSJed Brown { 1423*0a96aa3bSJed Brown p4est_vtk_context_t *pvtk; 1424*0a96aa3bSJed Brown int footerr; 1425*0a96aa3bSJed Brown 1426*0a96aa3bSJed Brown PetscStackCallP4estReturn(pvtk,p4est_vtk_context_new,(pforest->forest,name)); 1427*0a96aa3bSJed Brown PetscStackCallP4est(p4est_vtk_context_set_geom,(pvtk,geom)); 1428*0a96aa3bSJed Brown PetscStackCallP4est(p4est_vtk_context_set_scale,(pvtk,(double)vtkScale)); 1429*0a96aa3bSJed Brown PetscStackCallP4estReturn(pvtk,p4est_vtk_write_header,(pvtk)); 1430*0a96aa3bSJed Brown if (!pvtk) SETERRQ(PetscObjectComm((PetscObject)odm),PETSC_ERR_LIB,P4EST_STRING "_vtk_write_header() failed"); 1431*0a96aa3bSJed Brown PetscStackCallP4estReturn(pvtk,p4est_vtk_write_cell_dataf,(pvtk, 1432*0a96aa3bSJed Brown 1, /* write tree */ 1433*0a96aa3bSJed Brown 1, /* write level */ 1434*0a96aa3bSJed Brown 1, /* write rank */ 1435*0a96aa3bSJed Brown 0, /* do not wrap rank */ 1436*0a96aa3bSJed Brown 0, /* no scalar fields */ 1437*0a96aa3bSJed Brown 0, /* no vector fields */ 1438*0a96aa3bSJed Brown pvtk)); 1439*0a96aa3bSJed Brown if (!pvtk) SETERRQ(PetscObjectComm((PetscObject)odm),PETSC_ERR_LIB,P4EST_STRING "_vtk_write_cell_dataf() failed"); 1440*0a96aa3bSJed Brown PetscStackCallP4estReturn(footerr,p4est_vtk_write_footer,(pvtk)); 1441*0a96aa3bSJed Brown if (footerr) SETERRQ(PetscObjectComm((PetscObject)odm),PETSC_ERR_LIB,P4EST_STRING "_vtk_write_footer() failed"); 1442*0a96aa3bSJed Brown } 1443*0a96aa3bSJed Brown if (!pforest->topo->geom) PetscStackCallP4est(p4est_geometry_destroy,(geom)); 1444*0a96aa3bSJed Brown ierr = PetscFree(filenameStrip);CHKERRQ(ierr); 1445*0a96aa3bSJed Brown break; 1446*0a96aa3bSJed Brown default: SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 1447*0a96aa3bSJed Brown } 1448*0a96aa3bSJed Brown PetscFunctionReturn(0); 1449*0a96aa3bSJed Brown } 1450*0a96aa3bSJed Brown 1451*0a96aa3bSJed Brown #define DMView_HDF5_pforest _append_pforest(DMView_HDF5) 1452*0a96aa3bSJed Brown static PetscErrorCode DMView_HDF5_pforest(DM dm, PetscViewer viewer) 1453*0a96aa3bSJed Brown { 1454*0a96aa3bSJed Brown DM plex; 1455*0a96aa3bSJed Brown PetscErrorCode ierr; 1456*0a96aa3bSJed Brown 1457*0a96aa3bSJed Brown PetscFunctionBegin; 1458*0a96aa3bSJed Brown ierr = DMSetUp(dm);CHKERRQ(ierr); 1459*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm, &plex);CHKERRQ(ierr); 1460*0a96aa3bSJed Brown ierr = DMView(plex, viewer);CHKERRQ(ierr); 1461*0a96aa3bSJed Brown PetscFunctionReturn(0); 1462*0a96aa3bSJed Brown } 1463*0a96aa3bSJed Brown 1464*0a96aa3bSJed Brown #define DMView_GLVis_pforest _append_pforest(DMView_GLVis) 1465*0a96aa3bSJed Brown static PetscErrorCode DMView_GLVis_pforest(DM dm, PetscViewer viewer) 1466*0a96aa3bSJed Brown { 1467*0a96aa3bSJed Brown DM plex; 1468*0a96aa3bSJed Brown PetscErrorCode ierr; 1469*0a96aa3bSJed Brown 1470*0a96aa3bSJed Brown PetscFunctionBegin; 1471*0a96aa3bSJed Brown ierr = DMSetUp(dm);CHKERRQ(ierr); 1472*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm, &plex);CHKERRQ(ierr); 1473*0a96aa3bSJed Brown ierr = DMView(plex, viewer);CHKERRQ(ierr); 1474*0a96aa3bSJed Brown PetscFunctionReturn(0); 1475*0a96aa3bSJed Brown } 1476*0a96aa3bSJed Brown 1477*0a96aa3bSJed Brown #define DMView_pforest _append_pforest(DMView) 1478*0a96aa3bSJed Brown static PetscErrorCode DMView_pforest(DM dm, PetscViewer viewer) 1479*0a96aa3bSJed Brown { 1480*0a96aa3bSJed Brown PetscBool isascii, isvtk, ishdf5, isglvis; 1481*0a96aa3bSJed Brown PetscErrorCode ierr; 1482*0a96aa3bSJed Brown 1483*0a96aa3bSJed Brown PetscFunctionBegin; 1484*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1485*0a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1486*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &isascii);CHKERRQ(ierr); 1487*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1488*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1489*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 1490*0a96aa3bSJed Brown if (isascii) { 1491*0a96aa3bSJed Brown ierr = DMView_ASCII_pforest((PetscObject) dm,viewer);CHKERRQ(ierr); 1492*0a96aa3bSJed Brown } else if (isvtk) { 1493*0a96aa3bSJed Brown ierr = DMView_VTK_pforest((PetscObject) dm,viewer);CHKERRQ(ierr); 1494*0a96aa3bSJed Brown } else if (ishdf5) { 1495*0a96aa3bSJed Brown ierr = DMView_HDF5_pforest(dm, viewer);CHKERRQ(ierr); 1496*0a96aa3bSJed Brown } else if (isglvis) { 1497*0a96aa3bSJed Brown ierr = DMView_GLVis_pforest(dm, viewer);CHKERRQ(ierr); 1498*0a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject) dm),PETSC_ERR_SUP,"Viewer not supported (not VTK, HDF5, or GLVis)"); 1499*0a96aa3bSJed Brown PetscFunctionReturn(0); 1500*0a96aa3bSJed Brown } 1501*0a96aa3bSJed Brown 1502*0a96aa3bSJed Brown static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *conn, PetscInt **tree_face_to_uniq) 1503*0a96aa3bSJed Brown { 1504*0a96aa3bSJed Brown PetscInt *ttf, f, t, g, count; 1505*0a96aa3bSJed Brown PetscInt numFacets; 1506*0a96aa3bSJed Brown PetscErrorCode ierr; 1507*0a96aa3bSJed Brown 1508*0a96aa3bSJed Brown PetscFunctionBegin; 1509*0a96aa3bSJed Brown numFacets = conn->num_trees * P4EST_FACES; 1510*0a96aa3bSJed Brown ierr = PetscMalloc1(numFacets,&ttf);CHKERRQ(ierr); 1511*0a96aa3bSJed Brown for (f = 0; f < numFacets; f++) ttf[f] = -1; 1512*0a96aa3bSJed Brown for (g = 0, count = 0, t = 0; t < conn->num_trees; t++) { 1513*0a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++, g++) { 1514*0a96aa3bSJed Brown if (ttf[g] == -1) { 1515*0a96aa3bSJed Brown PetscInt ng; 1516*0a96aa3bSJed Brown 1517*0a96aa3bSJed Brown ttf[g] = count++; 1518*0a96aa3bSJed Brown ng = conn->tree_to_tree[g] * P4EST_FACES + (conn->tree_to_face[g] % P4EST_FACES); 1519*0a96aa3bSJed Brown ttf[ng] = ttf[g]; 1520*0a96aa3bSJed Brown } 1521*0a96aa3bSJed Brown } 1522*0a96aa3bSJed Brown } 1523*0a96aa3bSJed Brown *tree_face_to_uniq = ttf; 1524*0a96aa3bSJed Brown PetscFunctionReturn(0); 1525*0a96aa3bSJed Brown } 1526*0a96aa3bSJed Brown 1527*0a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM dm, p4est_connectivity_t **connOut, PetscInt **tree_face_to_uniq) 1528*0a96aa3bSJed Brown { 1529*0a96aa3bSJed Brown p4est_topidx_t numTrees, numVerts, numCorns, numCtt; 1530*0a96aa3bSJed Brown PetscSection ctt; 1531*0a96aa3bSJed Brown #if defined(P4_TO_P8) 1532*0a96aa3bSJed Brown p4est_topidx_t numEdges, numEtt; 1533*0a96aa3bSJed Brown PetscSection ett; 1534*0a96aa3bSJed Brown PetscInt eStart, eEnd, e, ettSize; 1535*0a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES + P8EST_EDGES; 1536*0a96aa3bSJed Brown PetscInt edgeOff = 1 + P4EST_FACES; 1537*0a96aa3bSJed Brown #else 1538*0a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES; 1539*0a96aa3bSJed Brown #endif 1540*0a96aa3bSJed Brown p4est_connectivity_t *conn; 1541*0a96aa3bSJed Brown PetscInt cStart, cEnd, c, vStart, vEnd, v, fStart, fEnd, f; 1542*0a96aa3bSJed Brown PetscInt *star = NULL, *closure = NULL, closureSize, starSize, cttSize; 1543*0a96aa3bSJed Brown PetscInt *ttf; 1544*0a96aa3bSJed Brown PetscErrorCode ierr; 1545*0a96aa3bSJed Brown 1546*0a96aa3bSJed Brown PetscFunctionBegin; 1547*0a96aa3bSJed Brown /* 1: count objects, allocate */ 1548*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 1549*0a96aa3bSJed Brown ierr = P4estTopidxCast(cEnd-cStart,&numTrees);CHKERRQ(ierr); 1550*0a96aa3bSJed Brown numVerts = P4EST_CHILDREN * numTrees; 1551*0a96aa3bSJed Brown ierr = DMPlexGetDepthStratum(dm,0,&vStart,&vEnd);CHKERRQ(ierr); 1552*0a96aa3bSJed Brown ierr = P4estTopidxCast(vEnd-vStart,&numCorns);CHKERRQ(ierr); 1553*0a96aa3bSJed Brown ierr = PetscSectionCreate(PETSC_COMM_SELF,&ctt);CHKERRQ(ierr); 1554*0a96aa3bSJed Brown ierr = PetscSectionSetChart(ctt,vStart,vEnd);CHKERRQ(ierr); 1555*0a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 1556*0a96aa3bSJed Brown PetscInt s; 1557*0a96aa3bSJed Brown 1558*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 1559*0a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 1560*0a96aa3bSJed Brown PetscInt p = star[2*s]; 1561*0a96aa3bSJed Brown 1562*0a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 1563*0a96aa3bSJed Brown /* we want to count every time cell p references v, so we see how many times it comes up in the closure. This 1564*0a96aa3bSJed Brown * only protects against periodicity problems */ 1565*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1566*0a96aa3bSJed Brown if (closureSize != P4EST_INSUL) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cell %D with wrong closure size %D != %D", p, closureSize, P4EST_INSUL); 1567*0a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 1568*0a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 1569*0a96aa3bSJed Brown 1570*0a96aa3bSJed Brown if (cellVert < vStart || cellVert >= vEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure: vertices"); 1571*0a96aa3bSJed Brown if (cellVert == v) { 1572*0a96aa3bSJed Brown ierr = PetscSectionAddDof(ctt,v,1);CHKERRQ(ierr); 1573*0a96aa3bSJed Brown } 1574*0a96aa3bSJed Brown } 1575*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1576*0a96aa3bSJed Brown } 1577*0a96aa3bSJed Brown } 1578*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 1579*0a96aa3bSJed Brown } 1580*0a96aa3bSJed Brown ierr = PetscSectionSetUp(ctt);CHKERRQ(ierr); 1581*0a96aa3bSJed Brown ierr = PetscSectionGetStorageSize(ctt,&cttSize);CHKERRQ(ierr); 1582*0a96aa3bSJed Brown ierr = P4estTopidxCast(cttSize,&numCtt);CHKERRQ(ierr); 1583*0a96aa3bSJed Brown #if defined(P4_TO_P8) 1584*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(dm,P4EST_DIM-1,&eStart,&eEnd);CHKERRQ(ierr); 1585*0a96aa3bSJed Brown ierr = P4estTopidxCast(eEnd-eStart,&numEdges);CHKERRQ(ierr); 1586*0a96aa3bSJed Brown ierr = PetscSectionCreate(PETSC_COMM_SELF,&ett);CHKERRQ(ierr); 1587*0a96aa3bSJed Brown ierr = PetscSectionSetChart(ett,eStart,eEnd);CHKERRQ(ierr); 1588*0a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 1589*0a96aa3bSJed Brown PetscInt s; 1590*0a96aa3bSJed Brown 1591*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 1592*0a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 1593*0a96aa3bSJed Brown PetscInt p = star[2*s]; 1594*0a96aa3bSJed Brown 1595*0a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 1596*0a96aa3bSJed Brown /* we want to count every time cell p references e, so we see how many times it comes up in the closure. This 1597*0a96aa3bSJed Brown * only protects against periodicity problems */ 1598*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1599*0a96aa3bSJed Brown if (closureSize != P4EST_INSUL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cell with wrong closure size"); 1600*0a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 1601*0a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 1602*0a96aa3bSJed Brown 1603*0a96aa3bSJed Brown if (cellEdge < eStart || cellEdge >= eEnd) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure: edges"); 1604*0a96aa3bSJed Brown if (cellEdge == e) { 1605*0a96aa3bSJed Brown ierr = PetscSectionAddDof(ett,e,1);CHKERRQ(ierr); 1606*0a96aa3bSJed Brown } 1607*0a96aa3bSJed Brown } 1608*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1609*0a96aa3bSJed Brown } 1610*0a96aa3bSJed Brown } 1611*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 1612*0a96aa3bSJed Brown } 1613*0a96aa3bSJed Brown ierr = PetscSectionSetUp(ett);CHKERRQ(ierr); 1614*0a96aa3bSJed Brown ierr = PetscSectionGetStorageSize(ett,&ettSize);CHKERRQ(ierr); 1615*0a96aa3bSJed Brown ierr = P4estTopidxCast(ettSize,&numEtt);CHKERRQ(ierr); 1616*0a96aa3bSJed Brown 1617*0a96aa3bSJed Brown /* This routine allocates space for the arrays, which we fill below */ 1618*0a96aa3bSJed Brown PetscStackCallP4estReturn(conn,p8est_connectivity_new,(numVerts,numTrees,numEdges,numEtt,numCorns,numCtt)); 1619*0a96aa3bSJed Brown #else 1620*0a96aa3bSJed Brown PetscStackCallP4estReturn(conn,p4est_connectivity_new,(numVerts,numTrees,numCorns,numCtt)); 1621*0a96aa3bSJed Brown #endif 1622*0a96aa3bSJed Brown 1623*0a96aa3bSJed Brown /* 2: visit every face, determine neighboring cells(trees) */ 1624*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(dm,1,&fStart,&fEnd);CHKERRQ(ierr); 1625*0a96aa3bSJed Brown ierr = PetscMalloc1((cEnd-cStart) * P4EST_FACES,&ttf);CHKERRQ(ierr); 1626*0a96aa3bSJed Brown for (f = fStart; f < fEnd; f++) { 1627*0a96aa3bSJed Brown PetscInt numSupp, s; 1628*0a96aa3bSJed Brown PetscInt myFace[2] = {-1, -1}; 1629*0a96aa3bSJed Brown PetscInt myOrnt[2] = {PETSC_MIN_INT, PETSC_MIN_INT}; 1630*0a96aa3bSJed Brown const PetscInt *supp; 1631*0a96aa3bSJed Brown 1632*0a96aa3bSJed Brown ierr = DMPlexGetSupportSize(dm, f, &numSupp);CHKERRQ(ierr); 1633*0a96aa3bSJed Brown if (numSupp != 1 && numSupp != 2) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"point %D has facet with %D sides: must be 1 or 2 (boundary or conformal)",f,numSupp); 1634*0a96aa3bSJed Brown ierr = DMPlexGetSupport(dm, f, &supp);CHKERRQ(ierr); 1635*0a96aa3bSJed Brown 1636*0a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 1637*0a96aa3bSJed Brown PetscInt p = supp[s]; 1638*0a96aa3bSJed Brown 1639*0a96aa3bSJed Brown if (p >= cEnd) { 1640*0a96aa3bSJed Brown numSupp--; 1641*0a96aa3bSJed Brown if (s) supp = &supp[1 - s]; 1642*0a96aa3bSJed Brown break; 1643*0a96aa3bSJed Brown } 1644*0a96aa3bSJed Brown } 1645*0a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 1646*0a96aa3bSJed Brown PetscInt p = supp[s], i; 1647*0a96aa3bSJed Brown PetscInt numCone; 1648*0a96aa3bSJed Brown DMPolytopeType ct; 1649*0a96aa3bSJed Brown const PetscInt *cone; 1650*0a96aa3bSJed Brown const PetscInt *ornt; 1651*0a96aa3bSJed Brown PetscInt orient = PETSC_MIN_INT; 1652*0a96aa3bSJed Brown 1653*0a96aa3bSJed Brown ierr = DMPlexGetConeSize(dm, p, &numCone);CHKERRQ(ierr); 1654*0a96aa3bSJed Brown if (numCone != P4EST_FACES) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"cell %D has %D facets, expect %d",p,numCone,P4EST_FACES); 1655*0a96aa3bSJed Brown ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1656*0a96aa3bSJed Brown ierr = DMPlexGetCellType(dm, cone[0], &ct);CHKERRQ(ierr); 1657*0a96aa3bSJed Brown ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr); 1658*0a96aa3bSJed Brown for (i = 0; i < P4EST_FACES; i++) { 1659*0a96aa3bSJed Brown if (cone[i] == f) { 1660*0a96aa3bSJed Brown orient = DMPolytopeConvertNewOrientation_Internal(ct, ornt[i]); 1661*0a96aa3bSJed Brown break; 1662*0a96aa3bSJed Brown } 1663*0a96aa3bSJed Brown } 1664*0a96aa3bSJed Brown if (i >= P4EST_FACES) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"cell %D faced %D mismatch",p,f); 1665*0a96aa3bSJed Brown if (p < cStart || p >= cEnd) { 1666*0a96aa3bSJed Brown DMPolytopeType ct; 1667*0a96aa3bSJed Brown ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1668*0a96aa3bSJed Brown SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"cell %D (%s) should be in [%D, %D)",p,DMPolytopeTypes[ct],cStart,cEnd); 1669*0a96aa3bSJed Brown } 1670*0a96aa3bSJed Brown ttf[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = f - fStart; 1671*0a96aa3bSJed Brown if (numSupp == 1) { 1672*0a96aa3bSJed Brown /* boundary faces indicated by self reference */ 1673*0a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = p - cStart; 1674*0a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = (int8_t) PetscFaceToP4estFace[i]; 1675*0a96aa3bSJed Brown } else { 1676*0a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 1677*0a96aa3bSJed Brown 1678*0a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = supp[1 - s] - cStart; 1679*0a96aa3bSJed Brown myFace[s] = PetscFaceToP4estFace[i]; 1680*0a96aa3bSJed Brown /* get the orientation of cell p in p4est-type closure to facet f, by composing the p4est-closure to 1681*0a96aa3bSJed Brown * petsc-closure permutation and the petsc-closure to facet orientation */ 1682*0a96aa3bSJed Brown myOrnt[s] = DihedralCompose(N,orient,DMPolytopeConvertNewOrientation_Internal(ct, P4estFaceToPetscOrnt[myFace[s]])); 1683*0a96aa3bSJed Brown } 1684*0a96aa3bSJed Brown } 1685*0a96aa3bSJed Brown if (numSupp == 2) { 1686*0a96aa3bSJed Brown for (s = 0; s < numSupp; s++) { 1687*0a96aa3bSJed Brown PetscInt p = supp[s]; 1688*0a96aa3bSJed Brown PetscInt orntAtoB; 1689*0a96aa3bSJed Brown PetscInt p4estOrient; 1690*0a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2; 1691*0a96aa3bSJed Brown 1692*0a96aa3bSJed Brown /* composing the forward permutation with the other cell's inverse permutation gives the self-to-neighbor 1693*0a96aa3bSJed Brown * permutation of this cell-facet's cone */ 1694*0a96aa3bSJed Brown orntAtoB = DihedralCompose(N,DihedralInvert(N,myOrnt[1-s]),myOrnt[s]); 1695*0a96aa3bSJed Brown 1696*0a96aa3bSJed Brown /* convert cone-description permutation (i.e., edges around facet) to cap-description permutation (i.e., 1697*0a96aa3bSJed Brown * vertices around facet) */ 1698*0a96aa3bSJed Brown #if !defined(P4_TO_P8) 1699*0a96aa3bSJed Brown p4estOrient = orntAtoB < 0 ? -(orntAtoB + 1) : orntAtoB; 1700*0a96aa3bSJed Brown #else 1701*0a96aa3bSJed Brown { 1702*0a96aa3bSJed Brown PetscInt firstVert = orntAtoB < 0 ? ((-orntAtoB) % N) : orntAtoB; 1703*0a96aa3bSJed Brown PetscInt p4estFirstVert = firstVert < 2 ? firstVert : (firstVert ^ 1); 1704*0a96aa3bSJed Brown 1705*0a96aa3bSJed Brown /* swap bits */ 1706*0a96aa3bSJed Brown p4estOrient = ((myFace[s] <= myFace[1 - s]) || (orntAtoB < 0)) ? p4estFirstVert : ((p4estFirstVert >> 1) | ((p4estFirstVert & 1) << 1)); 1707*0a96aa3bSJed Brown } 1708*0a96aa3bSJed Brown #endif 1709*0a96aa3bSJed Brown /* encode neighbor face and orientation in tree_to_face per p4est_connectivity standard (see 1710*0a96aa3bSJed Brown * p4est_connectivity.h, p8est_connectivity.h) */ 1711*0a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + myFace[s]] = (int8_t) myFace[1 - s] + p4estOrient * P4EST_FACES; 1712*0a96aa3bSJed Brown } 1713*0a96aa3bSJed Brown } 1714*0a96aa3bSJed Brown } 1715*0a96aa3bSJed Brown 1716*0a96aa3bSJed Brown #if defined(P4_TO_P8) 1717*0a96aa3bSJed Brown /* 3: visit every edge */ 1718*0a96aa3bSJed Brown conn->ett_offset[0] = 0; 1719*0a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) { 1720*0a96aa3bSJed Brown PetscInt off, s; 1721*0a96aa3bSJed Brown 1722*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(ett,e,&off);CHKERRQ(ierr); 1723*0a96aa3bSJed Brown conn->ett_offset[e - eStart] = (p4est_topidx_t) off; 1724*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 1725*0a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 1726*0a96aa3bSJed Brown PetscInt p = star[2 * s]; 1727*0a96aa3bSJed Brown 1728*0a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 1729*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1730*0a96aa3bSJed Brown if (closureSize != P4EST_INSUL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure"); 1731*0a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) { 1732*0a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)]; 1733*0a96aa3bSJed Brown PetscInt cellOrnt = closure[2 * (c + edgeOff) + 1]; 1734*0a96aa3bSJed Brown DMPolytopeType ct; 1735*0a96aa3bSJed Brown 1736*0a96aa3bSJed Brown ierr = DMPlexGetCellType(dm, cellEdge, &ct);CHKERRQ(ierr); 1737*0a96aa3bSJed Brown cellOrnt = DMPolytopeConvertNewOrientation_Internal(ct, cellOrnt); 1738*0a96aa3bSJed Brown if (cellEdge == e) { 1739*0a96aa3bSJed Brown PetscInt p4estEdge = PetscEdgeToP4estEdge[c]; 1740*0a96aa3bSJed Brown PetscInt totalOrient; 1741*0a96aa3bSJed Brown 1742*0a96aa3bSJed Brown /* compose p4est-closure to petsc-closure permutation and petsc-closure to edge orientation */ 1743*0a96aa3bSJed Brown totalOrient = DihedralCompose(2,cellOrnt,DMPolytopeConvertNewOrientation_Internal(DM_POLYTOPE_SEGMENT, P4estEdgeToPetscOrnt[p4estEdge])); 1744*0a96aa3bSJed Brown /* p4est orientations are positive: -2 => 1, -1 => 0 */ 1745*0a96aa3bSJed Brown totalOrient = (totalOrient < 0) ? -(totalOrient + 1) : totalOrient; 1746*0a96aa3bSJed Brown conn->edge_to_tree[off] = (p4est_locidx_t) (p - cStart); 1747*0a96aa3bSJed Brown /* encode cell-edge and orientation in edge_to_edge per p8est_connectivity standart (see 1748*0a96aa3bSJed Brown * p8est_connectivity.h) */ 1749*0a96aa3bSJed Brown conn->edge_to_edge[off++] = (int8_t) p4estEdge + P8EST_EDGES * totalOrient; 1750*0a96aa3bSJed Brown conn->tree_to_edge[P8EST_EDGES * (p - cStart) + p4estEdge] = e - eStart; 1751*0a96aa3bSJed Brown } 1752*0a96aa3bSJed Brown } 1753*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1754*0a96aa3bSJed Brown } 1755*0a96aa3bSJed Brown } 1756*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(dm,e,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 1757*0a96aa3bSJed Brown } 1758*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&ett);CHKERRQ(ierr); 1759*0a96aa3bSJed Brown #endif 1760*0a96aa3bSJed Brown 1761*0a96aa3bSJed Brown /* 4: visit every vertex */ 1762*0a96aa3bSJed Brown conn->ctt_offset[0] = 0; 1763*0a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) { 1764*0a96aa3bSJed Brown PetscInt off, s; 1765*0a96aa3bSJed Brown 1766*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(ctt,v,&off);CHKERRQ(ierr); 1767*0a96aa3bSJed Brown conn->ctt_offset[v - vStart] = (p4est_topidx_t) off; 1768*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 1769*0a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 1770*0a96aa3bSJed Brown PetscInt p = star[2 * s]; 1771*0a96aa3bSJed Brown 1772*0a96aa3bSJed Brown if (p >= cStart && p < cEnd) { 1773*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1774*0a96aa3bSJed Brown if (closureSize != P4EST_INSUL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Non-standard closure"); 1775*0a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) { 1776*0a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)]; 1777*0a96aa3bSJed Brown 1778*0a96aa3bSJed Brown if (cellVert == v) { 1779*0a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[c]; 1780*0a96aa3bSJed Brown 1781*0a96aa3bSJed Brown conn->corner_to_tree[off] = (p4est_locidx_t) (p - cStart); 1782*0a96aa3bSJed Brown conn->corner_to_corner[off++] = (int8_t) p4estVert; 1783*0a96aa3bSJed Brown conn->tree_to_corner[P4EST_CHILDREN * (p - cStart) + p4estVert] = v - vStart; 1784*0a96aa3bSJed Brown } 1785*0a96aa3bSJed Brown } 1786*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 1787*0a96aa3bSJed Brown } 1788*0a96aa3bSJed Brown } 1789*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(dm,v,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 1790*0a96aa3bSJed Brown } 1791*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&ctt);CHKERRQ(ierr); 1792*0a96aa3bSJed Brown 1793*0a96aa3bSJed Brown /* 5: Compute the coordinates */ 1794*0a96aa3bSJed Brown { 1795*0a96aa3bSJed Brown PetscInt coordDim; 1796*0a96aa3bSJed Brown Vec coordVec; 1797*0a96aa3bSJed Brown PetscSection coordSec; 1798*0a96aa3bSJed Brown PetscBool localized; 1799*0a96aa3bSJed Brown 1800*0a96aa3bSJed Brown ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 1801*0a96aa3bSJed Brown ierr = DMGetCoordinatesLocal(dm, &coordVec);CHKERRQ(ierr); 1802*0a96aa3bSJed Brown ierr = DMGetCoordinatesLocalizedLocal(dm, &localized);CHKERRQ(ierr); 1803*0a96aa3bSJed Brown ierr = DMGetCoordinateSection(dm, &coordSec);CHKERRQ(ierr); 1804*0a96aa3bSJed Brown for (c = cStart; c < cEnd; c++) { 1805*0a96aa3bSJed Brown PetscInt dof; 1806*0a96aa3bSJed Brown PetscScalar *cellCoords = NULL; 1807*0a96aa3bSJed Brown 1808*0a96aa3bSJed Brown ierr = DMPlexVecGetClosure(dm, coordSec, coordVec, c, &dof, &cellCoords);CHKERRQ(ierr); 1809*0a96aa3bSJed Brown if (!localized && dof != P4EST_CHILDREN * coordDim) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Need coordinates at the corners: (dof) %D != %D * %D (sdim)", dof, P4EST_CHILDREN, coordDim); 1810*0a96aa3bSJed Brown for (v = 0; v < P4EST_CHILDREN; v++) { 1811*0a96aa3bSJed Brown PetscInt i, lim = PetscMin(3, coordDim); 1812*0a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[v]; 1813*0a96aa3bSJed Brown 1814*0a96aa3bSJed Brown conn->tree_to_vertex[P4EST_CHILDREN * (c - cStart) + v] = P4EST_CHILDREN * (c - cStart) + v; 1815*0a96aa3bSJed Brown /* p4est vertices are always embedded in R^3 */ 1816*0a96aa3bSJed Brown for (i = 0; i < 3; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = 0.; 1817*0a96aa3bSJed Brown for (i = 0; i < lim; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = PetscRealPart(cellCoords[v * coordDim + i]); 1818*0a96aa3bSJed Brown } 1819*0a96aa3bSJed Brown ierr = DMPlexVecRestoreClosure(dm, coordSec, coordVec, c, &dof, &cellCoords);CHKERRQ(ierr); 1820*0a96aa3bSJed Brown } 1821*0a96aa3bSJed Brown } 1822*0a96aa3bSJed Brown 1823*0a96aa3bSJed Brown #if defined(P4EST_ENABLE_DEBUG) 1824*0a96aa3bSJed Brown if (!p4est_connectivity_is_valid(conn)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Plex to p4est conversion failed"); 1825*0a96aa3bSJed Brown #endif 1826*0a96aa3bSJed Brown 1827*0a96aa3bSJed Brown *connOut = conn; 1828*0a96aa3bSJed Brown 1829*0a96aa3bSJed Brown *tree_face_to_uniq = ttf; 1830*0a96aa3bSJed Brown 1831*0a96aa3bSJed Brown PetscFunctionReturn(0); 1832*0a96aa3bSJed Brown } 1833*0a96aa3bSJed Brown 1834*0a96aa3bSJed Brown static PetscErrorCode locidx_to_PetscInt(sc_array_t * array) 1835*0a96aa3bSJed Brown { 1836*0a96aa3bSJed Brown sc_array_t *newarray; 1837*0a96aa3bSJed Brown size_t zz, count = array->elem_count; 1838*0a96aa3bSJed Brown 1839*0a96aa3bSJed Brown PetscFunctionBegin; 1840*0a96aa3bSJed Brown if (array->elem_size != sizeof(p4est_locidx_t)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong locidx size"); 1841*0a96aa3bSJed Brown 1842*0a96aa3bSJed Brown if (sizeof(p4est_locidx_t) == sizeof(PetscInt)) PetscFunctionReturn(0); 1843*0a96aa3bSJed Brown 1844*0a96aa3bSJed Brown newarray = sc_array_new_size (sizeof(PetscInt), array->elem_count); 1845*0a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 1846*0a96aa3bSJed Brown p4est_locidx_t il = *((p4est_locidx_t*) sc_array_index (array, zz)); 1847*0a96aa3bSJed Brown PetscInt *ip = (PetscInt*) sc_array_index (newarray, zz); 1848*0a96aa3bSJed Brown 1849*0a96aa3bSJed Brown *ip = (PetscInt) il; 1850*0a96aa3bSJed Brown } 1851*0a96aa3bSJed Brown 1852*0a96aa3bSJed Brown sc_array_reset (array); 1853*0a96aa3bSJed Brown sc_array_init_size (array, sizeof(PetscInt), count); 1854*0a96aa3bSJed Brown sc_array_copy (array, newarray); 1855*0a96aa3bSJed Brown sc_array_destroy (newarray); 1856*0a96aa3bSJed Brown PetscFunctionReturn(0); 1857*0a96aa3bSJed Brown } 1858*0a96aa3bSJed Brown 1859*0a96aa3bSJed Brown static PetscErrorCode coords_double_to_PetscScalar(sc_array_t * array, PetscInt dim) 1860*0a96aa3bSJed Brown { 1861*0a96aa3bSJed Brown sc_array_t *newarray; 1862*0a96aa3bSJed Brown size_t zz, count = array->elem_count; 1863*0a96aa3bSJed Brown 1864*0a96aa3bSJed Brown PetscFunctionBegin; 1865*0a96aa3bSJed Brown if (array->elem_size != 3 * sizeof(double)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong coordinate size"); 1866*0a96aa3bSJed Brown #if !defined(PETSC_USE_COMPLEX) 1867*0a96aa3bSJed Brown if (sizeof(double) == sizeof(PetscScalar) && dim == 3) PetscFunctionReturn(0); 1868*0a96aa3bSJed Brown #endif 1869*0a96aa3bSJed Brown 1870*0a96aa3bSJed Brown newarray = sc_array_new_size (dim * sizeof(PetscScalar), array->elem_count); 1871*0a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 1872*0a96aa3bSJed Brown int i; 1873*0a96aa3bSJed Brown double *id = (double*) sc_array_index (array, zz); 1874*0a96aa3bSJed Brown PetscScalar *ip = (PetscScalar*) sc_array_index (newarray, zz); 1875*0a96aa3bSJed Brown 1876*0a96aa3bSJed Brown for (i = 0; i < dim; i++) ip[i] = 0.; 1877*0a96aa3bSJed Brown for (i = 0; i < PetscMin(dim,3); i++) ip[i] = (PetscScalar) id[i]; 1878*0a96aa3bSJed Brown } 1879*0a96aa3bSJed Brown 1880*0a96aa3bSJed Brown sc_array_reset (array); 1881*0a96aa3bSJed Brown sc_array_init_size (array, dim * sizeof(PetscScalar), count); 1882*0a96aa3bSJed Brown sc_array_copy (array, newarray); 1883*0a96aa3bSJed Brown sc_array_destroy (newarray); 1884*0a96aa3bSJed Brown PetscFunctionReturn(0); 1885*0a96aa3bSJed Brown } 1886*0a96aa3bSJed Brown 1887*0a96aa3bSJed Brown static PetscErrorCode locidx_pair_to_PetscSFNode(sc_array_t * array) 1888*0a96aa3bSJed Brown { 1889*0a96aa3bSJed Brown sc_array_t *newarray; 1890*0a96aa3bSJed Brown size_t zz, count = array->elem_count; 1891*0a96aa3bSJed Brown 1892*0a96aa3bSJed Brown PetscFunctionBegin; 1893*0a96aa3bSJed Brown if (array->elem_size != 2 * sizeof(p4est_locidx_t)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong locidx size"); 1894*0a96aa3bSJed Brown 1895*0a96aa3bSJed Brown newarray = sc_array_new_size (sizeof(PetscSFNode), array->elem_count); 1896*0a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 1897*0a96aa3bSJed Brown p4est_locidx_t *il = (p4est_locidx_t*) sc_array_index (array, zz); 1898*0a96aa3bSJed Brown PetscSFNode *ip = (PetscSFNode*) sc_array_index (newarray, zz); 1899*0a96aa3bSJed Brown 1900*0a96aa3bSJed Brown ip->rank = (PetscInt) il[0]; 1901*0a96aa3bSJed Brown ip->index = (PetscInt) il[1]; 1902*0a96aa3bSJed Brown } 1903*0a96aa3bSJed Brown 1904*0a96aa3bSJed Brown sc_array_reset (array); 1905*0a96aa3bSJed Brown sc_array_init_size (array, sizeof(PetscSFNode), count); 1906*0a96aa3bSJed Brown sc_array_copy (array, newarray); 1907*0a96aa3bSJed Brown sc_array_destroy (newarray); 1908*0a96aa3bSJed Brown PetscFunctionReturn(0); 1909*0a96aa3bSJed Brown } 1910*0a96aa3bSJed Brown 1911*0a96aa3bSJed Brown static PetscErrorCode P4estToPlex_Local(p4est_t *p4est, DM * plex) 1912*0a96aa3bSJed Brown { 1913*0a96aa3bSJed Brown PetscErrorCode ierr; 1914*0a96aa3bSJed Brown 1915*0a96aa3bSJed Brown PetscFunctionBegin; 1916*0a96aa3bSJed Brown { 1917*0a96aa3bSJed Brown sc_array_t *points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 1918*0a96aa3bSJed Brown sc_array_t *cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 1919*0a96aa3bSJed Brown sc_array_t *cones = sc_array_new(sizeof(p4est_locidx_t)); 1920*0a96aa3bSJed Brown sc_array_t *cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 1921*0a96aa3bSJed Brown sc_array_t *coords = sc_array_new(3 * sizeof(double)); 1922*0a96aa3bSJed Brown sc_array_t *children = sc_array_new(sizeof(p4est_locidx_t)); 1923*0a96aa3bSJed Brown sc_array_t *parents = sc_array_new(sizeof(p4est_locidx_t)); 1924*0a96aa3bSJed Brown sc_array_t *childids = sc_array_new(sizeof(p4est_locidx_t)); 1925*0a96aa3bSJed Brown sc_array_t *leaves = sc_array_new(sizeof(p4est_locidx_t)); 1926*0a96aa3bSJed Brown sc_array_t *remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 1927*0a96aa3bSJed Brown p4est_locidx_t first_local_quad; 1928*0a96aa3bSJed Brown 1929*0a96aa3bSJed 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)); 1930*0a96aa3bSJed Brown 1931*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(points_per_dim);CHKERRQ(ierr); 1932*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(cone_sizes);CHKERRQ(ierr); 1933*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(cones);CHKERRQ(ierr); 1934*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(cone_orientations);CHKERRQ(ierr); 1935*0a96aa3bSJed Brown ierr = coords_double_to_PetscScalar(coords, P4EST_DIM);CHKERRQ(ierr); 1936*0a96aa3bSJed Brown 1937*0a96aa3bSJed Brown ierr = DMPlexCreate(PETSC_COMM_SELF,plex);CHKERRQ(ierr); 1938*0a96aa3bSJed Brown ierr = DMSetDimension(*plex,P4EST_DIM);CHKERRQ(ierr); 1939*0a96aa3bSJed Brown ierr = DMPlexCreateFromDAG(*plex,P4EST_DIM,(PetscInt*)points_per_dim->array,(PetscInt*)cone_sizes->array,(PetscInt*)cones->array,(PetscInt*)cone_orientations->array,(PetscScalar*)coords->array);CHKERRQ(ierr); 1940*0a96aa3bSJed Brown ierr = DMPlexConvertOldOrientations_Internal(*plex);CHKERRQ(ierr); 1941*0a96aa3bSJed Brown sc_array_destroy (points_per_dim); 1942*0a96aa3bSJed Brown sc_array_destroy (cone_sizes); 1943*0a96aa3bSJed Brown sc_array_destroy (cones); 1944*0a96aa3bSJed Brown sc_array_destroy (cone_orientations); 1945*0a96aa3bSJed Brown sc_array_destroy (coords); 1946*0a96aa3bSJed Brown sc_array_destroy (children); 1947*0a96aa3bSJed Brown sc_array_destroy (parents); 1948*0a96aa3bSJed Brown sc_array_destroy (childids); 1949*0a96aa3bSJed Brown sc_array_destroy (leaves); 1950*0a96aa3bSJed Brown sc_array_destroy (remotes); 1951*0a96aa3bSJed Brown } 1952*0a96aa3bSJed Brown PetscFunctionReturn(0); 1953*0a96aa3bSJed Brown } 1954*0a96aa3bSJed Brown 1955*0a96aa3bSJed Brown #define DMReferenceTreeGetChildSymmetry_pforest _append_pforest(DMReferenceTreeGetChildSymmetry) 1956*0a96aa3bSJed Brown static PetscErrorCode DMReferenceTreeGetChildSymmetry_pforest(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB,PetscInt *childB) 1957*0a96aa3bSJed Brown { 1958*0a96aa3bSJed Brown PetscInt coneSize, dStart, dEnd, vStart, vEnd, dim, ABswap, oAvert, oBvert, ABswapVert; 1959*0a96aa3bSJed Brown PetscErrorCode ierr; 1960*0a96aa3bSJed Brown 1961*0a96aa3bSJed Brown PetscFunctionBegin; 1962*0a96aa3bSJed Brown if (parentOrientA == parentOrientB) { 1963*0a96aa3bSJed Brown if (childOrientB) *childOrientB = childOrientA; 1964*0a96aa3bSJed Brown if (childB) *childB = childA; 1965*0a96aa3bSJed Brown PetscFunctionReturn(0); 1966*0a96aa3bSJed Brown } 1967*0a96aa3bSJed Brown ierr = DMPlexGetDepthStratum(dm,0,&vStart,&vEnd);CHKERRQ(ierr); 1968*0a96aa3bSJed Brown if (childA >= vStart && childA < vEnd) { /* vertices (always in the middle) are invarient under rotation */ 1969*0a96aa3bSJed Brown if (childOrientB) *childOrientB = 0; 1970*0a96aa3bSJed Brown if (childB) *childB = childA; 1971*0a96aa3bSJed Brown PetscFunctionReturn(0); 1972*0a96aa3bSJed Brown } 1973*0a96aa3bSJed Brown for (dim = 0; dim < 3; dim++) { 1974*0a96aa3bSJed Brown ierr = DMPlexGetDepthStratum(dm,dim,&dStart,&dEnd);CHKERRQ(ierr); 1975*0a96aa3bSJed Brown if (parent >= dStart && parent <= dEnd) break; 1976*0a96aa3bSJed Brown } 1977*0a96aa3bSJed Brown if (dim > 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot perform child symmetry for %d-cells",dim); 1978*0a96aa3bSJed Brown if (!dim) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"A vertex has no children"); 1979*0a96aa3bSJed Brown if (childA < dStart || childA >= dEnd) { /* a 1-cell in a 2-cell */ 1980*0a96aa3bSJed Brown /* this is a lower-dimensional child: bootstrap */ 1981*0a96aa3bSJed Brown PetscInt size, i, sA = -1, sB, sOrientB, sConeSize; 1982*0a96aa3bSJed Brown const PetscInt *supp, *coneA, *coneB, *oA, *oB; 1983*0a96aa3bSJed Brown 1984*0a96aa3bSJed Brown ierr = DMPlexGetSupportSize(dm,childA,&size);CHKERRQ(ierr); 1985*0a96aa3bSJed Brown ierr = DMPlexGetSupport(dm,childA,&supp);CHKERRQ(ierr); 1986*0a96aa3bSJed Brown 1987*0a96aa3bSJed Brown /* find a point sA in supp(childA) that has the same parent */ 1988*0a96aa3bSJed Brown for (i = 0; i < size; i++) { 1989*0a96aa3bSJed Brown PetscInt sParent; 1990*0a96aa3bSJed Brown 1991*0a96aa3bSJed Brown sA = supp[i]; 1992*0a96aa3bSJed Brown if (sA == parent) continue; 1993*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(dm,sA,&sParent,NULL);CHKERRQ(ierr); 1994*0a96aa3bSJed Brown if (sParent == parent) break; 1995*0a96aa3bSJed Brown } 1996*0a96aa3bSJed Brown if (i == size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"could not find support in children"); 1997*0a96aa3bSJed Brown /* find out which point sB is in an equivalent position to sA under 1998*0a96aa3bSJed Brown * parentOrientB */ 1999*0a96aa3bSJed Brown ierr = DMReferenceTreeGetChildSymmetry_pforest(dm,parent,parentOrientA,0,sA,parentOrientB,&sOrientB,&sB);CHKERRQ(ierr); 2000*0a96aa3bSJed Brown ierr = DMPlexGetConeSize(dm,sA,&sConeSize);CHKERRQ(ierr); 2001*0a96aa3bSJed Brown ierr = DMPlexGetCone(dm,sA,&coneA);CHKERRQ(ierr); 2002*0a96aa3bSJed Brown ierr = DMPlexGetCone(dm,sB,&coneB);CHKERRQ(ierr); 2003*0a96aa3bSJed Brown ierr = DMPlexGetConeOrientation(dm,sA,&oA);CHKERRQ(ierr); 2004*0a96aa3bSJed Brown ierr = DMPlexGetConeOrientation(dm,sB,&oB);CHKERRQ(ierr); 2005*0a96aa3bSJed Brown /* step through the cone of sA in natural order */ 2006*0a96aa3bSJed Brown for (i = 0; i < sConeSize; i++) { 2007*0a96aa3bSJed Brown if (coneA[i] == childA) { 2008*0a96aa3bSJed Brown /* if childA is at position i in coneA, 2009*0a96aa3bSJed Brown * then we want the point that is at sOrientB*i in coneB */ 2010*0a96aa3bSJed Brown PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize -(sOrientB+1) - i) % sConeSize); 2011*0a96aa3bSJed Brown if (childB) *childB = coneB[j]; 2012*0a96aa3bSJed Brown if (childOrientB) { 2013*0a96aa3bSJed Brown DMPolytopeType ct; 2014*0a96aa3bSJed Brown PetscInt oBtrue; 2015*0a96aa3bSJed Brown 2016*0a96aa3bSJed Brown ierr = DMPlexGetConeSize(dm,childA,&coneSize);CHKERRQ(ierr); 2017*0a96aa3bSJed Brown /* compose sOrientB and oB[j] */ 2018*0a96aa3bSJed Brown if (coneSize != 0 && coneSize != 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected a vertex or an edge"); 2019*0a96aa3bSJed Brown ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 2020*0a96aa3bSJed Brown /* we may have to flip an edge */ 2021*0a96aa3bSJed Brown oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientationInv(ct, -1, oB[j]); 2022*0a96aa3bSJed Brown oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue); 2023*0a96aa3bSJed Brown ABswap = DihedralSwap(coneSize,DMPolytopeConvertNewOrientation_Internal(ct, oA[i]),oBtrue); 2024*0a96aa3bSJed Brown *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 2025*0a96aa3bSJed Brown } 2026*0a96aa3bSJed Brown break; 2027*0a96aa3bSJed Brown } 2028*0a96aa3bSJed Brown } 2029*0a96aa3bSJed Brown if (i == sConeSize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"support cone mismatch"); 2030*0a96aa3bSJed Brown PetscFunctionReturn(0); 2031*0a96aa3bSJed Brown } 2032*0a96aa3bSJed Brown /* get the cone size and symmetry swap */ 2033*0a96aa3bSJed Brown ierr = DMPlexGetConeSize(dm,parent,&coneSize);CHKERRQ(ierr); 2034*0a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB); 2035*0a96aa3bSJed Brown if (dim == 2) { 2036*0a96aa3bSJed Brown /* orientations refer to cones: we want them to refer to vertices: 2037*0a96aa3bSJed Brown * if it's a rotation, they are the same, but if the order is reversed, a 2038*0a96aa3bSJed Brown * permutation that puts side i first does *not* put vertex i first */ 2039*0a96aa3bSJed Brown oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1); 2040*0a96aa3bSJed Brown oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1); 2041*0a96aa3bSJed Brown ABswapVert = DihedralSwap(coneSize, oAvert, oBvert); 2042*0a96aa3bSJed Brown } else { 2043*0a96aa3bSJed Brown oAvert = parentOrientA; 2044*0a96aa3bSJed Brown oBvert = parentOrientB; 2045*0a96aa3bSJed Brown ABswapVert = ABswap; 2046*0a96aa3bSJed Brown } 2047*0a96aa3bSJed Brown if (childB) { 2048*0a96aa3bSJed Brown /* assume that each child corresponds to a vertex, in the same order */ 2049*0a96aa3bSJed Brown PetscInt p, posA = -1, numChildren, i; 2050*0a96aa3bSJed Brown const PetscInt *children; 2051*0a96aa3bSJed Brown 2052*0a96aa3bSJed Brown /* count which position the child is in */ 2053*0a96aa3bSJed Brown ierr = DMPlexGetTreeChildren(dm,parent,&numChildren,&children);CHKERRQ(ierr); 2054*0a96aa3bSJed Brown for (i = 0; i < numChildren; i++) { 2055*0a96aa3bSJed Brown p = children[i]; 2056*0a96aa3bSJed Brown if (p == childA) { 2057*0a96aa3bSJed Brown if (dim == 1) { 2058*0a96aa3bSJed Brown posA = i; 2059*0a96aa3bSJed Brown } else { /* 2D Morton to rotation */ 2060*0a96aa3bSJed Brown posA = (i & 2) ? (i ^ 1) : i; 2061*0a96aa3bSJed Brown } 2062*0a96aa3bSJed Brown break; 2063*0a96aa3bSJed Brown } 2064*0a96aa3bSJed Brown } 2065*0a96aa3bSJed Brown if (posA >= coneSize) { 2066*0a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Could not find childA in children of parent"); 2067*0a96aa3bSJed Brown } else { 2068*0a96aa3bSJed Brown /* figure out position B by applying ABswapVert */ 2069*0a96aa3bSJed Brown PetscInt posB, childIdB; 2070*0a96aa3bSJed Brown 2071*0a96aa3bSJed Brown posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize -(ABswapVert + 1) - posA) % coneSize); 2072*0a96aa3bSJed Brown if (dim == 1) { 2073*0a96aa3bSJed Brown childIdB = posB; 2074*0a96aa3bSJed Brown } else { /* 2D rotation to Morton */ 2075*0a96aa3bSJed Brown childIdB = (posB & 2) ? (posB ^ 1) : posB; 2076*0a96aa3bSJed Brown } 2077*0a96aa3bSJed Brown if (childB) *childB = children[childIdB]; 2078*0a96aa3bSJed Brown } 2079*0a96aa3bSJed Brown } 2080*0a96aa3bSJed Brown if (childOrientB) *childOrientB = DihedralCompose(coneSize,childOrientA,ABswap); 2081*0a96aa3bSJed Brown PetscFunctionReturn(0); 2082*0a96aa3bSJed Brown } 2083*0a96aa3bSJed Brown 2084*0a96aa3bSJed Brown #define DMCreateReferenceTree_pforest _append_pforest(DMCreateReferenceTree) 2085*0a96aa3bSJed Brown static PetscErrorCode DMCreateReferenceTree_pforest(MPI_Comm comm, DM *dm) 2086*0a96aa3bSJed Brown { 2087*0a96aa3bSJed Brown p4est_connectivity_t *refcube; 2088*0a96aa3bSJed Brown p4est_t *root, *refined; 2089*0a96aa3bSJed Brown DM dmRoot, dmRefined; 2090*0a96aa3bSJed Brown DM_Plex *mesh; 2091*0a96aa3bSJed Brown PetscMPIInt rank; 2092*0a96aa3bSJed Brown PetscErrorCode ierr; 2093*0a96aa3bSJed Brown 2094*0a96aa3bSJed Brown PetscFunctionBegin; 2095*0a96aa3bSJed Brown PetscStackCallP4estReturn(refcube,p4est_connectivity_new_byname,("unit")); 2096*0a96aa3bSJed Brown { /* [-1,1]^d geometry */ 2097*0a96aa3bSJed Brown PetscInt i, j; 2098*0a96aa3bSJed Brown 2099*0a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) { 2100*0a96aa3bSJed Brown for (j = 0; j < 3; j++) { 2101*0a96aa3bSJed Brown refcube->vertices[3 * i + j] *= 2.; 2102*0a96aa3bSJed Brown refcube->vertices[3 * i + j] -= 1.; 2103*0a96aa3bSJed Brown } 2104*0a96aa3bSJed Brown } 2105*0a96aa3bSJed Brown } 2106*0a96aa3bSJed Brown PetscStackCallP4estReturn(root,p4est_new,(PETSC_COMM_SELF,refcube,0,NULL,NULL)); 2107*0a96aa3bSJed Brown PetscStackCallP4estReturn(refined,p4est_new_ext,(PETSC_COMM_SELF,refcube,0,1,1,0,NULL,NULL)); 2108*0a96aa3bSJed Brown ierr = P4estToPlex_Local(root,&dmRoot);CHKERRQ(ierr); 2109*0a96aa3bSJed Brown ierr = P4estToPlex_Local(refined,&dmRefined);CHKERRQ(ierr); 2110*0a96aa3bSJed Brown { 2111*0a96aa3bSJed Brown #if !defined(P4_TO_P8) 2112*0a96aa3bSJed Brown PetscInt nPoints = 25; 2113*0a96aa3bSJed Brown PetscInt perm[25] = {0, 1, 2, 3, 2114*0a96aa3bSJed Brown 4, 12, 8, 14, 2115*0a96aa3bSJed Brown 6, 9, 15, 2116*0a96aa3bSJed Brown 5, 13, 10, 2117*0a96aa3bSJed Brown 7, 11, 2118*0a96aa3bSJed Brown 16, 22, 20, 24, 2119*0a96aa3bSJed Brown 17, 21, 2120*0a96aa3bSJed Brown 18, 23, 2121*0a96aa3bSJed Brown 19}; 2122*0a96aa3bSJed Brown PetscInt ident[25] = {0, 0, 0, 0, 2123*0a96aa3bSJed Brown 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 0, 2124*0a96aa3bSJed Brown 5, 6, 7, 8, 1, 2, 3, 4, 0}; 2125*0a96aa3bSJed Brown #else 2126*0a96aa3bSJed Brown PetscInt nPoints = 125; 2127*0a96aa3bSJed Brown PetscInt perm[125] = {0, 1, 2, 3, 4, 5, 6, 7, 2128*0a96aa3bSJed Brown 8, 32, 16, 36, 24, 40, 2129*0a96aa3bSJed Brown 12, 17, 37, 25, 41, 2130*0a96aa3bSJed Brown 9, 33, 20, 26, 42, 2131*0a96aa3bSJed Brown 13, 21, 27, 43, 2132*0a96aa3bSJed Brown 10, 34, 18, 38, 28, 2133*0a96aa3bSJed Brown 14, 19, 39, 29, 2134*0a96aa3bSJed Brown 11, 35, 22, 30, 2135*0a96aa3bSJed Brown 15, 23, 31, 2136*0a96aa3bSJed Brown 44, 84, 76, 92, 52, 86, 68, 94, 60, 78, 70, 96, 2137*0a96aa3bSJed Brown 45, 85, 77, 93, 54, 72, 62, 74, 2138*0a96aa3bSJed Brown 46, 80, 53, 87, 69, 95, 64, 82, 2139*0a96aa3bSJed Brown 47, 81, 55, 73, 66, 2140*0a96aa3bSJed Brown 48, 88, 56, 90, 61, 79, 71, 97, 2141*0a96aa3bSJed Brown 49, 89, 58, 63, 75, 2142*0a96aa3bSJed Brown 50, 57, 91, 65, 83, 2143*0a96aa3bSJed Brown 51, 59, 67, 2144*0a96aa3bSJed Brown 98, 106, 110, 122, 114, 120, 118, 124, 2145*0a96aa3bSJed Brown 99, 111, 115, 119, 2146*0a96aa3bSJed Brown 100, 107, 116, 121, 2147*0a96aa3bSJed Brown 101, 117, 2148*0a96aa3bSJed Brown 102, 108, 112, 123, 2149*0a96aa3bSJed Brown 103, 113, 2150*0a96aa3bSJed Brown 104, 109, 2151*0a96aa3bSJed Brown 105}; 2152*0a96aa3bSJed Brown PetscInt ident[125] = {0, 0, 0, 0, 0, 0, 0, 0, 2153*0a96aa3bSJed 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, 2154*0a96aa3bSJed Brown 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2155*0a96aa3bSJed 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, 2156*0a96aa3bSJed 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, 2157*0a96aa3bSJed Brown 0, 0, 0, 0, 0, 0, 2158*0a96aa3bSJed Brown 19, 20, 21, 22, 23, 24, 25, 26, 2159*0a96aa3bSJed Brown 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 2160*0a96aa3bSJed Brown 1, 2, 3, 4, 5, 6, 2161*0a96aa3bSJed Brown 0}; 2162*0a96aa3bSJed Brown 2163*0a96aa3bSJed Brown #endif 2164*0a96aa3bSJed Brown IS permIS; 2165*0a96aa3bSJed Brown DM dmPerm; 2166*0a96aa3bSJed Brown 2167*0a96aa3bSJed Brown ierr = ISCreateGeneral(PETSC_COMM_SELF,nPoints,perm,PETSC_USE_POINTER,&permIS);CHKERRQ(ierr); 2168*0a96aa3bSJed Brown ierr = DMPlexPermute(dmRefined,permIS,&dmPerm);CHKERRQ(ierr); 2169*0a96aa3bSJed Brown if (dmPerm) { 2170*0a96aa3bSJed Brown ierr = DMDestroy(&dmRefined);CHKERRQ(ierr); 2171*0a96aa3bSJed Brown dmRefined = dmPerm; 2172*0a96aa3bSJed Brown } 2173*0a96aa3bSJed Brown ierr = ISDestroy(&permIS);CHKERRQ(ierr); 2174*0a96aa3bSJed Brown { 2175*0a96aa3bSJed Brown PetscInt p; 2176*0a96aa3bSJed Brown ierr = DMCreateLabel(dmRoot,"identity");CHKERRQ(ierr); 2177*0a96aa3bSJed Brown ierr = DMCreateLabel(dmRefined,"identity");CHKERRQ(ierr); 2178*0a96aa3bSJed Brown for (p = 0; p < P4EST_INSUL; p++) { 2179*0a96aa3bSJed Brown ierr = DMSetLabelValue(dmRoot,"identity",p,p);CHKERRQ(ierr); 2180*0a96aa3bSJed Brown } 2181*0a96aa3bSJed Brown for (p = 0; p < nPoints; p++) { 2182*0a96aa3bSJed Brown ierr = DMSetLabelValue(dmRefined,"identity",p,ident[p]);CHKERRQ(ierr); 2183*0a96aa3bSJed Brown } 2184*0a96aa3bSJed Brown } 2185*0a96aa3bSJed Brown } 2186*0a96aa3bSJed Brown ierr = DMPlexCreateReferenceTree_Union(dmRoot,dmRefined,"identity",dm);CHKERRQ(ierr); 2187*0a96aa3bSJed Brown mesh = (DM_Plex*) (*dm)->data; 2188*0a96aa3bSJed Brown mesh->getchildsymmetry = DMReferenceTreeGetChildSymmetry_pforest; 2189*0a96aa3bSJed Brown ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 2190*0a96aa3bSJed Brown if (rank == 0) { 2191*0a96aa3bSJed Brown ierr = DMViewFromOptions(dmRoot, NULL,"-dm_p4est_ref_root_view");CHKERRQ(ierr); 2192*0a96aa3bSJed Brown ierr = DMViewFromOptions(dmRefined,NULL,"-dm_p4est_ref_refined_view");CHKERRQ(ierr); 2193*0a96aa3bSJed Brown ierr = DMViewFromOptions(dmRefined,NULL,"-dm_p4est_ref_tree_view");CHKERRQ(ierr); 2194*0a96aa3bSJed Brown } 2195*0a96aa3bSJed Brown ierr = DMDestroy(&dmRefined);CHKERRQ(ierr); 2196*0a96aa3bSJed Brown ierr = DMDestroy(&dmRoot);CHKERRQ(ierr); 2197*0a96aa3bSJed Brown PetscStackCallP4est(p4est_destroy,(refined)); 2198*0a96aa3bSJed Brown PetscStackCallP4est(p4est_destroy,(root)); 2199*0a96aa3bSJed Brown PetscStackCallP4est(p4est_connectivity_destroy,(refcube)); 2200*0a96aa3bSJed Brown PetscFunctionReturn(0); 2201*0a96aa3bSJed Brown } 2202*0a96aa3bSJed Brown 2203*0a96aa3bSJed Brown static PetscErrorCode DMShareDiscretization(DM dmA, DM dmB) 2204*0a96aa3bSJed Brown { 2205*0a96aa3bSJed Brown void *ctx; 2206*0a96aa3bSJed Brown PetscInt num; 2207*0a96aa3bSJed Brown PetscReal val; 2208*0a96aa3bSJed Brown PetscErrorCode ierr; 2209*0a96aa3bSJed Brown 2210*0a96aa3bSJed Brown PetscFunctionBegin; 2211*0a96aa3bSJed Brown ierr = DMGetApplicationContext(dmA,&ctx);CHKERRQ(ierr); 2212*0a96aa3bSJed Brown ierr = DMSetApplicationContext(dmB,ctx);CHKERRQ(ierr); 2213*0a96aa3bSJed Brown ierr = DMCopyDisc(dmA,dmB);CHKERRQ(ierr); 2214*0a96aa3bSJed Brown ierr = DMGetOutputSequenceNumber(dmA,&num,&val);CHKERRQ(ierr); 2215*0a96aa3bSJed Brown ierr = DMSetOutputSequenceNumber(dmB,num,val);CHKERRQ(ierr); 2216*0a96aa3bSJed Brown if (dmB->localSection != dmA->localSection || dmB->globalSection != dmA->globalSection) { 2217*0a96aa3bSJed Brown ierr = DMClearLocalVectors(dmB);CHKERRQ(ierr); 2218*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)dmA->localSection);CHKERRQ(ierr); 2219*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&(dmB->localSection));CHKERRQ(ierr); 2220*0a96aa3bSJed Brown dmB->localSection = dmA->localSection; 2221*0a96aa3bSJed Brown ierr = DMClearGlobalVectors(dmB);CHKERRQ(ierr); 2222*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)dmA->globalSection);CHKERRQ(ierr); 2223*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&(dmB->globalSection));CHKERRQ(ierr); 2224*0a96aa3bSJed Brown dmB->globalSection = dmA->globalSection; 2225*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)dmA->defaultConstraintSection);CHKERRQ(ierr); 2226*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&(dmB->defaultConstraintSection));CHKERRQ(ierr); 2227*0a96aa3bSJed Brown dmB->defaultConstraintSection = dmA->defaultConstraintSection; 2228*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)dmA->defaultConstraintMat);CHKERRQ(ierr); 2229*0a96aa3bSJed Brown ierr = MatDestroy(&(dmB->defaultConstraintMat));CHKERRQ(ierr); 2230*0a96aa3bSJed Brown dmB->defaultConstraintMat = dmA->defaultConstraintMat; 2231*0a96aa3bSJed Brown if (dmA->map) {ierr = PetscLayoutReference(dmA->map, &dmB->map);CHKERRQ(ierr);} 2232*0a96aa3bSJed Brown } 2233*0a96aa3bSJed Brown if (dmB->sectionSF != dmA->sectionSF) { 2234*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)dmA->sectionSF);CHKERRQ(ierr); 2235*0a96aa3bSJed Brown ierr = PetscSFDestroy(&dmB->sectionSF);CHKERRQ(ierr); 2236*0a96aa3bSJed Brown dmB->sectionSF = dmA->sectionSF; 2237*0a96aa3bSJed Brown } 2238*0a96aa3bSJed Brown PetscFunctionReturn(0); 2239*0a96aa3bSJed Brown } 2240*0a96aa3bSJed Brown 2241*0a96aa3bSJed Brown /* Get an SF that broadcasts a coarse-cell covering of the local fine cells */ 2242*0a96aa3bSJed Brown static PetscErrorCode DMPforestGetCellCoveringSF(MPI_Comm comm,p4est_t *p4estC, p4est_t *p4estF, PetscInt cStart, PetscInt cEnd, PetscSF *coveringSF) 2243*0a96aa3bSJed Brown { 2244*0a96aa3bSJed Brown PetscInt startF, endF, startC, endC, p, nLeaves; 2245*0a96aa3bSJed Brown PetscSFNode *leaves; 2246*0a96aa3bSJed Brown PetscSF sf; 2247*0a96aa3bSJed Brown PetscInt *recv, *send; 2248*0a96aa3bSJed Brown PetscMPIInt tag; 2249*0a96aa3bSJed Brown MPI_Request *recvReqs, *sendReqs; 2250*0a96aa3bSJed Brown PetscSection section; 2251*0a96aa3bSJed Brown PetscErrorCode ierr; 2252*0a96aa3bSJed Brown 2253*0a96aa3bSJed Brown PetscFunctionBegin; 2254*0a96aa3bSJed Brown ierr = DMPforestComputeOverlappingRanks(p4estC->mpisize,p4estC->mpirank,p4estF,p4estC,&startC,&endC);CHKERRQ(ierr); 2255*0a96aa3bSJed Brown ierr = PetscMalloc2(2*(endC-startC),&recv,endC-startC,&recvReqs);CHKERRQ(ierr); 2256*0a96aa3bSJed Brown ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr); 2257*0a96aa3bSJed Brown for (p = startC; p < endC; p++) { 2258*0a96aa3bSJed Brown recvReqs[p-startC] = MPI_REQUEST_NULL; /* just in case we don't initiate a receive */ 2259*0a96aa3bSJed Brown if (p4estC->global_first_quadrant[p] == p4estC->global_first_quadrant[p+1]) { /* empty coarse partition */ 2260*0a96aa3bSJed Brown recv[2*(p-startC)] = 0; 2261*0a96aa3bSJed Brown recv[2*(p-startC)+1] = 0; 2262*0a96aa3bSJed Brown continue; 2263*0a96aa3bSJed Brown } 2264*0a96aa3bSJed Brown 2265*0a96aa3bSJed Brown ierr = MPI_Irecv(&recv[2*(p-startC)],2,MPIU_INT,p,tag,comm,&recvReqs[p-startC]);CHKERRMPI(ierr); 2266*0a96aa3bSJed Brown } 2267*0a96aa3bSJed Brown ierr = DMPforestComputeOverlappingRanks(p4estC->mpisize,p4estC->mpirank,p4estC,p4estF,&startF,&endF);CHKERRQ(ierr); 2268*0a96aa3bSJed Brown ierr = PetscMalloc2(2*(endF-startF),&send,endF-startF,&sendReqs);CHKERRQ(ierr); 2269*0a96aa3bSJed Brown /* count the quadrants rank will send to each of [startF,endF) */ 2270*0a96aa3bSJed Brown for (p = startF; p < endF; p++) { 2271*0a96aa3bSJed Brown p4est_quadrant_t *myFineStart = &p4estF->global_first_position[p]; 2272*0a96aa3bSJed Brown p4est_quadrant_t *myFineEnd = &p4estF->global_first_position[p+1]; 2273*0a96aa3bSJed Brown PetscInt tStart = (PetscInt) myFineStart->p.which_tree; 2274*0a96aa3bSJed Brown PetscInt tEnd = (PetscInt) myFineEnd->p.which_tree; 2275*0a96aa3bSJed Brown PetscInt firstCell = -1, lastCell = -1; 2276*0a96aa3bSJed Brown p4est_tree_t *treeStart = &(((p4est_tree_t*) p4estC->trees->array)[tStart]); 2277*0a96aa3bSJed Brown p4est_tree_t *treeEnd = (size_t) tEnd < p4estC->trees->elem_count ? &(((p4est_tree_t*) p4estC->trees->array)[tEnd]) : NULL; 2278*0a96aa3bSJed Brown ssize_t overlapIndex; 2279*0a96aa3bSJed Brown 2280*0a96aa3bSJed Brown sendReqs[p-startF] = MPI_REQUEST_NULL; /* just in case we don't initiate a send */ 2281*0a96aa3bSJed Brown if (p4estF->global_first_quadrant[p] == p4estF->global_first_quadrant[p+1]) continue; 2282*0a96aa3bSJed Brown 2283*0a96aa3bSJed Brown /* locate myFineStart in (or before) a cell */ 2284*0a96aa3bSJed Brown if (treeStart->quadrants.elem_count) { 2285*0a96aa3bSJed Brown PetscStackCallP4estReturn(overlapIndex,sc_array_bsearch,(&(treeStart->quadrants),myFineStart,p4est_quadrant_disjoint)); 2286*0a96aa3bSJed Brown if (overlapIndex < 0) { 2287*0a96aa3bSJed Brown firstCell = 0; 2288*0a96aa3bSJed Brown } else { 2289*0a96aa3bSJed Brown firstCell = treeStart->quadrants_offset + overlapIndex; 2290*0a96aa3bSJed Brown } 2291*0a96aa3bSJed Brown } else { 2292*0a96aa3bSJed Brown firstCell = 0; 2293*0a96aa3bSJed Brown } 2294*0a96aa3bSJed Brown if (treeEnd && treeEnd->quadrants.elem_count) { 2295*0a96aa3bSJed Brown PetscStackCallP4estReturn(overlapIndex,sc_array_bsearch,(&(treeEnd->quadrants),myFineEnd,p4est_quadrant_disjoint)); 2296*0a96aa3bSJed Brown if (overlapIndex < 0) { /* all of this local section is overlapped */ 2297*0a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 2298*0a96aa3bSJed Brown } else { 2299*0a96aa3bSJed Brown p4est_quadrant_t *container = &(((p4est_quadrant_t*) treeEnd->quadrants.array)[overlapIndex]); 2300*0a96aa3bSJed Brown p4est_quadrant_t first_desc; 2301*0a96aa3bSJed Brown int equal; 2302*0a96aa3bSJed Brown 2303*0a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_first_descendant,(container,&first_desc,P4EST_QMAXLEVEL)); 2304*0a96aa3bSJed Brown PetscStackCallP4estReturn(equal,p4est_quadrant_is_equal,(myFineEnd,&first_desc)); 2305*0a96aa3bSJed Brown if (equal) { 2306*0a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex; 2307*0a96aa3bSJed Brown } else { 2308*0a96aa3bSJed Brown lastCell = treeEnd->quadrants_offset + overlapIndex + 1; 2309*0a96aa3bSJed Brown } 2310*0a96aa3bSJed Brown } 2311*0a96aa3bSJed Brown } else { 2312*0a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants; 2313*0a96aa3bSJed Brown } 2314*0a96aa3bSJed Brown send[2*(p-startF)] = firstCell; 2315*0a96aa3bSJed Brown send[2*(p-startF)+1] = lastCell - firstCell; 2316*0a96aa3bSJed Brown ierr = MPI_Isend(&send[2*(p-startF)],2,MPIU_INT,p,tag,comm,&sendReqs[p-startF]);CHKERRMPI(ierr); 2317*0a96aa3bSJed Brown } 2318*0a96aa3bSJed Brown ierr = MPI_Waitall((PetscMPIInt)(endC-startC),recvReqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr); 2319*0a96aa3bSJed Brown ierr = PetscSectionCreate(PETSC_COMM_SELF,§ion);CHKERRQ(ierr); 2320*0a96aa3bSJed Brown ierr = PetscSectionSetChart(section,startC,endC);CHKERRQ(ierr); 2321*0a96aa3bSJed Brown for (p = startC; p < endC; p++) { 2322*0a96aa3bSJed Brown PetscInt numCells = recv[2*(p-startC)+1]; 2323*0a96aa3bSJed Brown ierr = PetscSectionSetDof(section,p,numCells);CHKERRQ(ierr); 2324*0a96aa3bSJed Brown } 2325*0a96aa3bSJed Brown ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 2326*0a96aa3bSJed Brown ierr = PetscSectionGetStorageSize(section,&nLeaves);CHKERRQ(ierr); 2327*0a96aa3bSJed Brown ierr = PetscMalloc1(nLeaves,&leaves);CHKERRQ(ierr); 2328*0a96aa3bSJed Brown for (p = startC; p < endC; p++) { 2329*0a96aa3bSJed Brown PetscInt firstCell = recv[2*(p-startC)]; 2330*0a96aa3bSJed Brown PetscInt numCells = recv[2*(p-startC)+1]; 2331*0a96aa3bSJed Brown PetscInt off, i; 2332*0a96aa3bSJed Brown 2333*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(section,p,&off);CHKERRQ(ierr); 2334*0a96aa3bSJed Brown for (i = 0; i < numCells; i++) { 2335*0a96aa3bSJed Brown leaves[off+i].rank = p; 2336*0a96aa3bSJed Brown leaves[off+i].index = firstCell + i; 2337*0a96aa3bSJed Brown } 2338*0a96aa3bSJed Brown } 2339*0a96aa3bSJed Brown ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr); 2340*0a96aa3bSJed Brown ierr = PetscSFSetGraph(sf,cEnd-cStart,nLeaves,NULL,PETSC_OWN_POINTER,leaves,PETSC_OWN_POINTER);CHKERRQ(ierr); 2341*0a96aa3bSJed Brown ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 2342*0a96aa3bSJed Brown ierr = MPI_Waitall((PetscMPIInt)(endF-startF),sendReqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr); 2343*0a96aa3bSJed Brown ierr = PetscFree2(send,sendReqs);CHKERRQ(ierr); 2344*0a96aa3bSJed Brown ierr = PetscFree2(recv,recvReqs);CHKERRQ(ierr); 2345*0a96aa3bSJed Brown *coveringSF = sf; 2346*0a96aa3bSJed Brown PetscFunctionReturn(0); 2347*0a96aa3bSJed Brown } 2348*0a96aa3bSJed Brown 2349*0a96aa3bSJed Brown /* closure points for locally-owned cells */ 2350*0a96aa3bSJed Brown static PetscErrorCode DMPforestGetCellSFNodes(DM dm, PetscInt numClosureIndices, PetscInt *numClosurePoints, PetscSFNode **closurePoints,PetscBool redirect) 2351*0a96aa3bSJed Brown { 2352*0a96aa3bSJed Brown PetscInt cStart, cEnd; 2353*0a96aa3bSJed Brown PetscInt count, c; 2354*0a96aa3bSJed Brown PetscMPIInt rank; 2355*0a96aa3bSJed Brown PetscInt closureSize = -1; 2356*0a96aa3bSJed Brown PetscInt *closure = NULL; 2357*0a96aa3bSJed Brown PetscSF pointSF; 2358*0a96aa3bSJed Brown PetscInt nleaves, nroots; 2359*0a96aa3bSJed Brown const PetscInt *ilocal; 2360*0a96aa3bSJed Brown const PetscSFNode *iremote; 2361*0a96aa3bSJed Brown DM plex; 2362*0a96aa3bSJed Brown DM_Forest *forest; 2363*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 2364*0a96aa3bSJed Brown PetscErrorCode ierr; 2365*0a96aa3bSJed Brown 2366*0a96aa3bSJed Brown PetscFunctionBegin; 2367*0a96aa3bSJed Brown forest = (DM_Forest *) dm->data; 2368*0a96aa3bSJed Brown pforest = (DM_Forest_pforest *) forest->data; 2369*0a96aa3bSJed Brown cStart = pforest->cLocalStart; 2370*0a96aa3bSJed Brown cEnd = pforest->cLocalEnd; 2371*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 2372*0a96aa3bSJed Brown ierr = DMGetPointSF(dm,&pointSF);CHKERRQ(ierr); 2373*0a96aa3bSJed Brown ierr = PetscSFGetGraph(pointSF,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); 2374*0a96aa3bSJed Brown nleaves = PetscMax(0,nleaves); 2375*0a96aa3bSJed Brown nroots = PetscMax(0,nroots); 2376*0a96aa3bSJed Brown *numClosurePoints = numClosureIndices * (cEnd - cStart); 2377*0a96aa3bSJed Brown ierr = PetscMalloc1(*numClosurePoints,closurePoints);CHKERRQ(ierr); 2378*0a96aa3bSJed Brown ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr); 2379*0a96aa3bSJed Brown for (c = cStart, count = 0; c < cEnd; c++) { 2380*0a96aa3bSJed Brown PetscInt i; 2381*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(plex,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 2382*0a96aa3bSJed Brown 2383*0a96aa3bSJed Brown for (i = 0; i < numClosureIndices; i++, count++) { 2384*0a96aa3bSJed Brown PetscInt p = closure[2 * i]; 2385*0a96aa3bSJed Brown PetscInt loc = -1; 2386*0a96aa3bSJed Brown 2387*0a96aa3bSJed Brown ierr = PetscFindInt(p,nleaves,ilocal,&loc);CHKERRQ(ierr); 2388*0a96aa3bSJed Brown if (redirect && loc >= 0) { 2389*0a96aa3bSJed Brown (*closurePoints)[count].rank = iremote[loc].rank; 2390*0a96aa3bSJed Brown (*closurePoints)[count].index = iremote[loc].index; 2391*0a96aa3bSJed Brown } else { 2392*0a96aa3bSJed Brown (*closurePoints)[count].rank = rank; 2393*0a96aa3bSJed Brown (*closurePoints)[count].index = p; 2394*0a96aa3bSJed Brown } 2395*0a96aa3bSJed Brown } 2396*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(plex,c,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 2397*0a96aa3bSJed Brown } 2398*0a96aa3bSJed Brown PetscFunctionReturn(0); 2399*0a96aa3bSJed Brown } 2400*0a96aa3bSJed Brown 2401*0a96aa3bSJed Brown static void MPIAPI DMPforestMaxSFNode(void *a, void *b, PetscMPIInt *len, MPI_Datatype *type) 2402*0a96aa3bSJed Brown { 2403*0a96aa3bSJed Brown PetscMPIInt i; 2404*0a96aa3bSJed Brown 2405*0a96aa3bSJed Brown for (i = 0; i < *len; i++) { 2406*0a96aa3bSJed Brown PetscSFNode *A = (PetscSFNode*)a; 2407*0a96aa3bSJed Brown PetscSFNode *B = (PetscSFNode*)b; 2408*0a96aa3bSJed Brown 2409*0a96aa3bSJed Brown if (B->rank < 0) *B = *A; 2410*0a96aa3bSJed Brown } 2411*0a96aa3bSJed Brown } 2412*0a96aa3bSJed Brown 2413*0a96aa3bSJed Brown static PetscErrorCode DMPforestGetTransferSF_Point(DM coarse, DM fine, PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 2414*0a96aa3bSJed Brown { 2415*0a96aa3bSJed Brown MPI_Comm comm; 2416*0a96aa3bSJed Brown PetscMPIInt rank, size; 2417*0a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 2418*0a96aa3bSJed Brown p4est_t *p4estC, *p4estF; 2419*0a96aa3bSJed Brown PetscInt numClosureIndices; 2420*0a96aa3bSJed Brown PetscInt numClosurePointsC, numClosurePointsF; 2421*0a96aa3bSJed Brown PetscSFNode *closurePointsC, *closurePointsF; 2422*0a96aa3bSJed Brown p4est_quadrant_t *coverQuads = NULL; 2423*0a96aa3bSJed Brown p4est_quadrant_t **treeQuads; 2424*0a96aa3bSJed Brown PetscInt *treeQuadCounts; 2425*0a96aa3bSJed Brown MPI_Datatype nodeType; 2426*0a96aa3bSJed Brown MPI_Datatype nodeClosureType; 2427*0a96aa3bSJed Brown MPI_Op sfNodeReduce; 2428*0a96aa3bSJed Brown p4est_topidx_t fltF, lltF, t; 2429*0a96aa3bSJed Brown DM plexC, plexF; 2430*0a96aa3bSJed Brown PetscInt pStartF, pEndF, pStartC, pEndC; 2431*0a96aa3bSJed Brown PetscBool saveInCoarse = PETSC_FALSE; 2432*0a96aa3bSJed Brown PetscBool saveInFine = PETSC_FALSE; 2433*0a96aa3bSJed Brown PetscBool formCids = (childIds != NULL) ? PETSC_TRUE : PETSC_FALSE; 2434*0a96aa3bSJed Brown PetscInt *cids = NULL; 2435*0a96aa3bSJed Brown PetscErrorCode ierr; 2436*0a96aa3bSJed Brown 2437*0a96aa3bSJed Brown PetscFunctionBegin; 2438*0a96aa3bSJed Brown pforestC = (DM_Forest_pforest*) ((DM_Forest*) coarse->data)->data; 2439*0a96aa3bSJed Brown pforestF = (DM_Forest_pforest*) ((DM_Forest*) fine->data)->data; 2440*0a96aa3bSJed Brown p4estC = pforestC->forest; 2441*0a96aa3bSJed Brown p4estF = pforestF->forest; 2442*0a96aa3bSJed Brown if (pforestC->topo != pforestF->topo) SETERRQ(PetscObjectComm((PetscObject)coarse),PETSC_ERR_ARG_INCOMP,"DM's must have the same base DM"); 2443*0a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 2444*0a96aa3bSJed Brown ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 2445*0a96aa3bSJed Brown ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 2446*0a96aa3bSJed Brown ierr = DMPforestGetPlex(fine,&plexF);CHKERRQ(ierr); 2447*0a96aa3bSJed Brown ierr = DMPlexGetChart(plexF,&pStartF,&pEndF);CHKERRQ(ierr); 2448*0a96aa3bSJed Brown ierr = DMPforestGetPlex(coarse,&plexC);CHKERRQ(ierr); 2449*0a96aa3bSJed Brown ierr = DMPlexGetChart(plexC,&pStartC,&pEndC);CHKERRQ(ierr); 2450*0a96aa3bSJed Brown { /* check if the results have been cached */ 2451*0a96aa3bSJed Brown DM adaptCoarse, adaptFine; 2452*0a96aa3bSJed Brown 2453*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(coarse,&adaptCoarse);CHKERRQ(ierr); 2454*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(fine,&adaptFine);CHKERRQ(ierr); 2455*0a96aa3bSJed Brown if (adaptCoarse && adaptCoarse->data == fine->data) { /* coarse is adapted from fine */ 2456*0a96aa3bSJed Brown if (pforestC->pointSelfToAdaptSF) { 2457*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)(pforestC->pointSelfToAdaptSF));CHKERRQ(ierr); 2458*0a96aa3bSJed Brown *sf = pforestC->pointSelfToAdaptSF; 2459*0a96aa3bSJed Brown if (childIds) { 2460*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndF-pStartF,&cids);CHKERRQ(ierr); 2461*0a96aa3bSJed Brown ierr = PetscArraycpy(cids,pforestC->pointSelfToAdaptCids,pEndF-pStartF);CHKERRQ(ierr); 2462*0a96aa3bSJed Brown *childIds = cids; 2463*0a96aa3bSJed Brown } 2464*0a96aa3bSJed Brown PetscFunctionReturn(0); 2465*0a96aa3bSJed Brown } else { 2466*0a96aa3bSJed Brown saveInCoarse = PETSC_TRUE; 2467*0a96aa3bSJed Brown formCids = PETSC_TRUE; 2468*0a96aa3bSJed Brown } 2469*0a96aa3bSJed Brown } else if (adaptFine && adaptFine->data == coarse->data) { /* fine is adapted from coarse */ 2470*0a96aa3bSJed Brown if (pforestF->pointAdaptToSelfSF) { 2471*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)(pforestF->pointAdaptToSelfSF));CHKERRQ(ierr); 2472*0a96aa3bSJed Brown *sf = pforestF->pointAdaptToSelfSF; 2473*0a96aa3bSJed Brown if (childIds) { 2474*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndF-pStartF,&cids);CHKERRQ(ierr); 2475*0a96aa3bSJed Brown ierr = PetscArraycpy(cids,pforestF->pointAdaptToSelfCids,pEndF-pStartF);CHKERRQ(ierr); 2476*0a96aa3bSJed Brown *childIds = cids; 2477*0a96aa3bSJed Brown } 2478*0a96aa3bSJed Brown PetscFunctionReturn(0); 2479*0a96aa3bSJed Brown } else { 2480*0a96aa3bSJed Brown saveInFine = PETSC_TRUE; 2481*0a96aa3bSJed Brown formCids = PETSC_TRUE; 2482*0a96aa3bSJed Brown } 2483*0a96aa3bSJed Brown } 2484*0a96aa3bSJed Brown } 2485*0a96aa3bSJed Brown 2486*0a96aa3bSJed Brown /* count the number of closure points that have dofs and create a list */ 2487*0a96aa3bSJed Brown numClosureIndices = P4EST_INSUL; 2488*0a96aa3bSJed Brown /* create the datatype */ 2489*0a96aa3bSJed Brown ierr = MPI_Type_contiguous(2,MPIU_INT,&nodeType);CHKERRMPI(ierr); 2490*0a96aa3bSJed Brown ierr = MPI_Type_commit(&nodeType);CHKERRMPI(ierr); 2491*0a96aa3bSJed Brown ierr = MPI_Op_create(DMPforestMaxSFNode,PETSC_FALSE,&sfNodeReduce);CHKERRMPI(ierr); 2492*0a96aa3bSJed Brown ierr = MPI_Type_contiguous(numClosureIndices*2,MPIU_INT,&nodeClosureType);CHKERRMPI(ierr); 2493*0a96aa3bSJed Brown ierr = MPI_Type_commit(&nodeClosureType);CHKERRMPI(ierr); 2494*0a96aa3bSJed Brown /* everything has to go through cells: for each cell, create a list of the sfnodes in its closure */ 2495*0a96aa3bSJed Brown /* get lists of closure point SF nodes for every cell */ 2496*0a96aa3bSJed Brown ierr = DMPforestGetCellSFNodes(coarse,numClosureIndices,&numClosurePointsC,&closurePointsC,PETSC_TRUE);CHKERRQ(ierr); 2497*0a96aa3bSJed Brown ierr = DMPforestGetCellSFNodes(fine ,numClosureIndices,&numClosurePointsF,&closurePointsF,PETSC_FALSE);CHKERRQ(ierr); 2498*0a96aa3bSJed Brown /* create pointers for tree lists */ 2499*0a96aa3bSJed Brown fltF = p4estF->first_local_tree; 2500*0a96aa3bSJed Brown lltF = p4estF->last_local_tree; 2501*0a96aa3bSJed Brown ierr = PetscCalloc2(lltF + 1 - fltF, &treeQuads, lltF + 1 - fltF, &treeQuadCounts);CHKERRQ(ierr); 2502*0a96aa3bSJed Brown /* if the partitions don't match, ship the coarse to cover the fine */ 2503*0a96aa3bSJed Brown if (size > 1) { 2504*0a96aa3bSJed Brown PetscInt p; 2505*0a96aa3bSJed Brown 2506*0a96aa3bSJed Brown for (p = 0; p < size; p++) { 2507*0a96aa3bSJed Brown int equal; 2508*0a96aa3bSJed Brown 2509*0a96aa3bSJed Brown PetscStackCallP4estReturn(equal,p4est_quadrant_is_equal_piggy,(&p4estC->global_first_position[p],&p4estF->global_first_position[p])); 2510*0a96aa3bSJed Brown if (!equal) break; 2511*0a96aa3bSJed Brown } 2512*0a96aa3bSJed Brown if (p < size) { /* non-matching distribution: send the coarse to cover the fine */ 2513*0a96aa3bSJed Brown PetscInt cStartC, cEndC; 2514*0a96aa3bSJed Brown PetscSF coveringSF; 2515*0a96aa3bSJed Brown PetscInt nleaves; 2516*0a96aa3bSJed Brown PetscInt count; 2517*0a96aa3bSJed Brown PetscSFNode *newClosurePointsC; 2518*0a96aa3bSJed Brown p4est_quadrant_t *coverQuadsSend; 2519*0a96aa3bSJed Brown p4est_topidx_t fltC = p4estC->first_local_tree; 2520*0a96aa3bSJed Brown p4est_topidx_t lltC = p4estC->last_local_tree; 2521*0a96aa3bSJed Brown p4est_topidx_t t; 2522*0a96aa3bSJed Brown PetscMPIInt blockSizes[4] = {P4EST_DIM,2,1,1}; 2523*0a96aa3bSJed Brown MPI_Aint blockOffsets[4] = {offsetof(p4est_quadrant_t,x), 2524*0a96aa3bSJed Brown offsetof(p4est_quadrant_t,level), 2525*0a96aa3bSJed Brown offsetof(p4est_quadrant_t,pad16), 2526*0a96aa3bSJed Brown offsetof(p4est_quadrant_t,p)}; 2527*0a96aa3bSJed Brown MPI_Datatype blockTypes[4] = {MPI_INT32_T,MPI_INT8_T,MPI_INT16_T,MPI_INT32_T/* p.which_tree */}; 2528*0a96aa3bSJed Brown MPI_Datatype quadStruct,quadType; 2529*0a96aa3bSJed Brown 2530*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(plexC,0,&cStartC,&cEndC);CHKERRQ(ierr); 2531*0a96aa3bSJed Brown ierr = DMPforestGetCellCoveringSF(comm,p4estC,p4estF,pforestC->cLocalStart,pforestC->cLocalEnd,&coveringSF);CHKERRQ(ierr); 2532*0a96aa3bSJed Brown ierr = PetscSFGetGraph(coveringSF,NULL,&nleaves,NULL,NULL);CHKERRQ(ierr); 2533*0a96aa3bSJed Brown ierr = PetscMalloc1(numClosureIndices*nleaves,&newClosurePointsC);CHKERRQ(ierr); 2534*0a96aa3bSJed Brown ierr = PetscMalloc1(nleaves,&coverQuads);CHKERRQ(ierr); 2535*0a96aa3bSJed Brown ierr = PetscMalloc1(cEndC-cStartC,&coverQuadsSend);CHKERRQ(ierr); 2536*0a96aa3bSJed Brown count = 0; 2537*0a96aa3bSJed Brown for (t = fltC; t <= lltC; t++) { /* unfortunately, we need to pack a send array, since quads are not stored packed in p4est */ 2538*0a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4estC->trees->array)[t]); 2539*0a96aa3bSJed Brown PetscInt q; 2540*0a96aa3bSJed Brown 2541*0a96aa3bSJed Brown ierr = PetscMemcpy(&coverQuadsSend[count],tree->quadrants.array,tree->quadrants.elem_count * sizeof(p4est_quadrant_t));CHKERRQ(ierr); 2542*0a96aa3bSJed Brown for (q = 0; (size_t) q < tree->quadrants.elem_count; q++) coverQuadsSend[count+q].p.which_tree = t; 2543*0a96aa3bSJed Brown count += tree->quadrants.elem_count; 2544*0a96aa3bSJed Brown } 2545*0a96aa3bSJed Brown /* p is of a union type p4est_quadrant_data, but only the p.which_tree field is active at this time. So, we 2546*0a96aa3bSJed Brown have a simple blockTypes[] to use. Note that quadStruct does not count potential padding in array of 2547*0a96aa3bSJed Brown p4est_quadrant_t. We have to call MPI_Type_create_resized() to change upper-bound of quadStruct. 2548*0a96aa3bSJed Brown */ 2549*0a96aa3bSJed Brown ierr = MPI_Type_create_struct(4,blockSizes,blockOffsets,blockTypes,&quadStruct);CHKERRMPI(ierr); 2550*0a96aa3bSJed Brown ierr = MPI_Type_create_resized(quadStruct,0,sizeof(p4est_quadrant_t),&quadType);CHKERRMPI(ierr); 2551*0a96aa3bSJed Brown ierr = MPI_Type_commit(&quadType);CHKERRMPI(ierr); 2552*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(coveringSF,nodeClosureType,closurePointsC,newClosurePointsC,MPI_REPLACE);CHKERRQ(ierr); 2553*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(coveringSF,quadType,coverQuadsSend,coverQuads,MPI_REPLACE);CHKERRQ(ierr); 2554*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(coveringSF,nodeClosureType,closurePointsC,newClosurePointsC,MPI_REPLACE);CHKERRQ(ierr); 2555*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(coveringSF,quadType,coverQuadsSend,coverQuads,MPI_REPLACE);CHKERRQ(ierr); 2556*0a96aa3bSJed Brown ierr = MPI_Type_free(&quadStruct);CHKERRMPI(ierr); 2557*0a96aa3bSJed Brown ierr = MPI_Type_free(&quadType);CHKERRMPI(ierr); 2558*0a96aa3bSJed Brown ierr = PetscFree(coverQuadsSend);CHKERRQ(ierr); 2559*0a96aa3bSJed Brown ierr = PetscFree(closurePointsC);CHKERRQ(ierr); 2560*0a96aa3bSJed Brown ierr = PetscSFDestroy(&coveringSF);CHKERRQ(ierr); 2561*0a96aa3bSJed Brown closurePointsC = newClosurePointsC; 2562*0a96aa3bSJed Brown 2563*0a96aa3bSJed Brown /* assign tree quads based on locations in coverQuads */ 2564*0a96aa3bSJed Brown { 2565*0a96aa3bSJed Brown PetscInt q; 2566*0a96aa3bSJed Brown for (q = 0; q < nleaves; q++) { 2567*0a96aa3bSJed Brown p4est_locidx_t t = coverQuads[q].p.which_tree; 2568*0a96aa3bSJed Brown if (!treeQuadCounts[t-fltF]++) treeQuads[t-fltF] = &coverQuads[q]; 2569*0a96aa3bSJed Brown } 2570*0a96aa3bSJed Brown } 2571*0a96aa3bSJed Brown } 2572*0a96aa3bSJed Brown } 2573*0a96aa3bSJed Brown if (!coverQuads) { /* matching partitions: assign tree quads based on locations in p4est native arrays */ 2574*0a96aa3bSJed Brown for (t = fltF; t <= lltF; t++) { 2575*0a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4estC->trees->array)[t]); 2576*0a96aa3bSJed Brown 2577*0a96aa3bSJed Brown treeQuadCounts[t - fltF] = tree->quadrants.elem_count; 2578*0a96aa3bSJed Brown treeQuads[t - fltF] = (p4est_quadrant_t*) tree->quadrants.array; 2579*0a96aa3bSJed Brown } 2580*0a96aa3bSJed Brown } 2581*0a96aa3bSJed Brown 2582*0a96aa3bSJed Brown { 2583*0a96aa3bSJed Brown PetscInt p; 2584*0a96aa3bSJed Brown PetscInt cLocalStartF; 2585*0a96aa3bSJed Brown PetscSF pointSF; 2586*0a96aa3bSJed Brown PetscSFNode *roots; 2587*0a96aa3bSJed Brown PetscInt *rootType; 2588*0a96aa3bSJed Brown DM refTree = NULL; 2589*0a96aa3bSJed Brown DMLabel canonical; 2590*0a96aa3bSJed Brown PetscInt *childClosures[P4EST_CHILDREN] = {NULL}; 2591*0a96aa3bSJed Brown PetscInt *rootClosure = NULL; 2592*0a96aa3bSJed Brown PetscInt coarseOffset; 2593*0a96aa3bSJed Brown PetscInt numCoarseQuads; 2594*0a96aa3bSJed Brown 2595*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndF-pStartF,&roots);CHKERRQ(ierr); 2596*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndF-pStartF,&rootType);CHKERRQ(ierr); 2597*0a96aa3bSJed Brown ierr = DMGetPointSF(fine,&pointSF);CHKERRQ(ierr); 2598*0a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 2599*0a96aa3bSJed Brown roots[p-pStartF].rank = -1; 2600*0a96aa3bSJed Brown roots[p-pStartF].index = -1; 2601*0a96aa3bSJed Brown rootType[p-pStartF] = -1; 2602*0a96aa3bSJed Brown } 2603*0a96aa3bSJed Brown if (formCids) { 2604*0a96aa3bSJed Brown PetscInt child; 2605*0a96aa3bSJed Brown 2606*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndF-pStartF,&cids);CHKERRQ(ierr); 2607*0a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) cids[p - pStartF] = -2; 2608*0a96aa3bSJed Brown ierr = DMPlexGetReferenceTree(plexF,&refTree);CHKERRQ(ierr); 2609*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(refTree,0,PETSC_TRUE,NULL,&rootClosure);CHKERRQ(ierr); 2610*0a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { /* get the closures of the child cells in the reference tree */ 2611*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(refTree,child+1,PETSC_TRUE,NULL,&childClosures[child]);CHKERRQ(ierr); 2612*0a96aa3bSJed Brown } 2613*0a96aa3bSJed Brown ierr = DMGetLabel(refTree,"canonical",&canonical);CHKERRQ(ierr); 2614*0a96aa3bSJed Brown } 2615*0a96aa3bSJed Brown cLocalStartF = pforestF->cLocalStart; 2616*0a96aa3bSJed Brown for (t = fltF, coarseOffset = 0, numCoarseQuads = 0; t <= lltF; t++, coarseOffset += numCoarseQuads) { 2617*0a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t*) p4estF->trees->array)[t]); 2618*0a96aa3bSJed Brown PetscInt numFineQuads = tree->quadrants.elem_count; 2619*0a96aa3bSJed Brown p4est_quadrant_t *coarseQuads = treeQuads[t - fltF]; 2620*0a96aa3bSJed Brown p4est_quadrant_t *fineQuads = (p4est_quadrant_t*) tree->quadrants.array; 2621*0a96aa3bSJed Brown PetscInt i, coarseCount = 0; 2622*0a96aa3bSJed Brown PetscInt offset = tree->quadrants_offset; 2623*0a96aa3bSJed Brown sc_array_t coarseQuadsArray; 2624*0a96aa3bSJed Brown 2625*0a96aa3bSJed Brown numCoarseQuads = treeQuadCounts[t - fltF]; 2626*0a96aa3bSJed Brown PetscStackCallP4est(sc_array_init_data,(&coarseQuadsArray,coarseQuads,sizeof(p4est_quadrant_t),(size_t) numCoarseQuads)); 2627*0a96aa3bSJed Brown for (i = 0; i < numFineQuads; i++) { 2628*0a96aa3bSJed Brown PetscInt c = i + offset; 2629*0a96aa3bSJed Brown p4est_quadrant_t *quad = &fineQuads[i]; 2630*0a96aa3bSJed Brown p4est_quadrant_t *quadCoarse = NULL; 2631*0a96aa3bSJed Brown ssize_t disjoint = -1; 2632*0a96aa3bSJed Brown 2633*0a96aa3bSJed Brown while (disjoint < 0 && coarseCount < numCoarseQuads) { 2634*0a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2635*0a96aa3bSJed Brown PetscStackCallP4estReturn(disjoint,p4est_quadrant_disjoint,(quadCoarse,quad)); 2636*0a96aa3bSJed Brown if (disjoint < 0) coarseCount++; 2637*0a96aa3bSJed Brown } 2638*0a96aa3bSJed Brown if (disjoint != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"did not find overlapping coarse quad"); 2639*0a96aa3bSJed Brown if (quadCoarse->level > quad->level || (quadCoarse->level == quad->level && !transferIdent)) { /* the "coarse" mesh is finer than the fine mesh at the point: continue */ 2640*0a96aa3bSJed Brown if (transferIdent) { /* find corners */ 2641*0a96aa3bSJed Brown PetscInt j = 0; 2642*0a96aa3bSJed Brown 2643*0a96aa3bSJed Brown do { 2644*0a96aa3bSJed Brown if (j < P4EST_CHILDREN) { 2645*0a96aa3bSJed Brown p4est_quadrant_t cornerQuad; 2646*0a96aa3bSJed Brown int equal; 2647*0a96aa3bSJed Brown 2648*0a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_corner_descendant,(quad,&cornerQuad,j,quadCoarse->level)); 2649*0a96aa3bSJed Brown PetscStackCallP4estReturn(equal,p4est_quadrant_is_equal,(&cornerQuad,quadCoarse)); 2650*0a96aa3bSJed Brown if (equal) { 2651*0a96aa3bSJed Brown PetscInt petscJ = P4estVertToPetscVert[j]; 2652*0a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + (P4EST_INSUL - P4EST_CHILDREN) + petscJ].index; 2653*0a96aa3bSJed Brown PetscSFNode q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + (P4EST_INSUL - P4EST_CHILDREN) + petscJ]; 2654*0a96aa3bSJed Brown 2655*0a96aa3bSJed Brown roots[p-pStartF] = q; 2656*0a96aa3bSJed Brown rootType[p-pStartF] = PETSC_MAX_INT; 2657*0a96aa3bSJed Brown cids[p-pStartF] = -1; 2658*0a96aa3bSJed Brown j++; 2659*0a96aa3bSJed Brown } 2660*0a96aa3bSJed Brown } 2661*0a96aa3bSJed Brown coarseCount++; 2662*0a96aa3bSJed Brown disjoint = 1; 2663*0a96aa3bSJed Brown if (coarseCount < numCoarseQuads) { 2664*0a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount]; 2665*0a96aa3bSJed Brown PetscStackCallP4estReturn(disjoint,p4est_quadrant_disjoint,(quadCoarse,quad)); 2666*0a96aa3bSJed Brown } 2667*0a96aa3bSJed Brown } while (!disjoint); 2668*0a96aa3bSJed Brown } 2669*0a96aa3bSJed Brown continue; 2670*0a96aa3bSJed Brown } 2671*0a96aa3bSJed Brown if (quadCoarse->level == quad->level) { /* same quad present in coarse and fine mesh */ 2672*0a96aa3bSJed Brown PetscInt j; 2673*0a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 2674*0a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + j].index; 2675*0a96aa3bSJed Brown 2676*0a96aa3bSJed Brown roots[p-pStartF] = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + j]; 2677*0a96aa3bSJed Brown rootType[p-pStartF] = PETSC_MAX_INT; /* unconditionally accept */ 2678*0a96aa3bSJed Brown cids[p-pStartF] = -1; 2679*0a96aa3bSJed Brown } 2680*0a96aa3bSJed Brown } else { 2681*0a96aa3bSJed Brown PetscInt levelDiff = quad->level - quadCoarse->level; 2682*0a96aa3bSJed Brown PetscInt proposedCids[P4EST_INSUL] = {0}; 2683*0a96aa3bSJed Brown 2684*0a96aa3bSJed Brown if (formCids) { 2685*0a96aa3bSJed Brown PetscInt cl; 2686*0a96aa3bSJed Brown PetscInt *pointClosure = NULL; 2687*0a96aa3bSJed Brown int cid; 2688*0a96aa3bSJed Brown 2689*0a96aa3bSJed Brown if (levelDiff > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Recursive child ids not implemented"); 2690*0a96aa3bSJed Brown PetscStackCallP4estReturn(cid,p4est_quadrant_child_id,(quad)); 2691*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(plexF,c + cLocalStartF,PETSC_TRUE,NULL,&pointClosure);CHKERRQ(ierr); 2692*0a96aa3bSJed Brown for (cl = 0; cl < P4EST_INSUL; cl++) { 2693*0a96aa3bSJed Brown PetscInt p = pointClosure[2 * cl]; 2694*0a96aa3bSJed Brown PetscInt point = childClosures[cid][2 * cl]; 2695*0a96aa3bSJed Brown PetscInt ornt = childClosures[cid][2 * cl + 1]; 2696*0a96aa3bSJed Brown PetscInt newcid = -1; 2697*0a96aa3bSJed Brown DMPolytopeType ct; 2698*0a96aa3bSJed Brown 2699*0a96aa3bSJed Brown if (rootType[p-pStartF] == PETSC_MAX_INT) continue; 2700*0a96aa3bSJed Brown ierr = DMPlexGetCellType(refTree, point, &ct);CHKERRQ(ierr); 2701*0a96aa3bSJed Brown ornt = DMPolytopeConvertNewOrientation_Internal(ct, ornt); 2702*0a96aa3bSJed Brown if (!cl) { 2703*0a96aa3bSJed Brown newcid = cid + 1; 2704*0a96aa3bSJed Brown } else { 2705*0a96aa3bSJed Brown PetscInt rcl, parent, parentOrnt = 0; 2706*0a96aa3bSJed Brown 2707*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(refTree,point,&parent,NULL);CHKERRQ(ierr); 2708*0a96aa3bSJed Brown if (parent == point) { 2709*0a96aa3bSJed Brown newcid = -1; 2710*0a96aa3bSJed Brown } else if (!parent) { /* in the root */ 2711*0a96aa3bSJed Brown newcid = point; 2712*0a96aa3bSJed Brown } else { 2713*0a96aa3bSJed Brown DMPolytopeType rct = DM_POLYTOPE_UNKNOWN; 2714*0a96aa3bSJed Brown 2715*0a96aa3bSJed Brown for (rcl = 1; rcl < P4EST_INSUL; rcl++) { 2716*0a96aa3bSJed Brown if (rootClosure[2 * rcl] == parent) { 2717*0a96aa3bSJed Brown ierr = DMPlexGetCellType(refTree, parent, &rct);CHKERRQ(ierr); 2718*0a96aa3bSJed Brown parentOrnt = DMPolytopeConvertNewOrientation_Internal(rct, rootClosure[2 * rcl + 1]); 2719*0a96aa3bSJed Brown break; 2720*0a96aa3bSJed Brown } 2721*0a96aa3bSJed Brown } 2722*0a96aa3bSJed Brown if (rcl >= P4EST_INSUL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Couldn't find parent in root closure"); 2723*0a96aa3bSJed Brown ierr = DMPlexReferenceTreeGetChildSymmetry(refTree,parent,parentOrnt,ornt,point,DMPolytopeConvertNewOrientation_Internal(rct, pointClosure[2 * rcl + 1]),NULL,&newcid);CHKERRQ(ierr); 2724*0a96aa3bSJed Brown } 2725*0a96aa3bSJed Brown } 2726*0a96aa3bSJed Brown if (newcid >= 0) { 2727*0a96aa3bSJed Brown 2728*0a96aa3bSJed Brown if (canonical) { 2729*0a96aa3bSJed Brown ierr = DMLabelGetValue(canonical,newcid,&newcid);CHKERRQ(ierr); 2730*0a96aa3bSJed Brown } 2731*0a96aa3bSJed Brown proposedCids[cl] = newcid; 2732*0a96aa3bSJed Brown } 2733*0a96aa3bSJed Brown } 2734*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(plexF,c + cLocalStartF,PETSC_TRUE,NULL,&pointClosure);CHKERRQ(ierr); 2735*0a96aa3bSJed Brown } 2736*0a96aa3bSJed Brown p4est_qcoord_t coarseBound[2][P4EST_DIM] = {{quadCoarse->x,quadCoarse->y, 2737*0a96aa3bSJed Brown #if defined(P4_TO_P8) 2738*0a96aa3bSJed Brown quadCoarse->z 2739*0a96aa3bSJed Brown #endif 2740*0a96aa3bSJed Brown },{0}}; 2741*0a96aa3bSJed Brown p4est_qcoord_t fineBound[2][P4EST_DIM] = {{quad->x,quad->y, 2742*0a96aa3bSJed Brown #if defined(P4_TO_P8) 2743*0a96aa3bSJed Brown quad->z 2744*0a96aa3bSJed Brown #endif 2745*0a96aa3bSJed Brown },{0}}; 2746*0a96aa3bSJed Brown PetscInt j; 2747*0a96aa3bSJed Brown for (j = 0; j < P4EST_DIM; j++) { /* get the coordinates of cell boundaries in each direction */ 2748*0a96aa3bSJed Brown coarseBound[1][j] = coarseBound[0][j] + P4EST_QUADRANT_LEN(quadCoarse->level); 2749*0a96aa3bSJed Brown fineBound[1][j] = fineBound[0][j] + P4EST_QUADRANT_LEN(quad->level); 2750*0a96aa3bSJed Brown } 2751*0a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) { 2752*0a96aa3bSJed Brown PetscInt l, p; 2753*0a96aa3bSJed Brown PetscSFNode q; 2754*0a96aa3bSJed Brown 2755*0a96aa3bSJed Brown p = closurePointsF[numClosureIndices * c + j].index; 2756*0a96aa3bSJed Brown if (rootType[p-pStartF] == PETSC_MAX_INT) continue; 2757*0a96aa3bSJed Brown if (j == 0) { /* volume: ancestor is volume */ 2758*0a96aa3bSJed Brown l = 0; 2759*0a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES) { /* facet */ 2760*0a96aa3bSJed Brown PetscInt face = PetscFaceToP4estFace[j - 1]; 2761*0a96aa3bSJed Brown PetscInt direction = face / 2; 2762*0a96aa3bSJed Brown PetscInt coarseFace = -1; 2763*0a96aa3bSJed Brown 2764*0a96aa3bSJed Brown if (coarseBound[face % 2][direction] == fineBound[face % 2][direction]) { 2765*0a96aa3bSJed Brown coarseFace = face; 2766*0a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 2767*0a96aa3bSJed Brown } else { 2768*0a96aa3bSJed Brown l = 0; 2769*0a96aa3bSJed Brown } 2770*0a96aa3bSJed Brown #if defined(P4_TO_P8) 2771*0a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES + P8EST_EDGES) { 2772*0a96aa3bSJed Brown PetscInt edge = PetscEdgeToP4estEdge[j - (1 + P4EST_FACES)]; 2773*0a96aa3bSJed Brown PetscInt direction = edge / 4; 2774*0a96aa3bSJed Brown PetscInt mod = edge % 4; 2775*0a96aa3bSJed Brown PetscInt coarseEdge = -1, coarseFace = -1; 2776*0a96aa3bSJed Brown PetscInt minDir = PetscMin((direction + 1) % 3,(direction + 2) % 3); 2777*0a96aa3bSJed Brown PetscInt maxDir = PetscMax((direction + 1) % 3,(direction + 2) % 3); 2778*0a96aa3bSJed Brown PetscBool dirTest[2]; 2779*0a96aa3bSJed Brown 2780*0a96aa3bSJed Brown dirTest[0] = (PetscBool) (coarseBound[mod % 2][minDir] == fineBound[mod % 2][minDir]); 2781*0a96aa3bSJed Brown dirTest[1] = (PetscBool) (coarseBound[mod / 2][maxDir] == fineBound[mod / 2][maxDir]); 2782*0a96aa3bSJed Brown 2783*0a96aa3bSJed Brown if (dirTest[0] && dirTest[1]) { /* fine edge falls on coarse edge */ 2784*0a96aa3bSJed Brown coarseEdge = edge; 2785*0a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 2786*0a96aa3bSJed Brown } else if (dirTest[0]) { /* fine edge falls on a coarse face in the minDir direction */ 2787*0a96aa3bSJed Brown coarseFace = 2 * minDir + (mod % 2); 2788*0a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 2789*0a96aa3bSJed Brown } else if (dirTest[1]) { /* fine edge falls on a coarse face in the maxDir direction */ 2790*0a96aa3bSJed Brown coarseFace = 2 * maxDir + (mod / 2); 2791*0a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 2792*0a96aa3bSJed Brown } else { 2793*0a96aa3bSJed Brown l = 0; 2794*0a96aa3bSJed Brown } 2795*0a96aa3bSJed Brown #endif 2796*0a96aa3bSJed Brown } else { 2797*0a96aa3bSJed Brown PetscInt vertex = PetscVertToP4estVert[P4EST_CHILDREN - (P4EST_INSUL - j)]; 2798*0a96aa3bSJed Brown PetscBool dirTest[P4EST_DIM]; 2799*0a96aa3bSJed Brown PetscInt m; 2800*0a96aa3bSJed Brown PetscInt numMatch = 0; 2801*0a96aa3bSJed Brown PetscInt coarseVertex = -1, coarseFace = -1; 2802*0a96aa3bSJed Brown #if defined(P4_TO_P8) 2803*0a96aa3bSJed Brown PetscInt coarseEdge = -1; 2804*0a96aa3bSJed Brown #endif 2805*0a96aa3bSJed Brown 2806*0a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 2807*0a96aa3bSJed Brown dirTest[m] = (PetscBool) (coarseBound[(vertex >> m) & 1][m] == fineBound[(vertex >> m) & 1][m]); 2808*0a96aa3bSJed Brown if (dirTest[m]) numMatch++; 2809*0a96aa3bSJed Brown } 2810*0a96aa3bSJed Brown if (numMatch == P4EST_DIM) { /* vertex on vertex */ 2811*0a96aa3bSJed Brown coarseVertex = vertex; 2812*0a96aa3bSJed Brown l = P4EST_INSUL - (P4EST_CHILDREN - P4estVertToPetscVert[coarseVertex]); 2813*0a96aa3bSJed Brown } else if (numMatch == 1) { /* vertex on face */ 2814*0a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 2815*0a96aa3bSJed Brown if (dirTest[m]) { 2816*0a96aa3bSJed Brown coarseFace = 2 * m + ((vertex >> m) & 1); 2817*0a96aa3bSJed Brown break; 2818*0a96aa3bSJed Brown } 2819*0a96aa3bSJed Brown } 2820*0a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace]; 2821*0a96aa3bSJed Brown #if defined(P4_TO_P8) 2822*0a96aa3bSJed Brown } else if (numMatch == 2) { /* vertex on edge */ 2823*0a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) { 2824*0a96aa3bSJed Brown if (!dirTest[m]) { 2825*0a96aa3bSJed Brown PetscInt otherDir1 = (m + 1) % 3; 2826*0a96aa3bSJed Brown PetscInt otherDir2 = (m + 2) % 3; 2827*0a96aa3bSJed Brown PetscInt minDir = PetscMin(otherDir1,otherDir2); 2828*0a96aa3bSJed Brown PetscInt maxDir = PetscMax(otherDir1,otherDir2); 2829*0a96aa3bSJed Brown 2830*0a96aa3bSJed Brown coarseEdge = m * 4 + 2 * ((vertex >> maxDir) & 1) + ((vertex >> minDir) & 1); 2831*0a96aa3bSJed Brown break; 2832*0a96aa3bSJed Brown } 2833*0a96aa3bSJed Brown } 2834*0a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge]; 2835*0a96aa3bSJed Brown #endif 2836*0a96aa3bSJed Brown } else { /* volume */ 2837*0a96aa3bSJed Brown l = 0; 2838*0a96aa3bSJed Brown } 2839*0a96aa3bSJed Brown } 2840*0a96aa3bSJed Brown q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + l]; 2841*0a96aa3bSJed Brown if (l > rootType[p-pStartF]) { 2842*0a96aa3bSJed Brown if (l >= P4EST_INSUL - P4EST_CHILDREN) { /* vertex on vertex: unconditional acceptance */ 2843*0a96aa3bSJed Brown if (transferIdent) { 2844*0a96aa3bSJed Brown roots[p-pStartF] = q; 2845*0a96aa3bSJed Brown rootType[p-pStartF] = PETSC_MAX_INT; 2846*0a96aa3bSJed Brown if (formCids) cids[p-pStartF] = -1; 2847*0a96aa3bSJed Brown } 2848*0a96aa3bSJed Brown } else { 2849*0a96aa3bSJed Brown PetscInt k, thisp = p, limit; 2850*0a96aa3bSJed Brown 2851*0a96aa3bSJed Brown roots[p-pStartF] = q; 2852*0a96aa3bSJed Brown rootType[p-pStartF] = l; 2853*0a96aa3bSJed Brown if (formCids) cids[p - pStartF] = proposedCids[j]; 2854*0a96aa3bSJed Brown limit = transferIdent ? levelDiff : (levelDiff - 1); 2855*0a96aa3bSJed Brown for (k = 0; k < limit; k++) { 2856*0a96aa3bSJed Brown PetscInt parent; 2857*0a96aa3bSJed Brown 2858*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(plexF,thisp,&parent,NULL);CHKERRQ(ierr); 2859*0a96aa3bSJed Brown if (parent == thisp) break; 2860*0a96aa3bSJed Brown 2861*0a96aa3bSJed Brown roots[parent-pStartF] = q; 2862*0a96aa3bSJed Brown rootType[parent-pStartF] = PETSC_MAX_INT; 2863*0a96aa3bSJed Brown if (formCids) cids[parent-pStartF] = -1; 2864*0a96aa3bSJed Brown thisp = parent; 2865*0a96aa3bSJed Brown } 2866*0a96aa3bSJed Brown } 2867*0a96aa3bSJed Brown } 2868*0a96aa3bSJed Brown } 2869*0a96aa3bSJed Brown } 2870*0a96aa3bSJed Brown } 2871*0a96aa3bSJed Brown } 2872*0a96aa3bSJed Brown 2873*0a96aa3bSJed 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 */ 2874*0a96aa3bSJed Brown if (size > 1) { 2875*0a96aa3bSJed Brown PetscInt *rootTypeCopy, p; 2876*0a96aa3bSJed Brown 2877*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndF-pStartF,&rootTypeCopy);CHKERRQ(ierr); 2878*0a96aa3bSJed Brown ierr = PetscArraycpy(rootTypeCopy,rootType,pEndF-pStartF);CHKERRQ(ierr); 2879*0a96aa3bSJed Brown ierr = PetscSFReduceBegin(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPIU_MAX);CHKERRQ(ierr); 2880*0a96aa3bSJed Brown ierr = PetscSFReduceEnd(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPIU_MAX);CHKERRQ(ierr); 2881*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPI_REPLACE);CHKERRQ(ierr); 2882*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(pointSF,MPIU_INT,rootTypeCopy,rootTypeCopy,MPI_REPLACE);CHKERRQ(ierr); 2883*0a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 2884*0a96aa3bSJed 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 */ 2885*0a96aa3bSJed Brown roots[p-pStartF].rank = -1; 2886*0a96aa3bSJed Brown roots[p-pStartF].index = -1; 2887*0a96aa3bSJed Brown } 2888*0a96aa3bSJed Brown if (formCids && rootTypeCopy[p-pStartF] == PETSC_MAX_INT) { 2889*0a96aa3bSJed Brown cids[p-pStartF] = -1; /* we have found an antecedent that is the same: no child id */ 2890*0a96aa3bSJed Brown } 2891*0a96aa3bSJed Brown } 2892*0a96aa3bSJed Brown ierr = PetscFree(rootTypeCopy);CHKERRQ(ierr); 2893*0a96aa3bSJed Brown ierr = PetscSFReduceBegin(pointSF,nodeType,roots,roots,sfNodeReduce);CHKERRQ(ierr); 2894*0a96aa3bSJed Brown ierr = PetscSFReduceEnd(pointSF,nodeType,roots,roots,sfNodeReduce);CHKERRQ(ierr); 2895*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(pointSF,nodeType,roots,roots,MPI_REPLACE);CHKERRQ(ierr); 2896*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(pointSF,nodeType,roots,roots,MPI_REPLACE);CHKERRQ(ierr); 2897*0a96aa3bSJed Brown } 2898*0a96aa3bSJed Brown ierr = PetscFree(rootType);CHKERRQ(ierr); 2899*0a96aa3bSJed Brown 2900*0a96aa3bSJed Brown { 2901*0a96aa3bSJed Brown PetscInt numRoots; 2902*0a96aa3bSJed Brown PetscInt numLeaves; 2903*0a96aa3bSJed Brown PetscInt *leaves; 2904*0a96aa3bSJed Brown PetscSFNode *iremote; 2905*0a96aa3bSJed Brown /* count leaves */ 2906*0a96aa3bSJed Brown 2907*0a96aa3bSJed Brown numRoots = pEndC - pStartC; 2908*0a96aa3bSJed Brown 2909*0a96aa3bSJed Brown numLeaves = 0; 2910*0a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 2911*0a96aa3bSJed Brown if (roots[p-pStartF].index >= 0) numLeaves++; 2912*0a96aa3bSJed Brown } 2913*0a96aa3bSJed Brown ierr = PetscMalloc1(numLeaves,&leaves);CHKERRQ(ierr); 2914*0a96aa3bSJed Brown ierr = PetscMalloc1(numLeaves,&iremote);CHKERRQ(ierr); 2915*0a96aa3bSJed Brown numLeaves = 0; 2916*0a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) { 2917*0a96aa3bSJed Brown if (roots[p-pStartF].index >= 0) { 2918*0a96aa3bSJed Brown leaves[numLeaves] = p-pStartF; 2919*0a96aa3bSJed Brown iremote[numLeaves] = roots[p-pStartF]; 2920*0a96aa3bSJed Brown numLeaves++; 2921*0a96aa3bSJed Brown } 2922*0a96aa3bSJed Brown } 2923*0a96aa3bSJed Brown ierr = PetscFree(roots);CHKERRQ(ierr); 2924*0a96aa3bSJed Brown ierr = PetscSFCreate(comm,sf);CHKERRQ(ierr); 2925*0a96aa3bSJed Brown if (numLeaves == (pEndF-pStartF)) { 2926*0a96aa3bSJed Brown ierr = PetscFree(leaves);CHKERRQ(ierr); 2927*0a96aa3bSJed Brown ierr = PetscSFSetGraph(*sf,numRoots,numLeaves,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 2928*0a96aa3bSJed Brown } else { 2929*0a96aa3bSJed Brown ierr = PetscSFSetGraph(*sf,numRoots,numLeaves,leaves,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 2930*0a96aa3bSJed Brown } 2931*0a96aa3bSJed Brown } 2932*0a96aa3bSJed Brown if (formCids) { 2933*0a96aa3bSJed Brown PetscSF pointSF; 2934*0a96aa3bSJed Brown PetscInt child; 2935*0a96aa3bSJed Brown 2936*0a96aa3bSJed Brown ierr = DMPlexGetReferenceTree(plexF,&refTree);CHKERRQ(ierr); 2937*0a96aa3bSJed Brown ierr = DMGetPointSF(plexF,&pointSF);CHKERRQ(ierr); 2938*0a96aa3bSJed Brown ierr = PetscSFReduceBegin(pointSF,MPIU_INT,cids,cids,MPIU_MAX);CHKERRQ(ierr); 2939*0a96aa3bSJed Brown ierr = PetscSFReduceEnd(pointSF,MPIU_INT,cids,cids,MPIU_MAX);CHKERRQ(ierr); 2940*0a96aa3bSJed Brown if (childIds) *childIds = cids; 2941*0a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { 2942*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(refTree,child+1,PETSC_TRUE,NULL,&childClosures[child]);CHKERRQ(ierr); 2943*0a96aa3bSJed Brown } 2944*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(refTree,0,PETSC_TRUE,NULL,&rootClosure);CHKERRQ(ierr); 2945*0a96aa3bSJed Brown } 2946*0a96aa3bSJed Brown } 2947*0a96aa3bSJed Brown if (saveInCoarse) { /* cache results */ 2948*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)*sf);CHKERRQ(ierr); 2949*0a96aa3bSJed Brown pforestC->pointSelfToAdaptSF = *sf; 2950*0a96aa3bSJed Brown if (!childIds) { 2951*0a96aa3bSJed Brown pforestC->pointSelfToAdaptCids = cids; 2952*0a96aa3bSJed Brown } else { 2953*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndF-pStartF,&pforestC->pointSelfToAdaptCids);CHKERRQ(ierr); 2954*0a96aa3bSJed Brown ierr = PetscArraycpy(pforestC->pointSelfToAdaptCids,cids,pEndF-pStartF);CHKERRQ(ierr); 2955*0a96aa3bSJed Brown } 2956*0a96aa3bSJed Brown } else if (saveInFine) { 2957*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)*sf);CHKERRQ(ierr); 2958*0a96aa3bSJed Brown pforestF->pointAdaptToSelfSF = *sf; 2959*0a96aa3bSJed Brown if (!childIds) { 2960*0a96aa3bSJed Brown pforestF->pointAdaptToSelfCids = cids; 2961*0a96aa3bSJed Brown } else { 2962*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndF-pStartF,&pforestF->pointAdaptToSelfCids);CHKERRQ(ierr); 2963*0a96aa3bSJed Brown ierr = PetscArraycpy(pforestF->pointAdaptToSelfCids,cids,pEndF-pStartF);CHKERRQ(ierr); 2964*0a96aa3bSJed Brown } 2965*0a96aa3bSJed Brown } 2966*0a96aa3bSJed Brown ierr = PetscFree2(treeQuads,treeQuadCounts);CHKERRQ(ierr); 2967*0a96aa3bSJed Brown ierr = PetscFree(coverQuads);CHKERRQ(ierr); 2968*0a96aa3bSJed Brown ierr = PetscFree(closurePointsC);CHKERRQ(ierr); 2969*0a96aa3bSJed Brown ierr = PetscFree(closurePointsF);CHKERRQ(ierr); 2970*0a96aa3bSJed Brown ierr = MPI_Type_free(&nodeClosureType);CHKERRMPI(ierr); 2971*0a96aa3bSJed Brown ierr = MPI_Op_free(&sfNodeReduce);CHKERRMPI(ierr); 2972*0a96aa3bSJed Brown ierr = MPI_Type_free(&nodeType);CHKERRMPI(ierr); 2973*0a96aa3bSJed Brown PetscFunctionReturn(0); 2974*0a96aa3bSJed Brown } 2975*0a96aa3bSJed Brown 2976*0a96aa3bSJed Brown /* children are sf leaves of parents */ 2977*0a96aa3bSJed Brown static PetscErrorCode DMPforestGetTransferSF_Internal(DM coarse, DM fine, const PetscInt dofPerDim[], PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[]) 2978*0a96aa3bSJed Brown { 2979*0a96aa3bSJed Brown MPI_Comm comm; 2980*0a96aa3bSJed Brown PetscMPIInt rank, size; 2981*0a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF; 2982*0a96aa3bSJed Brown PetscInt numClosureIndices; 2983*0a96aa3bSJed Brown DM plexC, plexF; 2984*0a96aa3bSJed Brown PetscInt pStartC, pEndC, pStartF, pEndF; 2985*0a96aa3bSJed Brown PetscSF pointTransferSF; 2986*0a96aa3bSJed Brown PetscBool allOnes = PETSC_TRUE; 2987*0a96aa3bSJed Brown PetscErrorCode ierr; 2988*0a96aa3bSJed Brown 2989*0a96aa3bSJed Brown PetscFunctionBegin; 2990*0a96aa3bSJed Brown pforestC = (DM_Forest_pforest*) ((DM_Forest*) coarse->data)->data; 2991*0a96aa3bSJed Brown pforestF = (DM_Forest_pforest*) ((DM_Forest*) fine->data)->data; 2992*0a96aa3bSJed Brown if (pforestC->topo != pforestF->topo) SETERRQ(PetscObjectComm((PetscObject)coarse),PETSC_ERR_ARG_INCOMP,"DM's must have the same base DM"); 2993*0a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse); 2994*0a96aa3bSJed Brown ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 2995*0a96aa3bSJed Brown ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 2996*0a96aa3bSJed Brown 2997*0a96aa3bSJed Brown /* count the number of closure points that have dofs and create a list */ 2998*0a96aa3bSJed Brown numClosureIndices = 0; 2999*0a96aa3bSJed Brown if (dofPerDim[P4EST_DIM] > 0) numClosureIndices += 1; 3000*0a96aa3bSJed Brown if (dofPerDim[P4EST_DIM - 1] > 0) numClosureIndices += P4EST_FACES; 3001*0a96aa3bSJed Brown #if defined(P4_TO_P8) 3002*0a96aa3bSJed Brown if (dofPerDim[P4EST_DIM - 2] > 0) numClosureIndices += P8EST_EDGES; 3003*0a96aa3bSJed Brown #endif 3004*0a96aa3bSJed Brown if (dofPerDim[0] > 0) numClosureIndices += P4EST_CHILDREN; 3005*0a96aa3bSJed Brown { 3006*0a96aa3bSJed Brown PetscInt i; 3007*0a96aa3bSJed Brown for (i = 0; i <= P4EST_DIM; i++) { 3008*0a96aa3bSJed Brown if (dofPerDim[i] != 1) { 3009*0a96aa3bSJed Brown allOnes = PETSC_FALSE; 3010*0a96aa3bSJed Brown break; 3011*0a96aa3bSJed Brown } 3012*0a96aa3bSJed Brown } 3013*0a96aa3bSJed Brown } 3014*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Point(coarse,fine,&pointTransferSF,transferIdent,childIds);CHKERRQ(ierr); 3015*0a96aa3bSJed Brown if (allOnes) { 3016*0a96aa3bSJed Brown *sf = pointTransferSF; 3017*0a96aa3bSJed Brown PetscFunctionReturn(0); 3018*0a96aa3bSJed Brown } 3019*0a96aa3bSJed Brown 3020*0a96aa3bSJed Brown ierr = DMPforestGetPlex(fine,&plexF);CHKERRQ(ierr); 3021*0a96aa3bSJed Brown ierr = DMPlexGetChart(plexF,&pStartF,&pEndF);CHKERRQ(ierr); 3022*0a96aa3bSJed Brown ierr = DMPforestGetPlex(coarse,&plexC);CHKERRQ(ierr); 3023*0a96aa3bSJed Brown ierr = DMPlexGetChart(plexC,&pStartC,&pEndC);CHKERRQ(ierr); 3024*0a96aa3bSJed Brown { 3025*0a96aa3bSJed Brown PetscInt numRoots; 3026*0a96aa3bSJed Brown PetscInt numLeaves; 3027*0a96aa3bSJed Brown const PetscInt *leaves; 3028*0a96aa3bSJed Brown const PetscSFNode *iremote; 3029*0a96aa3bSJed Brown PetscInt d; 3030*0a96aa3bSJed Brown PetscSection leafSection, rootSection; 3031*0a96aa3bSJed Brown /* count leaves */ 3032*0a96aa3bSJed Brown 3033*0a96aa3bSJed Brown ierr = PetscSFGetGraph(pointTransferSF,&numRoots,&numLeaves,&leaves,&iremote);CHKERRQ(ierr); 3034*0a96aa3bSJed Brown ierr = PetscSectionCreate(PETSC_COMM_SELF,&rootSection);CHKERRQ(ierr); 3035*0a96aa3bSJed Brown ierr = PetscSectionCreate(PETSC_COMM_SELF,&leafSection);CHKERRQ(ierr); 3036*0a96aa3bSJed Brown ierr = PetscSectionSetChart(rootSection,pStartC,pEndC);CHKERRQ(ierr); 3037*0a96aa3bSJed Brown ierr = PetscSectionSetChart(leafSection,pStartF,pEndF);CHKERRQ(ierr); 3038*0a96aa3bSJed Brown 3039*0a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 3040*0a96aa3bSJed Brown PetscInt startC, endC, e; 3041*0a96aa3bSJed Brown 3042*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(plexC,P4EST_DIM-d,&startC,&endC);CHKERRQ(ierr); 3043*0a96aa3bSJed Brown for (e = startC; e < endC; e++) { 3044*0a96aa3bSJed Brown ierr = PetscSectionSetDof(rootSection,e,dofPerDim[d]);CHKERRQ(ierr); 3045*0a96aa3bSJed Brown } 3046*0a96aa3bSJed Brown } 3047*0a96aa3bSJed Brown 3048*0a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) { 3049*0a96aa3bSJed Brown PetscInt startF, endF, e; 3050*0a96aa3bSJed Brown 3051*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(plexF,P4EST_DIM-d,&startF,&endF);CHKERRQ(ierr); 3052*0a96aa3bSJed Brown for (e = startF; e < endF; e++) { 3053*0a96aa3bSJed Brown ierr = PetscSectionSetDof(leafSection,e,dofPerDim[d]);CHKERRQ(ierr); 3054*0a96aa3bSJed Brown } 3055*0a96aa3bSJed Brown } 3056*0a96aa3bSJed Brown 3057*0a96aa3bSJed Brown ierr = PetscSectionSetUp(rootSection);CHKERRQ(ierr); 3058*0a96aa3bSJed Brown ierr = PetscSectionSetUp(leafSection);CHKERRQ(ierr); 3059*0a96aa3bSJed Brown { 3060*0a96aa3bSJed Brown PetscInt nroots, nleaves; 3061*0a96aa3bSJed Brown PetscInt *mine, i, p; 3062*0a96aa3bSJed Brown PetscInt *offsets, *offsetsRoot; 3063*0a96aa3bSJed Brown PetscSFNode *remote; 3064*0a96aa3bSJed Brown 3065*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndF-pStartF,&offsets);CHKERRQ(ierr); 3066*0a96aa3bSJed Brown ierr = PetscMalloc1(pEndC-pStartC,&offsetsRoot);CHKERRQ(ierr); 3067*0a96aa3bSJed Brown for (p = pStartC; p < pEndC; p++) { 3068*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(rootSection,p,&offsetsRoot[p-pStartC]);CHKERRQ(ierr); 3069*0a96aa3bSJed Brown } 3070*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(pointTransferSF,MPIU_INT,offsetsRoot,offsets,MPI_REPLACE);CHKERRQ(ierr); 3071*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(pointTransferSF,MPIU_INT,offsetsRoot,offsets,MPI_REPLACE);CHKERRQ(ierr); 3072*0a96aa3bSJed Brown ierr = PetscSectionGetStorageSize(rootSection,&nroots);CHKERRQ(ierr); 3073*0a96aa3bSJed Brown nleaves = 0; 3074*0a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 3075*0a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 3076*0a96aa3bSJed Brown PetscInt dof; 3077*0a96aa3bSJed Brown 3078*0a96aa3bSJed Brown ierr = PetscSectionGetDof(leafSection,leaf,&dof);CHKERRQ(ierr); 3079*0a96aa3bSJed Brown nleaves += dof; 3080*0a96aa3bSJed Brown } 3081*0a96aa3bSJed Brown ierr = PetscMalloc1(nleaves,&mine);CHKERRQ(ierr); 3082*0a96aa3bSJed Brown ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr); 3083*0a96aa3bSJed Brown nleaves = 0; 3084*0a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) { 3085*0a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i; 3086*0a96aa3bSJed Brown PetscInt dof; 3087*0a96aa3bSJed Brown PetscInt off, j; 3088*0a96aa3bSJed Brown 3089*0a96aa3bSJed Brown ierr = PetscSectionGetDof(leafSection,leaf,&dof);CHKERRQ(ierr); 3090*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(leafSection,leaf,&off);CHKERRQ(ierr); 3091*0a96aa3bSJed Brown for (j = 0; j < dof; j++) { 3092*0a96aa3bSJed Brown remote[nleaves].rank = iremote[i].rank; 3093*0a96aa3bSJed Brown remote[nleaves].index = offsets[leaf] + j; 3094*0a96aa3bSJed Brown mine[nleaves++] = off + j; 3095*0a96aa3bSJed Brown } 3096*0a96aa3bSJed Brown } 3097*0a96aa3bSJed Brown ierr = PetscFree(offsetsRoot);CHKERRQ(ierr); 3098*0a96aa3bSJed Brown ierr = PetscFree(offsets);CHKERRQ(ierr); 3099*0a96aa3bSJed Brown ierr = PetscSFCreate(comm,sf);CHKERRQ(ierr); 3100*0a96aa3bSJed Brown ierr = PetscSFSetGraph(*sf,nroots,nleaves,mine,PETSC_OWN_POINTER,remote,PETSC_OWN_POINTER);CHKERRQ(ierr); 3101*0a96aa3bSJed Brown } 3102*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&leafSection);CHKERRQ(ierr); 3103*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&rootSection);CHKERRQ(ierr); 3104*0a96aa3bSJed Brown ierr = PetscSFDestroy(&pointTransferSF);CHKERRQ(ierr); 3105*0a96aa3bSJed Brown } 3106*0a96aa3bSJed Brown PetscFunctionReturn(0); 3107*0a96aa3bSJed Brown } 3108*0a96aa3bSJed Brown 3109*0a96aa3bSJed Brown static PetscErrorCode DMPforestGetTransferSF(DM dmA, DM dmB, const PetscInt dofPerDim[], PetscSF *sfAtoB, PetscSF *sfBtoA) 3110*0a96aa3bSJed Brown { 3111*0a96aa3bSJed Brown DM adaptA, adaptB; 3112*0a96aa3bSJed Brown DMAdaptFlag purpose; 3113*0a96aa3bSJed Brown PetscErrorCode ierr; 3114*0a96aa3bSJed Brown 3115*0a96aa3bSJed Brown PetscFunctionBegin; 3116*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(dmA,&adaptA);CHKERRQ(ierr); 3117*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(dmB,&adaptB);CHKERRQ(ierr); 3118*0a96aa3bSJed Brown /* it is more efficient when the coarser mesh is the first argument: reorder if we know one is coarser than the other */ 3119*0a96aa3bSJed Brown if (adaptA && adaptA->data == dmB->data) { /* dmA was adapted from dmB */ 3120*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityPurpose(dmA,&purpose);CHKERRQ(ierr); 3121*0a96aa3bSJed Brown if (purpose == DM_ADAPT_REFINE) { 3122*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB);CHKERRQ(ierr); 3123*0a96aa3bSJed Brown PetscFunctionReturn(0); 3124*0a96aa3bSJed Brown } 3125*0a96aa3bSJed Brown } else if (adaptB && adaptB->data == dmA->data) { /* dmB was adapted from dmA */ 3126*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityPurpose(dmB,&purpose);CHKERRQ(ierr); 3127*0a96aa3bSJed Brown if (purpose == DM_ADAPT_COARSEN) { 3128*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB);CHKERRQ(ierr); 3129*0a96aa3bSJed Brown PetscFunctionReturn(0); 3130*0a96aa3bSJed Brown } 3131*0a96aa3bSJed Brown } 3132*0a96aa3bSJed Brown if (sfAtoB) { 3133*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmA,dmB,dofPerDim,sfAtoB,PETSC_TRUE,NULL);CHKERRQ(ierr); 3134*0a96aa3bSJed Brown } 3135*0a96aa3bSJed Brown if (sfBtoA) { 3136*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmB,dmA,dofPerDim,sfBtoA,(PetscBool) (sfAtoB == NULL),NULL);CHKERRQ(ierr); 3137*0a96aa3bSJed Brown } 3138*0a96aa3bSJed Brown PetscFunctionReturn(0); 3139*0a96aa3bSJed Brown } 3140*0a96aa3bSJed Brown 3141*0a96aa3bSJed Brown static PetscErrorCode DMPforestLabelsInitialize(DM dm, DM plex) 3142*0a96aa3bSJed Brown { 3143*0a96aa3bSJed Brown DM_Forest *forest = (DM_Forest*) dm->data; 3144*0a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) forest->data; 3145*0a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, cStart, cEnd, fStart, fEnd, eStart, eEnd, vStart, vEnd; 3146*0a96aa3bSJed Brown PetscInt cStartBase, cEndBase, fStartBase, fEndBase, vStartBase, vEndBase, eStartBase, eEndBase; 3147*0a96aa3bSJed Brown PetscInt pStart, pEnd, pStartBase, pEndBase, p; 3148*0a96aa3bSJed Brown DM base; 3149*0a96aa3bSJed Brown PetscInt *star = NULL, starSize; 3150*0a96aa3bSJed Brown DMLabelLink next = dm->labels; 3151*0a96aa3bSJed Brown PetscInt guess = 0; 3152*0a96aa3bSJed Brown p4est_topidx_t num_trees = pforest->topo->conn->num_trees; 3153*0a96aa3bSJed Brown PetscErrorCode ierr; 3154*0a96aa3bSJed Brown 3155*0a96aa3bSJed Brown PetscFunctionBegin; 3156*0a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 3157*0a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 3158*0a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 3159*0a96aa3bSJed Brown ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr); 3160*0a96aa3bSJed Brown if (!base) { 3161*0a96aa3bSJed Brown if (pforest->ghostName) { /* insert a label to make the boundaries, with stratum values denoting which face of the element touches the boundary */ 3162*0a96aa3bSJed Brown p4est_connectivity_t *conn = pforest->topo->conn; 3163*0a96aa3bSJed Brown p4est_t *p4est = pforest->forest; 3164*0a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t*) p4est->trees->array; 3165*0a96aa3bSJed Brown p4est_topidx_t t, flt = p4est->first_local_tree; 3166*0a96aa3bSJed Brown p4est_topidx_t llt = pforest->forest->last_local_tree; 3167*0a96aa3bSJed Brown DMLabel ghostLabel; 3168*0a96aa3bSJed Brown PetscInt c; 3169*0a96aa3bSJed Brown 3170*0a96aa3bSJed Brown ierr = DMCreateLabel(plex,pforest->ghostName);CHKERRQ(ierr); 3171*0a96aa3bSJed Brown ierr = DMGetLabel(plex,pforest->ghostName,&ghostLabel);CHKERRQ(ierr); 3172*0a96aa3bSJed Brown for (c = cLocalStart, t = flt; t <= llt; t++) { 3173*0a96aa3bSJed Brown p4est_tree_t *tree = &trees[t]; 3174*0a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t*) tree->quadrants.array; 3175*0a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 3176*0a96aa3bSJed Brown PetscInt q; 3177*0a96aa3bSJed Brown 3178*0a96aa3bSJed Brown for (q = 0; q < numQuads; q++, c++) { 3179*0a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[q]; 3180*0a96aa3bSJed Brown PetscInt f; 3181*0a96aa3bSJed Brown 3182*0a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++) { 3183*0a96aa3bSJed Brown p4est_quadrant_t neigh; 3184*0a96aa3bSJed Brown int isOutside; 3185*0a96aa3bSJed Brown 3186*0a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_face_neighbor,(quad,f,&neigh)); 3187*0a96aa3bSJed Brown PetscStackCallP4estReturn(isOutside,p4est_quadrant_is_outside_face,(&neigh)); 3188*0a96aa3bSJed Brown if (isOutside) { 3189*0a96aa3bSJed Brown p4est_topidx_t nt; 3190*0a96aa3bSJed Brown PetscInt nf; 3191*0a96aa3bSJed Brown 3192*0a96aa3bSJed Brown nt = conn->tree_to_tree[t * P4EST_FACES + f]; 3193*0a96aa3bSJed Brown nf = (PetscInt) conn->tree_to_face[t * P4EST_FACES + f]; 3194*0a96aa3bSJed Brown nf = nf % P4EST_FACES; 3195*0a96aa3bSJed Brown if (nt == t && nf == f) { 3196*0a96aa3bSJed Brown PetscInt plexF = P4estFaceToPetscFace[f]; 3197*0a96aa3bSJed Brown const PetscInt *cone; 3198*0a96aa3bSJed Brown 3199*0a96aa3bSJed Brown ierr = DMPlexGetCone(plex,c,&cone);CHKERRQ(ierr); 3200*0a96aa3bSJed Brown ierr = DMLabelSetValue(ghostLabel,cone[plexF],plexF+1);CHKERRQ(ierr); 3201*0a96aa3bSJed Brown } 3202*0a96aa3bSJed Brown } 3203*0a96aa3bSJed Brown } 3204*0a96aa3bSJed Brown } 3205*0a96aa3bSJed Brown } 3206*0a96aa3bSJed Brown } 3207*0a96aa3bSJed Brown PetscFunctionReturn(0); 3208*0a96aa3bSJed Brown } 3209*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(base,0,&cStartBase,&cEndBase);CHKERRQ(ierr); 3210*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(base,1,&fStartBase,&fEndBase);CHKERRQ(ierr); 3211*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(base,P4EST_DIM-1,&eStartBase,&eEndBase);CHKERRQ(ierr); 3212*0a96aa3bSJed Brown ierr = DMPlexGetDepthStratum(base,0,&vStartBase,&vEndBase);CHKERRQ(ierr); 3213*0a96aa3bSJed Brown 3214*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(plex,0,&cStart,&cEnd);CHKERRQ(ierr); 3215*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(plex,1,&fStart,&fEnd);CHKERRQ(ierr); 3216*0a96aa3bSJed Brown ierr = DMPlexGetSimplexOrBoxCells(plex,P4EST_DIM-1,&eStart,&eEnd);CHKERRQ(ierr); 3217*0a96aa3bSJed Brown ierr = DMPlexGetDepthStratum(plex,0,&vStart,&vEnd);CHKERRQ(ierr); 3218*0a96aa3bSJed Brown 3219*0a96aa3bSJed Brown ierr = DMPlexGetChart(plex,&pStart,&pEnd);CHKERRQ(ierr); 3220*0a96aa3bSJed Brown ierr = DMPlexGetChart(base,&pStartBase,&pEndBase);CHKERRQ(ierr); 3221*0a96aa3bSJed Brown /* go through the mesh: use star to find a quadrant that borders a point. Use the closure to determine the 3222*0a96aa3bSJed Brown * orientation of the quadrant relative to that point. Use that to relate the point to the numbering in the base 3223*0a96aa3bSJed Brown * mesh, and extract a label value (since the base mesh is redundantly distributed, can be found locally). */ 3224*0a96aa3bSJed Brown while (next) { 3225*0a96aa3bSJed Brown DMLabel baseLabel; 3226*0a96aa3bSJed Brown DMLabel label = next->label; 3227*0a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK, isSpmap; 3228*0a96aa3bSJed Brown const char *name; 3229*0a96aa3bSJed Brown 3230*0a96aa3bSJed Brown ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr); 3231*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"depth",&isDepth);CHKERRQ(ierr); 3232*0a96aa3bSJed Brown if (isDepth) { 3233*0a96aa3bSJed Brown next = next->next; 3234*0a96aa3bSJed Brown continue; 3235*0a96aa3bSJed Brown } 3236*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"celltype",&isCellType);CHKERRQ(ierr); 3237*0a96aa3bSJed Brown if (isCellType) { 3238*0a96aa3bSJed Brown next = next->next; 3239*0a96aa3bSJed Brown continue; 3240*0a96aa3bSJed Brown } 3241*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"ghost",&isGhost);CHKERRQ(ierr); 3242*0a96aa3bSJed Brown if (isGhost) { 3243*0a96aa3bSJed Brown next = next->next; 3244*0a96aa3bSJed Brown continue; 3245*0a96aa3bSJed Brown } 3246*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"vtk",&isVTK);CHKERRQ(ierr); 3247*0a96aa3bSJed Brown if (isVTK) { 3248*0a96aa3bSJed Brown next = next->next; 3249*0a96aa3bSJed Brown continue; 3250*0a96aa3bSJed Brown } 3251*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"_forest_base_subpoint_map",&isSpmap);CHKERRQ(ierr); 3252*0a96aa3bSJed Brown if (!isSpmap) { 3253*0a96aa3bSJed Brown ierr = DMGetLabel(base,name,&baseLabel);CHKERRQ(ierr); 3254*0a96aa3bSJed Brown if (!baseLabel) { 3255*0a96aa3bSJed Brown next = next->next; 3256*0a96aa3bSJed Brown continue; 3257*0a96aa3bSJed Brown } 3258*0a96aa3bSJed Brown ierr = DMLabelCreateIndex(baseLabel,pStartBase,pEndBase);CHKERRQ(ierr); 3259*0a96aa3bSJed Brown } else baseLabel = NULL; 3260*0a96aa3bSJed Brown 3261*0a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 3262*0a96aa3bSJed Brown PetscInt s, c = -1, l; 3263*0a96aa3bSJed Brown PetscInt *closure = NULL, closureSize; 3264*0a96aa3bSJed Brown p4est_quadrant_t * ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 3265*0a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t*) pforest->forest->trees->array; 3266*0a96aa3bSJed Brown p4est_quadrant_t * q; 3267*0a96aa3bSJed Brown PetscInt t, val; 3268*0a96aa3bSJed Brown PetscBool zerosupportpoint = PETSC_FALSE; 3269*0a96aa3bSJed Brown 3270*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(plex,p,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 3271*0a96aa3bSJed Brown for (s = 0; s < starSize; s++) { 3272*0a96aa3bSJed Brown PetscInt point = star[2*s]; 3273*0a96aa3bSJed Brown 3274*0a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 3275*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(plex,point,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 3276*0a96aa3bSJed Brown for (l = 0; l < closureSize; l++) { 3277*0a96aa3bSJed Brown PetscInt qParent = closure[2 * l], q, pp = p, pParent = p; 3278*0a96aa3bSJed Brown do { /* check parents of q */ 3279*0a96aa3bSJed Brown q = qParent; 3280*0a96aa3bSJed Brown if (q == p) { 3281*0a96aa3bSJed Brown c = point; 3282*0a96aa3bSJed Brown break; 3283*0a96aa3bSJed Brown } 3284*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(plex,q,&qParent,NULL);CHKERRQ(ierr); 3285*0a96aa3bSJed Brown } while (qParent != q); 3286*0a96aa3bSJed Brown if (c != -1) break; 3287*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(plex,pp,&pParent,NULL);CHKERRQ(ierr); 3288*0a96aa3bSJed Brown q = closure[2 * l]; 3289*0a96aa3bSJed Brown while (pParent != pp) { /* check parents of p */ 3290*0a96aa3bSJed Brown pp = pParent; 3291*0a96aa3bSJed Brown if (pp == q) { 3292*0a96aa3bSJed Brown c = point; 3293*0a96aa3bSJed Brown break; 3294*0a96aa3bSJed Brown } 3295*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(plex,pp,&pParent,NULL);CHKERRQ(ierr); 3296*0a96aa3bSJed Brown } 3297*0a96aa3bSJed Brown if (c != -1) break; 3298*0a96aa3bSJed Brown } 3299*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(plex,point,PETSC_TRUE,NULL,&closure);CHKERRQ(ierr); 3300*0a96aa3bSJed Brown if (l < closureSize) break; 3301*0a96aa3bSJed Brown } else { 3302*0a96aa3bSJed Brown PetscInt supportSize; 3303*0a96aa3bSJed Brown 3304*0a96aa3bSJed Brown ierr = DMPlexGetSupportSize(plex,point,&supportSize);CHKERRQ(ierr); 3305*0a96aa3bSJed Brown zerosupportpoint = (PetscBool) (zerosupportpoint || !supportSize); 3306*0a96aa3bSJed Brown } 3307*0a96aa3bSJed Brown } 3308*0a96aa3bSJed Brown if (c < 0) { 3309*0a96aa3bSJed Brown const char* prefix; 3310*0a96aa3bSJed Brown PetscBool print = PETSC_FALSE; 3311*0a96aa3bSJed Brown 3312*0a96aa3bSJed Brown ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix);CHKERRQ(ierr); 3313*0a96aa3bSJed Brown ierr = PetscOptionsGetBool(((PetscObject)dm)->options,prefix,"-dm_forest_print_label_error",&print,NULL);CHKERRQ(ierr); 3314*0a96aa3bSJed Brown if (print) { 3315*0a96aa3bSJed Brown PetscInt i; 3316*0a96aa3bSJed Brown 3317*0a96aa3bSJed Brown ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] Failed to find cell with point %D in its closure for label %s (starSize %D)\n",PetscGlobalRank,p,baseLabel ? ((PetscObject)baseLabel)->name : "_forest_base_subpoint_map",starSize);CHKERRQ(ierr); 3318*0a96aa3bSJed Brown for (i = 0; i < starSize; i++) { ierr = PetscPrintf(PETSC_COMM_SELF," star[%D] = %D,%D\n",i,star[2*i],star[2*i+1]);CHKERRQ(ierr); } 3319*0a96aa3bSJed Brown } 3320*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(plex,p,PETSC_FALSE,NULL,&star);CHKERRQ(ierr); 3321*0a96aa3bSJed Brown if (zerosupportpoint) continue; 3322*0a96aa3bSJed Brown else SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Failed to find cell with point %D 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"); 3323*0a96aa3bSJed Brown } 3324*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(plex,p,PETSC_FALSE,NULL,&star);CHKERRQ(ierr); 3325*0a96aa3bSJed Brown 3326*0a96aa3bSJed Brown if (c < cLocalStart) { 3327*0a96aa3bSJed Brown /* get from the beginning of the ghost layer */ 3328*0a96aa3bSJed Brown q = &(ghosts[c]); 3329*0a96aa3bSJed Brown t = (PetscInt) q->p.which_tree; 3330*0a96aa3bSJed Brown } else if (c < cLocalEnd) { 3331*0a96aa3bSJed Brown PetscInt lo = 0, hi = num_trees; 3332*0a96aa3bSJed Brown /* get from local quadrants: have to find the right tree */ 3333*0a96aa3bSJed Brown 3334*0a96aa3bSJed Brown c -= cLocalStart; 3335*0a96aa3bSJed Brown 3336*0a96aa3bSJed Brown do { 3337*0a96aa3bSJed Brown p4est_tree_t *tree; 3338*0a96aa3bSJed Brown 3339*0a96aa3bSJed Brown if (guess < lo || guess >= num_trees || lo >= hi) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"failed binary search"); 3340*0a96aa3bSJed Brown tree = &trees[guess]; 3341*0a96aa3bSJed Brown if (c < tree->quadrants_offset) { 3342*0a96aa3bSJed Brown hi = guess; 3343*0a96aa3bSJed Brown } else if (c < tree->quadrants_offset + (PetscInt) tree->quadrants.elem_count) { 3344*0a96aa3bSJed Brown q = &((p4est_quadrant_t *)tree->quadrants.array)[c - (PetscInt) tree->quadrants_offset]; 3345*0a96aa3bSJed Brown t = guess; 3346*0a96aa3bSJed Brown break; 3347*0a96aa3bSJed Brown } else { 3348*0a96aa3bSJed Brown lo = guess + 1; 3349*0a96aa3bSJed Brown } 3350*0a96aa3bSJed Brown guess = lo + (hi - lo) / 2; 3351*0a96aa3bSJed Brown } while (1); 3352*0a96aa3bSJed Brown } else { 3353*0a96aa3bSJed Brown /* get from the end of the ghost layer */ 3354*0a96aa3bSJed Brown c -= (cLocalEnd - cLocalStart); 3355*0a96aa3bSJed Brown 3356*0a96aa3bSJed Brown q = &(ghosts[c]); 3357*0a96aa3bSJed Brown t = (PetscInt) q->p.which_tree; 3358*0a96aa3bSJed Brown } 3359*0a96aa3bSJed Brown 3360*0a96aa3bSJed Brown if (l == 0) { /* cell */ 3361*0a96aa3bSJed Brown if (baseLabel) { 3362*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,t+cStartBase,&val);CHKERRQ(ierr); 3363*0a96aa3bSJed Brown } else { 3364*0a96aa3bSJed Brown val = t+cStartBase; 3365*0a96aa3bSJed Brown } 3366*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3367*0a96aa3bSJed Brown } else if (l >= 1 && l < 1 + P4EST_FACES) { /* facet */ 3368*0a96aa3bSJed Brown p4est_quadrant_t nq; 3369*0a96aa3bSJed Brown int isInside; 3370*0a96aa3bSJed Brown 3371*0a96aa3bSJed Brown l = PetscFaceToP4estFace[l - 1]; 3372*0a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_face_neighbor,(q,l,&nq)); 3373*0a96aa3bSJed Brown PetscStackCallP4estReturn(isInside,p4est_quadrant_is_inside_root,(&nq)); 3374*0a96aa3bSJed Brown if (isInside) { 3375*0a96aa3bSJed Brown /* this facet is in the interior of a tree, so it inherits the label of the tree */ 3376*0a96aa3bSJed Brown if (baseLabel) { 3377*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,t+cStartBase,&val);CHKERRQ(ierr); 3378*0a96aa3bSJed Brown } else { 3379*0a96aa3bSJed Brown val = t+cStartBase; 3380*0a96aa3bSJed Brown } 3381*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3382*0a96aa3bSJed Brown } else { 3383*0a96aa3bSJed Brown PetscInt f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + l]; 3384*0a96aa3bSJed Brown 3385*0a96aa3bSJed Brown if (baseLabel) { 3386*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,f+fStartBase,&val);CHKERRQ(ierr); 3387*0a96aa3bSJed Brown } else { 3388*0a96aa3bSJed Brown val = f+fStartBase; 3389*0a96aa3bSJed Brown } 3390*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3391*0a96aa3bSJed Brown } 3392*0a96aa3bSJed Brown #if defined(P4_TO_P8) 3393*0a96aa3bSJed Brown } else if (l >= 1 + P4EST_FACES && l < 1 + P4EST_FACES + P8EST_EDGES) { /* edge */ 3394*0a96aa3bSJed Brown p4est_quadrant_t nq; 3395*0a96aa3bSJed Brown int isInside; 3396*0a96aa3bSJed Brown 3397*0a96aa3bSJed Brown l = PetscEdgeToP4estEdge[l - (1 + P4EST_FACES)]; 3398*0a96aa3bSJed Brown PetscStackCallP4est(p8est_quadrant_edge_neighbor,(q,l,&nq)); 3399*0a96aa3bSJed Brown PetscStackCallP4estReturn(isInside,p4est_quadrant_is_inside_root,(&nq)); 3400*0a96aa3bSJed Brown if (isInside) { 3401*0a96aa3bSJed Brown /* this edge is in the interior of a tree, so it inherits the label of the tree */ 3402*0a96aa3bSJed Brown if (baseLabel) { 3403*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,t+cStartBase,&val);CHKERRQ(ierr); 3404*0a96aa3bSJed Brown } else { 3405*0a96aa3bSJed Brown val = t+cStartBase; 3406*0a96aa3bSJed Brown } 3407*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3408*0a96aa3bSJed Brown } else { 3409*0a96aa3bSJed Brown int isOutsideFace; 3410*0a96aa3bSJed Brown 3411*0a96aa3bSJed Brown PetscStackCallP4estReturn(isOutsideFace,p4est_quadrant_is_outside_face,(&nq)); 3412*0a96aa3bSJed Brown if (isOutsideFace) { 3413*0a96aa3bSJed Brown PetscInt f; 3414*0a96aa3bSJed Brown 3415*0a96aa3bSJed Brown if (nq.x < 0) { 3416*0a96aa3bSJed Brown f = 0; 3417*0a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 3418*0a96aa3bSJed Brown f = 1; 3419*0a96aa3bSJed Brown } else if (nq.y < 0) { 3420*0a96aa3bSJed Brown f = 2; 3421*0a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 3422*0a96aa3bSJed Brown f = 3; 3423*0a96aa3bSJed Brown } else if (nq.z < 0) { 3424*0a96aa3bSJed Brown f = 4; 3425*0a96aa3bSJed Brown } else { 3426*0a96aa3bSJed Brown f = 5; 3427*0a96aa3bSJed Brown } 3428*0a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 3429*0a96aa3bSJed Brown if (baseLabel) { 3430*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,f+fStartBase,&val);CHKERRQ(ierr); 3431*0a96aa3bSJed Brown } else { 3432*0a96aa3bSJed Brown val = f+fStartBase; 3433*0a96aa3bSJed Brown } 3434*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3435*0a96aa3bSJed Brown } else { /* the quadrant edge corresponds to the tree edge */ 3436*0a96aa3bSJed Brown PetscInt e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + l]; 3437*0a96aa3bSJed Brown 3438*0a96aa3bSJed Brown if (baseLabel) { 3439*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,e+eStartBase,&val);CHKERRQ(ierr); 3440*0a96aa3bSJed Brown } else { 3441*0a96aa3bSJed Brown val = e+eStartBase; 3442*0a96aa3bSJed Brown } 3443*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3444*0a96aa3bSJed Brown } 3445*0a96aa3bSJed Brown } 3446*0a96aa3bSJed Brown #endif 3447*0a96aa3bSJed Brown } else { /* vertex */ 3448*0a96aa3bSJed Brown p4est_quadrant_t nq; 3449*0a96aa3bSJed Brown int isInside; 3450*0a96aa3bSJed Brown 3451*0a96aa3bSJed Brown #if defined(P4_TO_P8) 3452*0a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES + P8EST_EDGES)]; 3453*0a96aa3bSJed Brown #else 3454*0a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES)]; 3455*0a96aa3bSJed Brown #endif 3456*0a96aa3bSJed Brown PetscStackCallP4est(p4est_quadrant_corner_neighbor,(q,l,&nq)); 3457*0a96aa3bSJed Brown PetscStackCallP4estReturn(isInside,p4est_quadrant_is_inside_root,(&nq)); 3458*0a96aa3bSJed Brown if (isInside) { 3459*0a96aa3bSJed Brown if (baseLabel) { 3460*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,t+cStartBase,&val);CHKERRQ(ierr); 3461*0a96aa3bSJed Brown } else { 3462*0a96aa3bSJed Brown val = t+cStartBase; 3463*0a96aa3bSJed Brown } 3464*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3465*0a96aa3bSJed Brown } else { 3466*0a96aa3bSJed Brown int isOutside; 3467*0a96aa3bSJed Brown 3468*0a96aa3bSJed Brown PetscStackCallP4estReturn(isOutside,p4est_quadrant_is_outside_face,(&nq)); 3469*0a96aa3bSJed Brown if (isOutside) { 3470*0a96aa3bSJed Brown PetscInt f = -1; 3471*0a96aa3bSJed Brown 3472*0a96aa3bSJed Brown if (nq.x < 0) { 3473*0a96aa3bSJed Brown f = 0; 3474*0a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) { 3475*0a96aa3bSJed Brown f = 1; 3476*0a96aa3bSJed Brown } else if (nq.y < 0) { 3477*0a96aa3bSJed Brown f = 2; 3478*0a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) { 3479*0a96aa3bSJed Brown f = 3; 3480*0a96aa3bSJed Brown #if defined(P4_TO_P8) 3481*0a96aa3bSJed Brown } else if (nq.z < 0) { 3482*0a96aa3bSJed Brown f = 4; 3483*0a96aa3bSJed Brown } else { 3484*0a96aa3bSJed Brown f = 5; 3485*0a96aa3bSJed Brown #endif 3486*0a96aa3bSJed Brown } 3487*0a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f]; 3488*0a96aa3bSJed Brown if (baseLabel) { 3489*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,f+fStartBase,&val);CHKERRQ(ierr); 3490*0a96aa3bSJed Brown } else { 3491*0a96aa3bSJed Brown val = f+fStartBase; 3492*0a96aa3bSJed Brown } 3493*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3494*0a96aa3bSJed Brown continue; 3495*0a96aa3bSJed Brown } 3496*0a96aa3bSJed Brown #if defined(P4_TO_P8) 3497*0a96aa3bSJed Brown PetscStackCallP4estReturn(isOutside,p8est_quadrant_is_outside_edge,(&nq)); 3498*0a96aa3bSJed Brown if (isOutside) { 3499*0a96aa3bSJed Brown /* outside edge */ 3500*0a96aa3bSJed Brown PetscInt e = -1; 3501*0a96aa3bSJed Brown 3502*0a96aa3bSJed Brown if (nq.x >= 0 && nq.x < P4EST_ROOT_LEN) { 3503*0a96aa3bSJed Brown if (nq.z < 0) { 3504*0a96aa3bSJed Brown if (nq.y < 0) { 3505*0a96aa3bSJed Brown e = 0; 3506*0a96aa3bSJed Brown } else { 3507*0a96aa3bSJed Brown e = 1; 3508*0a96aa3bSJed Brown } 3509*0a96aa3bSJed Brown } else { 3510*0a96aa3bSJed Brown if (nq.y < 0) { 3511*0a96aa3bSJed Brown e = 2; 3512*0a96aa3bSJed Brown } else { 3513*0a96aa3bSJed Brown e = 3; 3514*0a96aa3bSJed Brown } 3515*0a96aa3bSJed Brown } 3516*0a96aa3bSJed Brown } else if (nq.y >= 0 && nq.y < P4EST_ROOT_LEN) { 3517*0a96aa3bSJed Brown if (nq.z < 0) { 3518*0a96aa3bSJed Brown if (nq.x < 0) { 3519*0a96aa3bSJed Brown e = 4; 3520*0a96aa3bSJed Brown } else { 3521*0a96aa3bSJed Brown e = 5; 3522*0a96aa3bSJed Brown } 3523*0a96aa3bSJed Brown } else { 3524*0a96aa3bSJed Brown if (nq.x < 0) { 3525*0a96aa3bSJed Brown e = 6; 3526*0a96aa3bSJed Brown } else { 3527*0a96aa3bSJed Brown e = 7; 3528*0a96aa3bSJed Brown } 3529*0a96aa3bSJed Brown } 3530*0a96aa3bSJed Brown } else { 3531*0a96aa3bSJed Brown if (nq.y < 0) { 3532*0a96aa3bSJed Brown if (nq.x < 0) { 3533*0a96aa3bSJed Brown e = 8; 3534*0a96aa3bSJed Brown } else { 3535*0a96aa3bSJed Brown e = 9; 3536*0a96aa3bSJed Brown } 3537*0a96aa3bSJed Brown } else { 3538*0a96aa3bSJed Brown if (nq.x < 0) { 3539*0a96aa3bSJed Brown e = 10; 3540*0a96aa3bSJed Brown } else { 3541*0a96aa3bSJed Brown e = 11; 3542*0a96aa3bSJed Brown } 3543*0a96aa3bSJed Brown } 3544*0a96aa3bSJed Brown } 3545*0a96aa3bSJed Brown 3546*0a96aa3bSJed Brown e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + e]; 3547*0a96aa3bSJed Brown if (baseLabel) { 3548*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,e+eStartBase,&val);CHKERRQ(ierr); 3549*0a96aa3bSJed Brown } else { 3550*0a96aa3bSJed Brown val = e+eStartBase; 3551*0a96aa3bSJed Brown } 3552*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3553*0a96aa3bSJed Brown continue; 3554*0a96aa3bSJed Brown } 3555*0a96aa3bSJed Brown #endif 3556*0a96aa3bSJed Brown { 3557*0a96aa3bSJed Brown /* outside vertex: same corner as quadrant corner */ 3558*0a96aa3bSJed Brown PetscInt v = pforest->topo->conn->tree_to_corner[P4EST_CHILDREN * t + l]; 3559*0a96aa3bSJed Brown 3560*0a96aa3bSJed Brown if (baseLabel) { 3561*0a96aa3bSJed Brown ierr = DMLabelGetValue(baseLabel,v+vStartBase,&val);CHKERRQ(ierr); 3562*0a96aa3bSJed Brown } else { 3563*0a96aa3bSJed Brown val = v+vStartBase; 3564*0a96aa3bSJed Brown } 3565*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,val);CHKERRQ(ierr); 3566*0a96aa3bSJed Brown } 3567*0a96aa3bSJed Brown } 3568*0a96aa3bSJed Brown } 3569*0a96aa3bSJed Brown } 3570*0a96aa3bSJed Brown next = next->next; 3571*0a96aa3bSJed Brown } 3572*0a96aa3bSJed Brown PetscFunctionReturn(0); 3573*0a96aa3bSJed Brown } 3574*0a96aa3bSJed Brown 3575*0a96aa3bSJed Brown static PetscErrorCode DMPforestLabelsFinalize(DM dm, DM plex) 3576*0a96aa3bSJed Brown { 3577*0a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 3578*0a96aa3bSJed Brown DM adapt; 3579*0a96aa3bSJed Brown PetscErrorCode ierr; 3580*0a96aa3bSJed Brown 3581*0a96aa3bSJed Brown PetscFunctionBegin; 3582*0a96aa3bSJed Brown if (pforest->labelsFinalized) PetscFunctionReturn(0); 3583*0a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 3584*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(dm,&adapt);CHKERRQ(ierr); 3585*0a96aa3bSJed Brown if (!adapt) { 3586*0a96aa3bSJed Brown /* Initialize labels from the base dm */ 3587*0a96aa3bSJed Brown ierr = DMPforestLabelsInitialize(dm,plex);CHKERRQ(ierr); 3588*0a96aa3bSJed Brown } else { 3589*0a96aa3bSJed Brown PetscInt dofPerDim[4]={1, 1, 1, 1}; 3590*0a96aa3bSJed Brown PetscSF transferForward, transferBackward, pointSF; 3591*0a96aa3bSJed Brown PetscInt pStart, pEnd, pStartA, pEndA; 3592*0a96aa3bSJed Brown PetscInt *values, *adaptValues; 3593*0a96aa3bSJed Brown DMLabelLink next = adapt->labels; 3594*0a96aa3bSJed Brown DMLabel adaptLabel; 3595*0a96aa3bSJed Brown DM adaptPlex; 3596*0a96aa3bSJed Brown 3597*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityLabel(dm,&adaptLabel);CHKERRQ(ierr); 3598*0a96aa3bSJed Brown ierr = DMPforestGetPlex(adapt,&adaptPlex);CHKERRQ(ierr); 3599*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF(adapt,dm,dofPerDim,&transferForward,&transferBackward);CHKERRQ(ierr); 3600*0a96aa3bSJed Brown ierr = DMPlexGetChart(plex,&pStart,&pEnd);CHKERRQ(ierr); 3601*0a96aa3bSJed Brown ierr = DMPlexGetChart(adaptPlex,&pStartA,&pEndA);CHKERRQ(ierr); 3602*0a96aa3bSJed Brown ierr = PetscMalloc2(pEnd-pStart,&values,pEndA-pStartA,&adaptValues);CHKERRQ(ierr); 3603*0a96aa3bSJed Brown ierr = DMGetPointSF(plex,&pointSF);CHKERRQ(ierr); 3604*0a96aa3bSJed Brown if (PetscDefined(USE_DEBUG)) { 3605*0a96aa3bSJed Brown PetscInt p; 3606*0a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) adaptValues[p-pStartA] = -1; 3607*0a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p-pStart] = -2; 3608*0a96aa3bSJed Brown if (transferForward) { 3609*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE);CHKERRQ(ierr); 3610*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE);CHKERRQ(ierr); 3611*0a96aa3bSJed Brown } 3612*0a96aa3bSJed Brown if (transferBackward) { 3613*0a96aa3bSJed Brown ierr = PetscSFReduceBegin(transferBackward,MPIU_INT,adaptValues,values,MPIU_MAX);CHKERRQ(ierr); 3614*0a96aa3bSJed Brown ierr = PetscSFReduceEnd(transferBackward,MPIU_INT,adaptValues,values,MPIU_MAX);CHKERRQ(ierr); 3615*0a96aa3bSJed Brown } 3616*0a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 3617*0a96aa3bSJed Brown PetscInt q = p, parent; 3618*0a96aa3bSJed Brown 3619*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(plex,q,&parent,NULL);CHKERRQ(ierr); 3620*0a96aa3bSJed Brown while (parent != q) { 3621*0a96aa3bSJed Brown if (values[parent] == -2) values[parent] = values[q]; 3622*0a96aa3bSJed Brown q = parent; 3623*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(plex,q,&parent,NULL);CHKERRQ(ierr); 3624*0a96aa3bSJed Brown } 3625*0a96aa3bSJed Brown } 3626*0a96aa3bSJed Brown ierr = PetscSFReduceBegin(pointSF,MPIU_INT,values,values,MPIU_MAX);CHKERRQ(ierr); 3627*0a96aa3bSJed Brown ierr = PetscSFReduceEnd(pointSF,MPIU_INT,values,values,MPIU_MAX);CHKERRQ(ierr); 3628*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(pointSF,MPIU_INT,values,values,MPI_REPLACE);CHKERRQ(ierr); 3629*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(pointSF,MPIU_INT,values,values,MPI_REPLACE);CHKERRQ(ierr); 3630*0a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 3631*0a96aa3bSJed Brown if (values[p-pStart] == -2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"uncovered point %D",p); 3632*0a96aa3bSJed Brown } 3633*0a96aa3bSJed Brown } 3634*0a96aa3bSJed Brown while (next) { 3635*0a96aa3bSJed Brown DMLabel nextLabel = next->label; 3636*0a96aa3bSJed Brown const char *name; 3637*0a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK; 3638*0a96aa3bSJed Brown DMLabel label; 3639*0a96aa3bSJed Brown PetscInt p; 3640*0a96aa3bSJed Brown 3641*0a96aa3bSJed Brown ierr = PetscObjectGetName((PetscObject) nextLabel, &name);CHKERRQ(ierr); 3642*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"depth",&isDepth);CHKERRQ(ierr); 3643*0a96aa3bSJed Brown if (isDepth) { 3644*0a96aa3bSJed Brown next = next->next; 3645*0a96aa3bSJed Brown continue; 3646*0a96aa3bSJed Brown } 3647*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"celltype",&isCellType);CHKERRQ(ierr); 3648*0a96aa3bSJed Brown if (isCellType) { 3649*0a96aa3bSJed Brown next = next->next; 3650*0a96aa3bSJed Brown continue; 3651*0a96aa3bSJed Brown } 3652*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"ghost",&isGhost);CHKERRQ(ierr); 3653*0a96aa3bSJed Brown if (isGhost) { 3654*0a96aa3bSJed Brown next = next->next; 3655*0a96aa3bSJed Brown continue; 3656*0a96aa3bSJed Brown } 3657*0a96aa3bSJed Brown ierr = PetscStrcmp(name,"vtk",&isVTK);CHKERRQ(ierr); 3658*0a96aa3bSJed Brown if (isVTK) { 3659*0a96aa3bSJed Brown next = next->next; 3660*0a96aa3bSJed Brown continue; 3661*0a96aa3bSJed Brown } 3662*0a96aa3bSJed Brown if (nextLabel == adaptLabel) { 3663*0a96aa3bSJed Brown next = next->next; 3664*0a96aa3bSJed Brown continue; 3665*0a96aa3bSJed Brown } 3666*0a96aa3bSJed Brown /* label was created earlier */ 3667*0a96aa3bSJed Brown ierr = DMGetLabel(dm,name,&label);CHKERRQ(ierr); 3668*0a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) { 3669*0a96aa3bSJed Brown ierr = DMLabelGetValue(nextLabel,p,&adaptValues[p]);CHKERRQ(ierr); 3670*0a96aa3bSJed Brown } 3671*0a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p] = PETSC_MIN_INT; 3672*0a96aa3bSJed Brown 3673*0a96aa3bSJed Brown if (transferForward) { 3674*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE);CHKERRQ(ierr); 3675*0a96aa3bSJed Brown } 3676*0a96aa3bSJed Brown if (transferBackward) { 3677*0a96aa3bSJed Brown ierr = PetscSFReduceBegin(transferBackward,MPIU_INT,adaptValues,values,MPIU_MAX);CHKERRQ(ierr); 3678*0a96aa3bSJed Brown } 3679*0a96aa3bSJed Brown if (transferForward) { 3680*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(transferForward,MPIU_INT,adaptValues,values,MPI_REPLACE);CHKERRQ(ierr); 3681*0a96aa3bSJed Brown } 3682*0a96aa3bSJed Brown if (transferBackward) { 3683*0a96aa3bSJed Brown ierr = PetscSFReduceEnd(transferBackward,MPIU_INT,adaptValues,values,MPIU_MAX);CHKERRQ(ierr); 3684*0a96aa3bSJed Brown } 3685*0a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 3686*0a96aa3bSJed Brown PetscInt q = p, parent; 3687*0a96aa3bSJed Brown 3688*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(plex,q,&parent,NULL);CHKERRQ(ierr); 3689*0a96aa3bSJed Brown while (parent != q) { 3690*0a96aa3bSJed Brown if (values[parent] == PETSC_MIN_INT) values[parent] = values[q]; 3691*0a96aa3bSJed Brown q = parent; 3692*0a96aa3bSJed Brown ierr = DMPlexGetTreeParent(plex,q,&parent,NULL);CHKERRQ(ierr); 3693*0a96aa3bSJed Brown } 3694*0a96aa3bSJed Brown } 3695*0a96aa3bSJed Brown ierr = PetscSFReduceBegin(pointSF,MPIU_INT,values,values,MPIU_MAX);CHKERRQ(ierr); 3696*0a96aa3bSJed Brown ierr = PetscSFReduceEnd(pointSF,MPIU_INT,values,values,MPIU_MAX);CHKERRQ(ierr); 3697*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(pointSF,MPIU_INT,values,values,MPI_REPLACE);CHKERRQ(ierr); 3698*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(pointSF,MPIU_INT,values,values,MPI_REPLACE);CHKERRQ(ierr); 3699*0a96aa3bSJed Brown 3700*0a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) { 3701*0a96aa3bSJed Brown ierr = DMLabelSetValue(label,p,values[p]);CHKERRQ(ierr); 3702*0a96aa3bSJed Brown } 3703*0a96aa3bSJed Brown next = next->next; 3704*0a96aa3bSJed Brown } 3705*0a96aa3bSJed Brown ierr = PetscFree2(values,adaptValues);CHKERRQ(ierr); 3706*0a96aa3bSJed Brown ierr = PetscSFDestroy(&transferForward);CHKERRQ(ierr); 3707*0a96aa3bSJed Brown ierr = PetscSFDestroy(&transferBackward);CHKERRQ(ierr); 3708*0a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE; 3709*0a96aa3bSJed Brown } 3710*0a96aa3bSJed Brown PetscFunctionReturn(0); 3711*0a96aa3bSJed Brown } 3712*0a96aa3bSJed Brown 3713*0a96aa3bSJed 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) 3714*0a96aa3bSJed Brown { 3715*0a96aa3bSJed Brown PetscInt closureSize, c, coordStart, coordEnd, coordDim; 3716*0a96aa3bSJed Brown PetscInt *closure = NULL; 3717*0a96aa3bSJed Brown PetscSection coordSec; 3718*0a96aa3bSJed Brown PetscErrorCode ierr; 3719*0a96aa3bSJed Brown 3720*0a96aa3bSJed Brown PetscFunctionBegin; 3721*0a96aa3bSJed Brown ierr = DMGetCoordinateSection(plex,&coordSec);CHKERRQ(ierr); 3722*0a96aa3bSJed Brown ierr = PetscSectionGetChart(coordSec,&coordStart,&coordEnd);CHKERRQ(ierr); 3723*0a96aa3bSJed Brown ierr = DMGetCoordinateDim(plex,&coordDim);CHKERRQ(ierr); 3724*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(plex,cell,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 3725*0a96aa3bSJed Brown for (c = 0; c < closureSize; c++) { 3726*0a96aa3bSJed Brown PetscInt point = closure[2 * c]; 3727*0a96aa3bSJed Brown 3728*0a96aa3bSJed Brown if (point >= coordStart && point < coordEnd) { 3729*0a96aa3bSJed Brown PetscInt dof, off; 3730*0a96aa3bSJed Brown PetscInt nCoords, i; 3731*0a96aa3bSJed Brown ierr = PetscSectionGetDof(coordSec,point,&dof);CHKERRQ(ierr); 3732*0a96aa3bSJed Brown if (dof % coordDim) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Did not understand coordinate layout"); 3733*0a96aa3bSJed Brown nCoords = dof / coordDim; 3734*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(coordSec,point,&off);CHKERRQ(ierr); 3735*0a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 3736*0a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 3737*0a96aa3bSJed Brown double coordP4est[3] = {0.}; 3738*0a96aa3bSJed Brown double coordP4estMapped[3] = {0.}; 3739*0a96aa3bSJed Brown PetscInt j; 3740*0a96aa3bSJed Brown PetscReal treeCoords[P4EST_CHILDREN][3] = {{0.}}; 3741*0a96aa3bSJed Brown PetscReal eta[3] = {0.}; 3742*0a96aa3bSJed Brown PetscInt numRounds = 10; 3743*0a96aa3bSJed Brown PetscReal coordGuess[3] = {0.}; 3744*0a96aa3bSJed Brown 3745*0a96aa3bSJed Brown eta[0] = (PetscReal) q->x / (PetscReal) P4EST_ROOT_LEN; 3746*0a96aa3bSJed Brown eta[1] = (PetscReal) q->y / (PetscReal) P4EST_ROOT_LEN; 3747*0a96aa3bSJed Brown #if defined(P4_TO_P8) 3748*0a96aa3bSJed Brown eta[2] = (PetscReal) q->z / (PetscReal) P4EST_ROOT_LEN; 3749*0a96aa3bSJed Brown #endif 3750*0a96aa3bSJed Brown 3751*0a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 3752*0a96aa3bSJed Brown PetscInt k; 3753*0a96aa3bSJed Brown 3754*0a96aa3bSJed Brown for (k = 0; k < 3; k++) treeCoords[j][k] = conn->vertices[3 * conn->tree_to_vertex[P4EST_CHILDREN * t + j] + k]; 3755*0a96aa3bSJed Brown } 3756*0a96aa3bSJed Brown 3757*0a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) { 3758*0a96aa3bSJed Brown PetscInt k; 3759*0a96aa3bSJed Brown PetscReal prod = 1.; 3760*0a96aa3bSJed Brown 3761*0a96aa3bSJed Brown for (k = 0; k < P4EST_DIM; k++) prod *= (j & (1 << k)) ? eta[k] : (1. - eta[k]); 3762*0a96aa3bSJed Brown for (k = 0; k < 3; k++) coordGuess[k] += prod * treeCoords[j][k]; 3763*0a96aa3bSJed Brown } 3764*0a96aa3bSJed Brown 3765*0a96aa3bSJed Brown for (j = 0; j < numRounds; j++) { 3766*0a96aa3bSJed Brown PetscInt dir; 3767*0a96aa3bSJed Brown 3768*0a96aa3bSJed Brown for (dir = 0; dir < P4EST_DIM; dir++) { 3769*0a96aa3bSJed Brown PetscInt k; 3770*0a96aa3bSJed Brown PetscReal diff[3]; 3771*0a96aa3bSJed Brown PetscReal dXdeta[3] = {0.}; 3772*0a96aa3bSJed Brown PetscReal rhs, scale, update; 3773*0a96aa3bSJed Brown 3774*0a96aa3bSJed Brown for (k = 0; k < 3; k++) diff[k] = coordP4est[k] - coordGuess[k]; 3775*0a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 3776*0a96aa3bSJed Brown PetscInt l; 3777*0a96aa3bSJed Brown PetscReal prod = 1.; 3778*0a96aa3bSJed Brown 3779*0a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) { 3780*0a96aa3bSJed Brown if (l == dir) { 3781*0a96aa3bSJed Brown prod *= (k & (1 << l)) ? 1. : -1.; 3782*0a96aa3bSJed Brown } else { 3783*0a96aa3bSJed Brown prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 3784*0a96aa3bSJed Brown } 3785*0a96aa3bSJed Brown } 3786*0a96aa3bSJed Brown for (l = 0; l < 3; l++) dXdeta[l] += prod * treeCoords[k][l]; 3787*0a96aa3bSJed Brown } 3788*0a96aa3bSJed Brown rhs = 0.; 3789*0a96aa3bSJed Brown scale = 0; 3790*0a96aa3bSJed Brown for (k = 0; k < 3; k++) { 3791*0a96aa3bSJed Brown rhs += diff[k] * dXdeta[k]; 3792*0a96aa3bSJed Brown scale += dXdeta[k] * dXdeta[k]; 3793*0a96aa3bSJed Brown } 3794*0a96aa3bSJed Brown update = rhs / scale; 3795*0a96aa3bSJed Brown eta[dir] += update; 3796*0a96aa3bSJed Brown eta[dir] = PetscMin(eta[dir],1.); 3797*0a96aa3bSJed Brown eta[dir] = PetscMax(eta[dir],0.); 3798*0a96aa3bSJed Brown 3799*0a96aa3bSJed Brown coordGuess[0] = coordGuess[1] = coordGuess[2] = 0.; 3800*0a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) { 3801*0a96aa3bSJed Brown PetscInt l; 3802*0a96aa3bSJed Brown PetscReal prod = 1.; 3803*0a96aa3bSJed Brown 3804*0a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]); 3805*0a96aa3bSJed Brown for (l = 0; l < 3; l++) coordGuess[l] += prod * treeCoords[k][l]; 3806*0a96aa3bSJed Brown } 3807*0a96aa3bSJed Brown } 3808*0a96aa3bSJed Brown } 3809*0a96aa3bSJed Brown for (j = 0; j < 3; j++) coordP4est[j] = (double) eta[j]; 3810*0a96aa3bSJed Brown 3811*0a96aa3bSJed Brown if (geom) { 3812*0a96aa3bSJed Brown (geom->X)(geom,t,coordP4est,coordP4estMapped); 3813*0a96aa3bSJed Brown for (j = 0; j < coordDim; j++) coord[j] = (PetscScalar) coordP4estMapped[j]; 3814*0a96aa3bSJed Brown } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not coded"); 3815*0a96aa3bSJed Brown } 3816*0a96aa3bSJed Brown } 3817*0a96aa3bSJed Brown } 3818*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(plex,cell,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 3819*0a96aa3bSJed Brown PetscFunctionReturn(0); 3820*0a96aa3bSJed Brown } 3821*0a96aa3bSJed Brown 3822*0a96aa3bSJed Brown static PetscErrorCode DMPforestMapCoordinates(DM dm, DM plex) 3823*0a96aa3bSJed Brown { 3824*0a96aa3bSJed Brown DM_Forest *forest; 3825*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 3826*0a96aa3bSJed Brown p4est_geometry_t *geom; 3827*0a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd; 3828*0a96aa3bSJed Brown Vec coordLocalVec; 3829*0a96aa3bSJed Brown PetscScalar *coords; 3830*0a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 3831*0a96aa3bSJed Brown p4est_tree_t *trees; 3832*0a96aa3bSJed Brown PetscErrorCode (*map)(DM,PetscInt, PetscInt, const PetscReal [], PetscReal [], void*); 3833*0a96aa3bSJed Brown void *mapCtx; 3834*0a96aa3bSJed Brown PetscErrorCode ierr; 3835*0a96aa3bSJed Brown 3836*0a96aa3bSJed Brown PetscFunctionBegin; 3837*0a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 3838*0a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 3839*0a96aa3bSJed Brown geom = pforest->topo->geom; 3840*0a96aa3bSJed Brown ierr = DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx);CHKERRQ(ierr); 3841*0a96aa3bSJed Brown if (!geom && !map) PetscFunctionReturn(0); 3842*0a96aa3bSJed Brown ierr = DMGetCoordinatesLocal(plex,&coordLocalVec);CHKERRQ(ierr); 3843*0a96aa3bSJed Brown ierr = VecGetArray(coordLocalVec,&coords);CHKERRQ(ierr); 3844*0a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 3845*0a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 3846*0a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 3847*0a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 3848*0a96aa3bSJed Brown trees = (p4est_tree_t*) pforest->forest->trees->array; 3849*0a96aa3bSJed Brown if (map) { /* apply the map directly to the existing coordinates */ 3850*0a96aa3bSJed Brown PetscSection coordSec; 3851*0a96aa3bSJed Brown PetscInt coordStart, coordEnd, p, coordDim, p4estCoordDim, cStart, cEnd, cEndInterior; 3852*0a96aa3bSJed Brown DM base; 3853*0a96aa3bSJed Brown 3854*0a96aa3bSJed Brown ierr = DMPlexGetHeightStratum(plex,0,&cStart,&cEnd);CHKERRQ(ierr); 3855*0a96aa3bSJed Brown ierr = DMPlexGetGhostCellStratum(plex,&cEndInterior,NULL);CHKERRQ(ierr); 3856*0a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 3857*0a96aa3bSJed Brown ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr); 3858*0a96aa3bSJed Brown ierr = DMGetCoordinateSection(plex,&coordSec);CHKERRQ(ierr); 3859*0a96aa3bSJed Brown ierr = PetscSectionGetChart(coordSec,&coordStart,&coordEnd);CHKERRQ(ierr); 3860*0a96aa3bSJed Brown ierr = DMGetCoordinateDim(plex,&coordDim);CHKERRQ(ierr); 3861*0a96aa3bSJed Brown p4estCoordDim = PetscMin(coordDim,3); 3862*0a96aa3bSJed Brown for (p = coordStart; p < coordEnd; p++) { 3863*0a96aa3bSJed Brown PetscInt *star = NULL, starSize; 3864*0a96aa3bSJed Brown PetscInt dof, off, cell = -1, coarsePoint = -1; 3865*0a96aa3bSJed Brown PetscInt nCoords, i; 3866*0a96aa3bSJed Brown ierr = PetscSectionGetDof(coordSec,p,&dof);CHKERRQ(ierr); 3867*0a96aa3bSJed Brown if (dof % coordDim) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Did not understand coordinate layout"); 3868*0a96aa3bSJed Brown nCoords = dof / coordDim; 3869*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(coordSec,p,&off);CHKERRQ(ierr); 3870*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(plex,p,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 3871*0a96aa3bSJed Brown for (i = 0; i < starSize; i++) { 3872*0a96aa3bSJed Brown PetscInt point = star[2 * i]; 3873*0a96aa3bSJed Brown 3874*0a96aa3bSJed Brown if (cStart <= point && point < cEnd) { 3875*0a96aa3bSJed Brown cell = point; 3876*0a96aa3bSJed Brown break; 3877*0a96aa3bSJed Brown } 3878*0a96aa3bSJed Brown } 3879*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(plex,p,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 3880*0a96aa3bSJed Brown if (cell >= 0) { 3881*0a96aa3bSJed Brown if (cell < cLocalStart) { 3882*0a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 3883*0a96aa3bSJed Brown 3884*0a96aa3bSJed Brown coarsePoint = ghosts[cell].p.which_tree; 3885*0a96aa3bSJed Brown } else if (cell < cLocalEnd) { 3886*0a96aa3bSJed Brown cell -= cLocalStart; 3887*0a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 3888*0a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 3889*0a96aa3bSJed Brown 3890*0a96aa3bSJed Brown if (cell >= tree->quadrants_offset && (size_t) cell < tree->quadrants_offset + tree->quadrants.elem_count) { 3891*0a96aa3bSJed Brown coarsePoint = t; 3892*0a96aa3bSJed Brown break; 3893*0a96aa3bSJed Brown } 3894*0a96aa3bSJed Brown } 3895*0a96aa3bSJed Brown } else { 3896*0a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 3897*0a96aa3bSJed Brown 3898*0a96aa3bSJed Brown coarsePoint = ghosts[cell - cLocalEnd].p.which_tree; 3899*0a96aa3bSJed Brown } 3900*0a96aa3bSJed Brown } 3901*0a96aa3bSJed Brown for (i = 0; i < nCoords; i++) { 3902*0a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim]; 3903*0a96aa3bSJed Brown PetscReal coordP4est[3] = {0.}; 3904*0a96aa3bSJed Brown PetscReal coordP4estMapped[3] = {0.}; 3905*0a96aa3bSJed Brown PetscInt j; 3906*0a96aa3bSJed Brown 3907*0a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coordP4est[j] = PetscRealPart(coord[j]); 3908*0a96aa3bSJed Brown ierr = (map)(base,coarsePoint,p4estCoordDim,coordP4est,coordP4estMapped,mapCtx);CHKERRQ(ierr); 3909*0a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coord[j] = (PetscScalar) coordP4estMapped[j]; 3910*0a96aa3bSJed Brown } 3911*0a96aa3bSJed Brown } 3912*0a96aa3bSJed Brown } else { /* we have to transform coordinates back to the unit cube (where geom is defined), and then apply geom */ 3913*0a96aa3bSJed Brown PetscInt cStart, cEnd, cEndInterior; 3914*0a96aa3bSJed Brown 3915*0a96aa3bSJed Brown ierr = DMPlexGetHeightStratum(plex,0,&cStart,&cEnd);CHKERRQ(ierr); 3916*0a96aa3bSJed Brown ierr = DMPlexGetGhostCellStratum(plex,&cEndInterior,NULL);CHKERRQ(ierr); 3917*0a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 3918*0a96aa3bSJed Brown if (cLocalStart > 0) { 3919*0a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 3920*0a96aa3bSJed Brown PetscInt count; 3921*0a96aa3bSJed Brown 3922*0a96aa3bSJed Brown for (count = 0; count < cLocalStart; count++) { 3923*0a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count]; 3924*0a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 3925*0a96aa3bSJed Brown 3926*0a96aa3bSJed Brown ierr = DMPforestMapCoordinates_Cell(plex,geom,count,quad,t,pforest->topo->conn,coords);CHKERRQ(ierr); 3927*0a96aa3bSJed Brown } 3928*0a96aa3bSJed Brown } 3929*0a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 3930*0a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 3931*0a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset, i; 3932*0a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 3933*0a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t*) tree->quadrants.array; 3934*0a96aa3bSJed Brown 3935*0a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 3936*0a96aa3bSJed Brown PetscInt count = i + offset; 3937*0a96aa3bSJed Brown 3938*0a96aa3bSJed Brown ierr = DMPforestMapCoordinates_Cell(plex,geom,count,&quads[i],t,pforest->topo->conn,coords);CHKERRQ(ierr); 3939*0a96aa3bSJed Brown } 3940*0a96aa3bSJed Brown } 3941*0a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 3942*0a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 3943*0a96aa3bSJed Brown PetscInt numGhosts = (PetscInt) pforest->ghost->ghosts.elem_count; 3944*0a96aa3bSJed Brown PetscInt count; 3945*0a96aa3bSJed Brown 3946*0a96aa3bSJed Brown for (count = 0; count < numGhosts - cLocalStart; count++) { 3947*0a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 3948*0a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree; 3949*0a96aa3bSJed Brown 3950*0a96aa3bSJed Brown ierr = DMPforestMapCoordinates_Cell(plex,geom,count + cLocalEnd,quad,t,pforest->topo->conn,coords);CHKERRQ(ierr); 3951*0a96aa3bSJed Brown } 3952*0a96aa3bSJed Brown } 3953*0a96aa3bSJed Brown } 3954*0a96aa3bSJed Brown ierr = VecRestoreArray(coordLocalVec,&coords);CHKERRQ(ierr); 3955*0a96aa3bSJed Brown PetscFunctionReturn(0); 3956*0a96aa3bSJed Brown } 3957*0a96aa3bSJed Brown 3958*0a96aa3bSJed Brown static PetscErrorCode DMPforestLocalizeCoordinates(DM dm, DM plex) 3959*0a96aa3bSJed Brown { 3960*0a96aa3bSJed Brown DM_Forest *forest; 3961*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 3962*0a96aa3bSJed Brown DM base; 3963*0a96aa3bSJed Brown Vec coordinates, cVec; 3964*0a96aa3bSJed Brown PetscSection oldSection, baseSection = NULL, newSection; 3965*0a96aa3bSJed Brown const PetscScalar *coords; 3966*0a96aa3bSJed Brown PetscScalar *coords2; 3967*0a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, coarsePoint; 3968*0a96aa3bSJed Brown PetscInt cDim, newStart, newEnd, dof, cdof = -1; 3969*0a96aa3bSJed Brown PetscInt v, vStart, vEnd, cp, cStart, cEnd, cEndInterior, *coarsePoints; 3970*0a96aa3bSJed Brown PetscInt *localize, overlap; 3971*0a96aa3bSJed Brown p4est_topidx_t flt, llt, t; 3972*0a96aa3bSJed Brown p4est_tree_t *trees; 3973*0a96aa3bSJed Brown PetscBool isper, baseLocalized = PETSC_FALSE; 3974*0a96aa3bSJed Brown PetscErrorCode ierr; 3975*0a96aa3bSJed Brown 3976*0a96aa3bSJed Brown PetscFunctionBegin; 3977*0a96aa3bSJed Brown ierr = DMGetPeriodicity(dm,&isper,NULL,NULL,NULL);CHKERRQ(ierr); 3978*0a96aa3bSJed Brown if (!isper) PetscFunctionReturn(0); 3979*0a96aa3bSJed Brown /* we localize on all cells if we don't have a base DM or the base DM coordinates have not been localized */ 3980*0a96aa3bSJed Brown ierr = DMGetCoordinateDim(dm, &cDim);CHKERRQ(ierr); 3981*0a96aa3bSJed Brown cdof = P4EST_CHILDREN*cDim; 3982*0a96aa3bSJed Brown ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr); 3983*0a96aa3bSJed Brown if (base) { 3984*0a96aa3bSJed Brown ierr = DMGetCoordinatesLocalized(base,&baseLocalized);CHKERRQ(ierr); 3985*0a96aa3bSJed Brown } 3986*0a96aa3bSJed Brown if (!baseLocalized) base = NULL; 3987*0a96aa3bSJed Brown ierr = DMPlexGetChart(plex, &newStart, &newEnd);CHKERRQ(ierr); 3988*0a96aa3bSJed Brown 3989*0a96aa3bSJed Brown ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr); 3990*0a96aa3bSJed Brown ierr = PetscCalloc1(overlap ? newEnd - newStart : 0,&localize);CHKERRQ(ierr); 3991*0a96aa3bSJed Brown 3992*0a96aa3bSJed Brown ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &newSection);CHKERRQ(ierr); 3993*0a96aa3bSJed Brown ierr = PetscSectionSetNumFields(newSection, 1);CHKERRQ(ierr); 3994*0a96aa3bSJed Brown ierr = PetscSectionSetFieldComponents(newSection, 0, cDim);CHKERRQ(ierr); 3995*0a96aa3bSJed Brown ierr = PetscSectionSetChart(newSection, newStart, newEnd);CHKERRQ(ierr); 3996*0a96aa3bSJed Brown 3997*0a96aa3bSJed Brown ierr = DMGetCoordinateSection(plex, &oldSection);CHKERRQ(ierr); 3998*0a96aa3bSJed Brown if (base) { ierr = DMGetCoordinateSection(base, &baseSection);CHKERRQ(ierr); } 3999*0a96aa3bSJed Brown ierr = DMPlexGetDepthStratum(plex,0,&vStart,&vEnd);CHKERRQ(ierr); 4000*0a96aa3bSJed Brown for (v = vStart; v < vEnd; ++v) { 4001*0a96aa3bSJed Brown ierr = PetscSectionGetDof(oldSection, v, &dof);CHKERRQ(ierr); 4002*0a96aa3bSJed Brown ierr = PetscSectionSetDof(newSection, v, dof);CHKERRQ(ierr); 4003*0a96aa3bSJed Brown ierr = PetscSectionSetFieldDof(newSection, v, 0, dof);CHKERRQ(ierr); 4004*0a96aa3bSJed Brown if (overlap) localize[v] = dof; 4005*0a96aa3bSJed Brown } 4006*0a96aa3bSJed Brown 4007*0a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 4008*0a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 4009*0a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 4010*0a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 4011*0a96aa3bSJed Brown flt = pforest->forest->first_local_tree; 4012*0a96aa3bSJed Brown llt = pforest->forest->last_local_tree; 4013*0a96aa3bSJed Brown trees = (p4est_tree_t*) pforest->forest->trees->array; 4014*0a96aa3bSJed Brown 4015*0a96aa3bSJed Brown cp = 0; 4016*0a96aa3bSJed Brown ierr = DMPlexGetHeightStratum(plex,0,&cStart,&cEnd);CHKERRQ(ierr); 4017*0a96aa3bSJed Brown ierr = DMPlexGetGhostCellStratum(plex,&cEndInterior,NULL);CHKERRQ(ierr); 4018*0a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 4019*0a96aa3bSJed Brown ierr = PetscMalloc1(cEnd-cStart,&coarsePoints);CHKERRQ(ierr); 4020*0a96aa3bSJed Brown if (cLocalStart > 0) { 4021*0a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 4022*0a96aa3bSJed Brown PetscInt count; 4023*0a96aa3bSJed Brown 4024*0a96aa3bSJed Brown for (count = 0; count < cLocalStart; count++) { 4025*0a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count]; 4026*0a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 4027*0a96aa3bSJed Brown 4028*0a96aa3bSJed Brown if (baseSection) { ierr = PetscSectionGetFieldDof(baseSection, coarsePoint, 0, &cdof);CHKERRQ(ierr); } 4029*0a96aa3bSJed Brown ierr = PetscSectionSetDof(newSection, count, cdof);CHKERRQ(ierr); 4030*0a96aa3bSJed Brown ierr = PetscSectionSetFieldDof(newSection, count, 0, cdof);CHKERRQ(ierr); 4031*0a96aa3bSJed Brown coarsePoints[cp++] = cdof ? coarsePoint : -1; 4032*0a96aa3bSJed Brown if (overlap) localize[count] = cdof; 4033*0a96aa3bSJed Brown } 4034*0a96aa3bSJed Brown } 4035*0a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 4036*0a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 4037*0a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 4038*0a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 4039*0a96aa3bSJed Brown PetscInt i; 4040*0a96aa3bSJed Brown 4041*0a96aa3bSJed Brown if (!numQuads) continue; 4042*0a96aa3bSJed Brown coarsePoint = t; 4043*0a96aa3bSJed Brown if (baseSection) { ierr = PetscSectionGetFieldDof(baseSection, coarsePoint, 0, &cdof);CHKERRQ(ierr); } 4044*0a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 4045*0a96aa3bSJed Brown PetscInt newCell = i + offset; 4046*0a96aa3bSJed Brown 4047*0a96aa3bSJed Brown ierr = PetscSectionSetDof(newSection, newCell, cdof);CHKERRQ(ierr); 4048*0a96aa3bSJed Brown ierr = PetscSectionSetFieldDof(newSection, newCell, 0, cdof);CHKERRQ(ierr); 4049*0a96aa3bSJed Brown coarsePoints[cp++] = cdof ? coarsePoint : -1; 4050*0a96aa3bSJed Brown if (overlap) localize[newCell] = cdof; 4051*0a96aa3bSJed Brown } 4052*0a96aa3bSJed Brown } 4053*0a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) { 4054*0a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t*) pforest->ghost->ghosts.array; 4055*0a96aa3bSJed Brown PetscInt numGhosts = (PetscInt) pforest->ghost->ghosts.elem_count; 4056*0a96aa3bSJed Brown PetscInt count; 4057*0a96aa3bSJed Brown 4058*0a96aa3bSJed Brown for (count = 0; count < numGhosts - cLocalStart; count++) { 4059*0a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart]; 4060*0a96aa3bSJed Brown coarsePoint = quad->p.which_tree; 4061*0a96aa3bSJed Brown PetscInt newCell = count + cLocalEnd; 4062*0a96aa3bSJed Brown 4063*0a96aa3bSJed Brown if (baseSection) { ierr = PetscSectionGetFieldDof(baseSection, coarsePoint, 0, &cdof);CHKERRQ(ierr); } 4064*0a96aa3bSJed Brown ierr = PetscSectionSetDof(newSection, newCell, cdof);CHKERRQ(ierr); 4065*0a96aa3bSJed Brown ierr = PetscSectionSetFieldDof(newSection, newCell, 0, cdof);CHKERRQ(ierr); 4066*0a96aa3bSJed Brown coarsePoints[cp++] = cdof ? coarsePoint : -1; 4067*0a96aa3bSJed Brown if (overlap) localize[newCell] = cdof; 4068*0a96aa3bSJed Brown } 4069*0a96aa3bSJed Brown } 4070*0a96aa3bSJed Brown if (cp != cEnd - cStart) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected number of fine cells %D != %D",cp,cEnd-cStart); 4071*0a96aa3bSJed Brown 4072*0a96aa3bSJed Brown if (base) { /* we need to localize on all the cells in the star of the coarse cell vertices */ 4073*0a96aa3bSJed Brown PetscInt *closure = NULL, closureSize; 4074*0a96aa3bSJed Brown PetscInt p, i, c, vStartBase, vEndBase, cStartBase, cEndBase; 4075*0a96aa3bSJed Brown 4076*0a96aa3bSJed Brown ierr = DMPlexGetHeightStratum(base,0,&cStartBase,&cEndBase);CHKERRQ(ierr); 4077*0a96aa3bSJed Brown ierr = DMPlexGetDepthStratum(base,0,&vStartBase,&vEndBase);CHKERRQ(ierr); 4078*0a96aa3bSJed Brown for (p = cStart; p < cEnd; p++) { 4079*0a96aa3bSJed Brown coarsePoint = coarsePoints[p-cStart]; 4080*0a96aa3bSJed Brown if (coarsePoint < 0) continue; 4081*0a96aa3bSJed Brown if (baseSection) { ierr = PetscSectionGetFieldDof(baseSection, coarsePoint, 0, &cdof);CHKERRQ(ierr); } 4082*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(base,coarsePoint,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 4083*0a96aa3bSJed Brown for (c = 0; c < closureSize; c++) { 4084*0a96aa3bSJed Brown PetscInt *star = NULL, starSize; 4085*0a96aa3bSJed Brown PetscInt j, v = closure[2 * c]; 4086*0a96aa3bSJed Brown 4087*0a96aa3bSJed Brown if (v < vStartBase || v > vEndBase) continue; 4088*0a96aa3bSJed Brown ierr = DMPlexGetTransitiveClosure(base,v,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 4089*0a96aa3bSJed Brown for (j = 0; j < starSize; j++) { 4090*0a96aa3bSJed Brown PetscInt cell = star[2 * j]; 4091*0a96aa3bSJed Brown 4092*0a96aa3bSJed Brown if (cStartBase <= cell && cell < cEndBase) { 4093*0a96aa3bSJed Brown p4est_tree_t *tree; 4094*0a96aa3bSJed Brown PetscInt offset,numQuads; 4095*0a96aa3bSJed Brown 4096*0a96aa3bSJed Brown if (cell < flt || cell > llt) continue; 4097*0a96aa3bSJed Brown tree = &(trees[cell]); 4098*0a96aa3bSJed Brown offset = cLocalStart + tree->quadrants_offset; 4099*0a96aa3bSJed Brown numQuads = (PetscInt) tree->quadrants.elem_count; 4100*0a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 4101*0a96aa3bSJed Brown PetscInt newCell = i + offset; 4102*0a96aa3bSJed Brown 4103*0a96aa3bSJed Brown ierr = PetscSectionSetDof(newSection, newCell, cdof);CHKERRQ(ierr); 4104*0a96aa3bSJed Brown ierr = PetscSectionSetFieldDof(newSection, newCell, 0, cdof);CHKERRQ(ierr); 4105*0a96aa3bSJed Brown if (overlap) localize[newCell] = cdof; 4106*0a96aa3bSJed Brown } 4107*0a96aa3bSJed Brown } 4108*0a96aa3bSJed Brown } 4109*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(base,v,PETSC_FALSE,&starSize,&star);CHKERRQ(ierr); 4110*0a96aa3bSJed Brown } 4111*0a96aa3bSJed Brown ierr = DMPlexRestoreTransitiveClosure(base,coarsePoint,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 4112*0a96aa3bSJed Brown } 4113*0a96aa3bSJed Brown } 4114*0a96aa3bSJed Brown ierr = PetscFree(coarsePoints);CHKERRQ(ierr); 4115*0a96aa3bSJed Brown 4116*0a96aa3bSJed Brown /* final consensus with overlap */ 4117*0a96aa3bSJed Brown if (overlap) { 4118*0a96aa3bSJed Brown PetscSF sf; 4119*0a96aa3bSJed Brown PetscInt *localizeGlobal; 4120*0a96aa3bSJed Brown 4121*0a96aa3bSJed Brown ierr = DMGetPointSF(plex,&sf);CHKERRQ(ierr); 4122*0a96aa3bSJed Brown ierr = PetscMalloc1(newEnd-newStart,&localizeGlobal);CHKERRQ(ierr); 4123*0a96aa3bSJed Brown for (v = newStart; v < newEnd; v++) localizeGlobal[v - newStart] = localize[v - newStart]; 4124*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(sf,MPIU_INT,localize,localizeGlobal,MPI_REPLACE);CHKERRQ(ierr); 4125*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(sf,MPIU_INT,localize,localizeGlobal,MPI_REPLACE);CHKERRQ(ierr); 4126*0a96aa3bSJed Brown for (v = newStart; v < newEnd; v++) { 4127*0a96aa3bSJed Brown ierr = PetscSectionSetDof(newSection, v, localizeGlobal[v-newStart]);CHKERRQ(ierr); 4128*0a96aa3bSJed Brown ierr = PetscSectionSetFieldDof(newSection, v, 0, localizeGlobal[v-newStart]);CHKERRQ(ierr); 4129*0a96aa3bSJed Brown } 4130*0a96aa3bSJed Brown ierr = PetscFree(localizeGlobal);CHKERRQ(ierr); 4131*0a96aa3bSJed Brown } 4132*0a96aa3bSJed Brown ierr = PetscFree(localize);CHKERRQ(ierr); 4133*0a96aa3bSJed Brown ierr = PetscSectionSetUp(newSection);CHKERRQ(ierr); 4134*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)oldSection);CHKERRQ(ierr); 4135*0a96aa3bSJed Brown ierr = DMSetCoordinateSection(plex, cDim, newSection);CHKERRQ(ierr); 4136*0a96aa3bSJed Brown ierr = PetscSectionGetStorageSize(newSection, &v);CHKERRQ(ierr); 4137*0a96aa3bSJed Brown ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 4138*0a96aa3bSJed Brown ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 4139*0a96aa3bSJed Brown ierr = VecSetBlockSize(cVec, cDim);CHKERRQ(ierr); 4140*0a96aa3bSJed Brown ierr = VecSetSizes(cVec, v, PETSC_DETERMINE);CHKERRQ(ierr); 4141*0a96aa3bSJed Brown ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 4142*0a96aa3bSJed Brown ierr = VecSet(cVec, PETSC_MIN_REAL);CHKERRQ(ierr); 4143*0a96aa3bSJed Brown 4144*0a96aa3bSJed Brown /* Copy over vertex coordinates */ 4145*0a96aa3bSJed Brown ierr = DMGetCoordinatesLocal(plex, &coordinates);CHKERRQ(ierr); 4146*0a96aa3bSJed Brown if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)plex),PETSC_ERR_SUP,"Missing local coordinates vector"); 4147*0a96aa3bSJed Brown ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 4148*0a96aa3bSJed Brown ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 4149*0a96aa3bSJed Brown for (v = vStart; v < vEnd; ++v) { 4150*0a96aa3bSJed Brown PetscInt d, off,off2; 4151*0a96aa3bSJed Brown 4152*0a96aa3bSJed Brown ierr = PetscSectionGetDof(oldSection, v, &dof);CHKERRQ(ierr); 4153*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(oldSection, v, &off);CHKERRQ(ierr); 4154*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(newSection, v, &off2);CHKERRQ(ierr); 4155*0a96aa3bSJed Brown for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 4156*0a96aa3bSJed Brown } 4157*0a96aa3bSJed Brown ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 4158*0a96aa3bSJed Brown 4159*0a96aa3bSJed Brown /* Localize coordinates on cells if needed */ 4160*0a96aa3bSJed Brown for (t = flt; t <= llt; t++) { 4161*0a96aa3bSJed Brown p4est_tree_t *tree = &(trees[t]); 4162*0a96aa3bSJed Brown const double *v = pforest->topo->conn->vertices; 4163*0a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t*) tree->quadrants.array; 4164*0a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset; 4165*0a96aa3bSJed Brown PetscInt numQuads = (PetscInt) tree->quadrants.elem_count; 4166*0a96aa3bSJed Brown p4est_topidx_t vt[8] = {0,0,0,0,0,0,0,0}; 4167*0a96aa3bSJed Brown PetscInt i,k; 4168*0a96aa3bSJed Brown 4169*0a96aa3bSJed Brown if (!numQuads) continue; 4170*0a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; ++k) { 4171*0a96aa3bSJed Brown vt[k] = pforest->topo->conn->tree_to_vertex[t * P4EST_CHILDREN + k]; 4172*0a96aa3bSJed Brown } 4173*0a96aa3bSJed Brown 4174*0a96aa3bSJed Brown for (i = 0; i < numQuads; i++) { 4175*0a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[i]; 4176*0a96aa3bSJed Brown const PetscReal intsize = 1.0 / P4EST_ROOT_LEN; 4177*0a96aa3bSJed Brown PetscReal h2; 4178*0a96aa3bSJed Brown PetscScalar xyz[3]; 4179*0a96aa3bSJed Brown #ifdef P4_TO_P8 4180*0a96aa3bSJed Brown PetscInt zi; 4181*0a96aa3bSJed Brown #endif 4182*0a96aa3bSJed Brown PetscInt yi,xi; 4183*0a96aa3bSJed Brown PetscInt off2; 4184*0a96aa3bSJed Brown PetscInt newCell = i + offset; 4185*0a96aa3bSJed Brown 4186*0a96aa3bSJed Brown ierr = PetscSectionGetFieldDof(newSection, newCell, 0, &cdof);CHKERRQ(ierr); 4187*0a96aa3bSJed Brown if (!cdof) continue; 4188*0a96aa3bSJed Brown 4189*0a96aa3bSJed Brown h2 = .5 * intsize * P4EST_QUADRANT_LEN (quad->level); 4190*0a96aa3bSJed Brown k = 0; 4191*0a96aa3bSJed Brown ierr = PetscSectionGetOffset(newSection, newCell, &off2);CHKERRQ(ierr); 4192*0a96aa3bSJed Brown #ifdef P4_TO_P8 4193*0a96aa3bSJed Brown for (zi = 0; zi < 2; ++zi) { 4194*0a96aa3bSJed Brown const PetscReal eta_z = intsize * quad->z + h2 * (1. + (zi * 2 - 1)); 4195*0a96aa3bSJed Brown #else 4196*0a96aa3bSJed Brown { 4197*0a96aa3bSJed Brown const PetscReal eta_z = 0.0; 4198*0a96aa3bSJed Brown #endif 4199*0a96aa3bSJed Brown for (yi = 0; yi < 2; ++yi) { 4200*0a96aa3bSJed Brown const PetscReal eta_y = intsize * quad->y + h2 * (1. + (yi * 2 - 1)); 4201*0a96aa3bSJed Brown for (xi = 0; xi < 2; ++xi) { 4202*0a96aa3bSJed Brown const PetscReal eta_x = intsize * quad->x + h2 * (1. + (xi * 2 - 1)); 4203*0a96aa3bSJed Brown PetscInt j; 4204*0a96aa3bSJed Brown 4205*0a96aa3bSJed Brown for (j = 0; j < 3; ++j) { 4206*0a96aa3bSJed Brown xyz[j] = ((1. - eta_z) * ((1. - eta_y) * ((1. - eta_x) * v[3 * vt[0] + j] + 4207*0a96aa3bSJed Brown eta_x * v[3 * vt[1] + j]) + 4208*0a96aa3bSJed Brown eta_y * ((1. - eta_x) * v[3 * vt[2] + j] + 4209*0a96aa3bSJed Brown eta_x * v[3 * vt[3] + j])) 4210*0a96aa3bSJed Brown + eta_z * ((1. - eta_y) * ((1. - eta_x) * v[3 * vt[4] + j] + 4211*0a96aa3bSJed Brown eta_x * v[3 * vt[5] + j]) + 4212*0a96aa3bSJed Brown eta_y * ((1. - eta_x) * v[3 * vt[6] + j] + 4213*0a96aa3bSJed Brown eta_x * v[3 * vt[7] + j]))); 4214*0a96aa3bSJed Brown } 4215*0a96aa3bSJed Brown for (j = 0; j < cDim; ++j) coords2[off2 + cDim*P4estVertToPetscVert[k] + j] = xyz[j]; 4216*0a96aa3bSJed Brown ++k; 4217*0a96aa3bSJed Brown } 4218*0a96aa3bSJed Brown } 4219*0a96aa3bSJed Brown } 4220*0a96aa3bSJed Brown } 4221*0a96aa3bSJed Brown } 4222*0a96aa3bSJed Brown ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 4223*0a96aa3bSJed Brown ierr = DMSetCoordinatesLocal(plex, cVec);CHKERRQ(ierr); 4224*0a96aa3bSJed Brown ierr = VecDestroy(&cVec);CHKERRQ(ierr); 4225*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4226*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&oldSection);CHKERRQ(ierr); 4227*0a96aa3bSJed Brown PetscFunctionReturn(0); 4228*0a96aa3bSJed Brown } 4229*0a96aa3bSJed Brown 4230*0a96aa3bSJed Brown #define DMForestClearAdaptivityForest_pforest _append_pforest(DMForestClearAdaptivityForest) 4231*0a96aa3bSJed Brown static PetscErrorCode DMForestClearAdaptivityForest_pforest(DM dm) 4232*0a96aa3bSJed Brown { 4233*0a96aa3bSJed Brown DM_Forest *forest; 4234*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 4235*0a96aa3bSJed Brown PetscErrorCode ierr; 4236*0a96aa3bSJed Brown 4237*0a96aa3bSJed Brown PetscFunctionBegin; 4238*0a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 4239*0a96aa3bSJed Brown pforest = (DM_Forest_pforest *) forest->data; 4240*0a96aa3bSJed Brown ierr = PetscSFDestroy(&(pforest->pointAdaptToSelfSF));CHKERRQ(ierr); 4241*0a96aa3bSJed Brown ierr = PetscSFDestroy(&(pforest->pointSelfToAdaptSF));CHKERRQ(ierr); 4242*0a96aa3bSJed Brown ierr = PetscFree(pforest->pointAdaptToSelfCids);CHKERRQ(ierr); 4243*0a96aa3bSJed Brown ierr = PetscFree(pforest->pointSelfToAdaptCids);CHKERRQ(ierr); 4244*0a96aa3bSJed Brown PetscFunctionReturn(0); 4245*0a96aa3bSJed Brown } 4246*0a96aa3bSJed Brown 4247*0a96aa3bSJed Brown static PetscErrorCode DMConvert_pforest_plex(DM dm, DMType newtype, DM *plex) 4248*0a96aa3bSJed Brown { 4249*0a96aa3bSJed Brown DM_Forest *forest; 4250*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 4251*0a96aa3bSJed Brown DM refTree, newPlex, base; 4252*0a96aa3bSJed Brown PetscInt adjDim, adjCodim, coordDim; 4253*0a96aa3bSJed Brown MPI_Comm comm; 4254*0a96aa3bSJed Brown PetscBool isPforest; 4255*0a96aa3bSJed Brown PetscInt dim; 4256*0a96aa3bSJed Brown PetscInt overlap; 4257*0a96aa3bSJed Brown p4est_connect_type_t ctype; 4258*0a96aa3bSJed Brown p4est_locidx_t first_local_quad = -1; 4259*0a96aa3bSJed Brown sc_array_t *points_per_dim, *cone_sizes, *cones, *cone_orientations, *coords, *children, *parents, *childids, *leaves, *remotes; 4260*0a96aa3bSJed Brown PetscSection parentSection; 4261*0a96aa3bSJed Brown PetscSF pointSF; 4262*0a96aa3bSJed Brown size_t zz, count; 4263*0a96aa3bSJed Brown PetscInt pStart, pEnd; 4264*0a96aa3bSJed Brown DMLabel ghostLabelBase = NULL; 4265*0a96aa3bSJed Brown PetscErrorCode ierr; 4266*0a96aa3bSJed Brown 4267*0a96aa3bSJed Brown PetscFunctionBegin; 4268*0a96aa3bSJed Brown 4269*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4270*0a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm); 4271*0a96aa3bSJed Brown ierr = PetscObjectTypeCompare((PetscObject)dm,DMPFOREST,&isPforest);CHKERRQ(ierr); 4272*0a96aa3bSJed Brown if (!isPforest) SETERRQ2(comm,PETSC_ERR_ARG_WRONG,"Expected DM type %s, got %s",DMPFOREST,((PetscObject)dm)->type_name); 4273*0a96aa3bSJed Brown ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 4274*0a96aa3bSJed Brown if (dim != P4EST_DIM) SETERRQ2(comm,PETSC_ERR_ARG_WRONG,"Expected DM dimension %d, got %d",P4EST_DIM,dim); 4275*0a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 4276*0a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 4277*0a96aa3bSJed Brown ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr); 4278*0a96aa3bSJed Brown if (base) { 4279*0a96aa3bSJed Brown ierr = DMGetLabel(base,"ghost",&ghostLabelBase);CHKERRQ(ierr); 4280*0a96aa3bSJed Brown } 4281*0a96aa3bSJed Brown if (!pforest->plex) { 4282*0a96aa3bSJed Brown PetscMPIInt size; 4283*0a96aa3bSJed Brown 4284*0a96aa3bSJed Brown ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 4285*0a96aa3bSJed Brown ierr = DMCreate(comm,&newPlex);CHKERRQ(ierr); 4286*0a96aa3bSJed Brown ierr = DMSetType(newPlex,DMPLEX);CHKERRQ(ierr); 4287*0a96aa3bSJed Brown ierr = DMSetMatType(newPlex,dm->mattype);CHKERRQ(ierr); 4288*0a96aa3bSJed Brown /* share labels */ 4289*0a96aa3bSJed Brown ierr = DMCopyLabels(dm, newPlex, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL);CHKERRQ(ierr); 4290*0a96aa3bSJed Brown ierr = DMForestGetAdjacencyDimension(dm,&adjDim);CHKERRQ(ierr); 4291*0a96aa3bSJed Brown ierr = DMForestGetAdjacencyCodimension(dm,&adjCodim);CHKERRQ(ierr); 4292*0a96aa3bSJed Brown ierr = DMGetCoordinateDim(dm,&coordDim);CHKERRQ(ierr); 4293*0a96aa3bSJed Brown if (adjDim == 0) { 4294*0a96aa3bSJed Brown ctype = P4EST_CONNECT_FULL; 4295*0a96aa3bSJed Brown } else if (adjCodim == 1) { 4296*0a96aa3bSJed Brown ctype = P4EST_CONNECT_FACE; 4297*0a96aa3bSJed Brown #if defined(P4_TO_P8) 4298*0a96aa3bSJed Brown } else if (adjDim == 1) { 4299*0a96aa3bSJed Brown ctype = P8EST_CONNECT_EDGE; 4300*0a96aa3bSJed Brown #endif 4301*0a96aa3bSJed Brown } else { 4302*0a96aa3bSJed Brown SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONG,"Invalid adjacency dimension %d",adjDim); 4303*0a96aa3bSJed Brown } 4304*0a96aa3bSJed Brown if (ctype != P4EST_CONNECT_FULL) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONG,"Adjacency dimension %D / codimension %D not supported yet",adjDim,adjCodim); 4305*0a96aa3bSJed Brown ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr); 4306*0a96aa3bSJed Brown ((DM_Plex *) newPlex->data)->overlap = overlap; 4307*0a96aa3bSJed Brown 4308*0a96aa3bSJed Brown points_per_dim = sc_array_new(sizeof(p4est_locidx_t)); 4309*0a96aa3bSJed Brown cone_sizes = sc_array_new(sizeof(p4est_locidx_t)); 4310*0a96aa3bSJed Brown cones = sc_array_new(sizeof(p4est_locidx_t)); 4311*0a96aa3bSJed Brown cone_orientations = sc_array_new(sizeof(p4est_locidx_t)); 4312*0a96aa3bSJed Brown coords = sc_array_new(3 * sizeof(double)); 4313*0a96aa3bSJed Brown children = sc_array_new(sizeof(p4est_locidx_t)); 4314*0a96aa3bSJed Brown parents = sc_array_new(sizeof(p4est_locidx_t)); 4315*0a96aa3bSJed Brown childids = sc_array_new(sizeof(p4est_locidx_t)); 4316*0a96aa3bSJed Brown leaves = sc_array_new(sizeof(p4est_locidx_t)); 4317*0a96aa3bSJed Brown remotes = sc_array_new(2 * sizeof(p4est_locidx_t)); 4318*0a96aa3bSJed Brown 4319*0a96aa3bSJed 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)); 4320*0a96aa3bSJed Brown 4321*0a96aa3bSJed Brown pforest->cLocalStart = (PetscInt) first_local_quad; 4322*0a96aa3bSJed Brown pforest->cLocalEnd = pforest->cLocalStart + (PetscInt) pforest->forest->local_num_quadrants; 4323*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(points_per_dim);CHKERRQ(ierr); 4324*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(cone_sizes);CHKERRQ(ierr); 4325*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(cones);CHKERRQ(ierr); 4326*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(cone_orientations);CHKERRQ(ierr); 4327*0a96aa3bSJed Brown ierr = coords_double_to_PetscScalar(coords, coordDim);CHKERRQ(ierr); 4328*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(children);CHKERRQ(ierr); 4329*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(parents);CHKERRQ(ierr); 4330*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(childids);CHKERRQ(ierr); 4331*0a96aa3bSJed Brown ierr = locidx_to_PetscInt(leaves);CHKERRQ(ierr); 4332*0a96aa3bSJed Brown ierr = locidx_pair_to_PetscSFNode(remotes);CHKERRQ(ierr); 4333*0a96aa3bSJed Brown 4334*0a96aa3bSJed Brown ierr = DMSetDimension(newPlex,P4EST_DIM);CHKERRQ(ierr); 4335*0a96aa3bSJed Brown ierr = DMSetCoordinateDim(newPlex,coordDim);CHKERRQ(ierr); 4336*0a96aa3bSJed Brown ierr = DMPlexSetMaxProjectionHeight(newPlex,P4EST_DIM - 1);CHKERRQ(ierr); 4337*0a96aa3bSJed Brown ierr = DMPlexCreateFromDAG(newPlex,P4EST_DIM,(PetscInt*)points_per_dim->array,(PetscInt*)cone_sizes->array,(PetscInt*)cones->array,(PetscInt*)cone_orientations->array,(PetscScalar*)coords->array);CHKERRQ(ierr); 4338*0a96aa3bSJed Brown ierr = DMPlexConvertOldOrientations_Internal(newPlex);CHKERRQ(ierr); 4339*0a96aa3bSJed Brown ierr = DMCreateReferenceTree_pforest(comm,&refTree);CHKERRQ(ierr); 4340*0a96aa3bSJed Brown ierr = DMPlexSetReferenceTree(newPlex,refTree);CHKERRQ(ierr); 4341*0a96aa3bSJed Brown ierr = PetscSectionCreate(comm,&parentSection);CHKERRQ(ierr); 4342*0a96aa3bSJed Brown ierr = DMPlexGetChart(newPlex,&pStart,&pEnd);CHKERRQ(ierr); 4343*0a96aa3bSJed Brown ierr = PetscSectionSetChart(parentSection,pStart,pEnd);CHKERRQ(ierr); 4344*0a96aa3bSJed Brown count = children->elem_count; 4345*0a96aa3bSJed Brown for (zz = 0; zz < count; zz++) { 4346*0a96aa3bSJed Brown PetscInt child = *((PetscInt*) sc_array_index(children,zz)); 4347*0a96aa3bSJed Brown 4348*0a96aa3bSJed Brown ierr = PetscSectionSetDof(parentSection,child,1);CHKERRQ(ierr); 4349*0a96aa3bSJed Brown } 4350*0a96aa3bSJed Brown ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 4351*0a96aa3bSJed Brown ierr = DMPlexSetTree(newPlex,parentSection,(PetscInt*)parents->array,(PetscInt*)childids->array);CHKERRQ(ierr); 4352*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 4353*0a96aa3bSJed Brown ierr = PetscSFCreate(comm,&pointSF);CHKERRQ(ierr); 4354*0a96aa3bSJed Brown /* 4355*0a96aa3bSJed Brown These arrays defining the sf are from the p4est library, but the code there shows the leaves being populated in increasing order. 4356*0a96aa3bSJed Brown https://gitlab.com/petsc/petsc/merge_requests/2248#note_240186391 4357*0a96aa3bSJed Brown */ 4358*0a96aa3bSJed Brown ierr = PetscSFSetGraph(pointSF,pEnd - pStart,(PetscInt)leaves->elem_count,(PetscInt*)leaves->array,PETSC_COPY_VALUES,(PetscSFNode*)remotes->array,PETSC_COPY_VALUES);CHKERRQ(ierr); 4359*0a96aa3bSJed Brown ierr = DMSetPointSF(newPlex,pointSF);CHKERRQ(ierr); 4360*0a96aa3bSJed Brown ierr = DMSetPointSF(dm,pointSF);CHKERRQ(ierr); 4361*0a96aa3bSJed Brown { 4362*0a96aa3bSJed Brown DM coordDM; 4363*0a96aa3bSJed Brown 4364*0a96aa3bSJed Brown ierr = DMGetCoordinateDM(newPlex,&coordDM);CHKERRQ(ierr); 4365*0a96aa3bSJed Brown ierr = DMSetPointSF(coordDM,pointSF);CHKERRQ(ierr); 4366*0a96aa3bSJed Brown } 4367*0a96aa3bSJed Brown ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 4368*0a96aa3bSJed Brown sc_array_destroy (points_per_dim); 4369*0a96aa3bSJed Brown sc_array_destroy (cone_sizes); 4370*0a96aa3bSJed Brown sc_array_destroy (cones); 4371*0a96aa3bSJed Brown sc_array_destroy (cone_orientations); 4372*0a96aa3bSJed Brown sc_array_destroy (coords); 4373*0a96aa3bSJed Brown sc_array_destroy (children); 4374*0a96aa3bSJed Brown sc_array_destroy (parents); 4375*0a96aa3bSJed Brown sc_array_destroy (childids); 4376*0a96aa3bSJed Brown sc_array_destroy (leaves); 4377*0a96aa3bSJed Brown sc_array_destroy (remotes); 4378*0a96aa3bSJed Brown 4379*0a96aa3bSJed Brown { 4380*0a96aa3bSJed Brown PetscBool isper; 4381*0a96aa3bSJed Brown const PetscReal *maxCell, *L; 4382*0a96aa3bSJed Brown const DMBoundaryType *bd; 4383*0a96aa3bSJed Brown 4384*0a96aa3bSJed Brown ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 4385*0a96aa3bSJed Brown ierr = DMSetPeriodicity(newPlex,isper,maxCell,L,bd);CHKERRQ(ierr); 4386*0a96aa3bSJed Brown ierr = DMPforestLocalizeCoordinates(dm,newPlex);CHKERRQ(ierr); 4387*0a96aa3bSJed Brown } 4388*0a96aa3bSJed Brown 4389*0a96aa3bSJed Brown if (overlap > 0) { /* the p4est routine can't set all of the coordinates in its routine if there is overlap */ 4390*0a96aa3bSJed Brown Vec coordsGlobal, coordsLocal; 4391*0a96aa3bSJed Brown const PetscScalar *globalArray; 4392*0a96aa3bSJed Brown PetscScalar *localArray; 4393*0a96aa3bSJed Brown PetscSF coordSF; 4394*0a96aa3bSJed Brown DM coordDM; 4395*0a96aa3bSJed Brown 4396*0a96aa3bSJed Brown ierr = DMGetCoordinateDM(newPlex,&coordDM);CHKERRQ(ierr); 4397*0a96aa3bSJed Brown ierr = DMGetSectionSF(coordDM,&coordSF);CHKERRQ(ierr); 4398*0a96aa3bSJed Brown ierr = DMGetCoordinates(newPlex, &coordsGlobal);CHKERRQ(ierr); 4399*0a96aa3bSJed Brown ierr = DMGetCoordinatesLocal(newPlex, &coordsLocal);CHKERRQ(ierr); 4400*0a96aa3bSJed Brown ierr = VecGetArrayRead(coordsGlobal, &globalArray);CHKERRQ(ierr); 4401*0a96aa3bSJed Brown ierr = VecGetArray(coordsLocal, &localArray);CHKERRQ(ierr); 4402*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(coordSF,MPIU_SCALAR,globalArray,localArray,MPI_REPLACE);CHKERRQ(ierr); 4403*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(coordSF,MPIU_SCALAR,globalArray,localArray,MPI_REPLACE);CHKERRQ(ierr); 4404*0a96aa3bSJed Brown ierr = VecRestoreArray(coordsLocal, &localArray);CHKERRQ(ierr); 4405*0a96aa3bSJed Brown ierr = VecRestoreArrayRead(coordsGlobal, &globalArray);CHKERRQ(ierr); 4406*0a96aa3bSJed Brown ierr = DMSetCoordinatesLocal(newPlex, coordsLocal);CHKERRQ(ierr); 4407*0a96aa3bSJed Brown } 4408*0a96aa3bSJed Brown ierr = DMPforestMapCoordinates(dm,newPlex);CHKERRQ(ierr); 4409*0a96aa3bSJed Brown 4410*0a96aa3bSJed Brown pforest->plex = newPlex; 4411*0a96aa3bSJed Brown 4412*0a96aa3bSJed Brown /* copy labels */ 4413*0a96aa3bSJed Brown ierr = DMPforestLabelsFinalize(dm,newPlex);CHKERRQ(ierr); 4414*0a96aa3bSJed Brown 4415*0a96aa3bSJed Brown if (ghostLabelBase || pforest->ghostName) { /* we have to do this after copying labels because the labels drive the construction of ghost cells */ 4416*0a96aa3bSJed Brown PetscInt numAdded; 4417*0a96aa3bSJed Brown DM newPlexGhosted; 4418*0a96aa3bSJed Brown void *ctx; 4419*0a96aa3bSJed Brown 4420*0a96aa3bSJed Brown ierr = DMPlexConstructGhostCells(newPlex,pforest->ghostName,&numAdded,&newPlexGhosted);CHKERRQ(ierr); 4421*0a96aa3bSJed Brown ierr = DMGetApplicationContext(newPlex,&ctx);CHKERRQ(ierr); 4422*0a96aa3bSJed Brown ierr = DMSetApplicationContext(newPlexGhosted,ctx);CHKERRQ(ierr); 4423*0a96aa3bSJed Brown /* we want the sf for the ghost dm to be the one for the p4est dm as well */ 4424*0a96aa3bSJed Brown ierr = DMGetPointSF(newPlexGhosted,&pointSF);CHKERRQ(ierr); 4425*0a96aa3bSJed Brown ierr = DMSetPointSF(dm,pointSF);CHKERRQ(ierr); 4426*0a96aa3bSJed Brown ierr = DMDestroy(&newPlex);CHKERRQ(ierr); 4427*0a96aa3bSJed Brown ierr = DMPlexSetReferenceTree(newPlexGhosted,refTree);CHKERRQ(ierr); 4428*0a96aa3bSJed Brown ierr = DMForestClearAdaptivityForest_pforest(dm);CHKERRQ(ierr); 4429*0a96aa3bSJed Brown newPlex = newPlexGhosted; 4430*0a96aa3bSJed Brown 4431*0a96aa3bSJed Brown /* share the labels back */ 4432*0a96aa3bSJed Brown ierr = DMDestroyLabelLinkList_Internal(dm);CHKERRQ(ierr); 4433*0a96aa3bSJed Brown ierr = DMCopyLabels(newPlex, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL);CHKERRQ(ierr); 4434*0a96aa3bSJed Brown pforest->plex = newPlex; 4435*0a96aa3bSJed Brown } 4436*0a96aa3bSJed Brown ierr = DMDestroy(&refTree);CHKERRQ(ierr); 4437*0a96aa3bSJed Brown if (dm->setfromoptionscalled) { 4438*0a96aa3bSJed Brown ierr = PetscObjectOptionsBegin((PetscObject)newPlex);CHKERRQ(ierr); 4439*0a96aa3bSJed Brown ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject,newPlex);CHKERRQ(ierr); 4440*0a96aa3bSJed Brown ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) newPlex);CHKERRQ(ierr); 4441*0a96aa3bSJed Brown ierr = PetscOptionsEnd();CHKERRQ(ierr); 4442*0a96aa3bSJed Brown } 4443*0a96aa3bSJed Brown ierr = DMViewFromOptions(newPlex,NULL,"-dm_p4est_plex_view");CHKERRQ(ierr); 4444*0a96aa3bSJed Brown { 4445*0a96aa3bSJed Brown PetscSection coordsSec; 4446*0a96aa3bSJed Brown Vec coords; 4447*0a96aa3bSJed Brown PetscInt cDim; 4448*0a96aa3bSJed Brown 4449*0a96aa3bSJed Brown ierr = DMGetCoordinateDim(newPlex,&cDim);CHKERRQ(ierr); 4450*0a96aa3bSJed Brown ierr = DMGetCoordinateSection(newPlex,&coordsSec);CHKERRQ(ierr); 4451*0a96aa3bSJed Brown ierr = DMSetCoordinateSection(dm,cDim,coordsSec);CHKERRQ(ierr); 4452*0a96aa3bSJed Brown ierr = DMGetCoordinatesLocal(newPlex,&coords);CHKERRQ(ierr); 4453*0a96aa3bSJed Brown ierr = DMSetCoordinatesLocal(dm,coords);CHKERRQ(ierr); 4454*0a96aa3bSJed Brown } 4455*0a96aa3bSJed Brown } 4456*0a96aa3bSJed Brown newPlex = pforest->plex; 4457*0a96aa3bSJed Brown if (plex) { 4458*0a96aa3bSJed Brown DM coordDM; 4459*0a96aa3bSJed Brown 4460*0a96aa3bSJed Brown ierr = DMClone(newPlex,plex);CHKERRQ(ierr); 4461*0a96aa3bSJed Brown ierr = DMGetCoordinateDM(newPlex,&coordDM);CHKERRQ(ierr); 4462*0a96aa3bSJed Brown ierr = DMSetCoordinateDM(*plex,coordDM);CHKERRQ(ierr); 4463*0a96aa3bSJed Brown ierr = DMShareDiscretization(dm,*plex);CHKERRQ(ierr); 4464*0a96aa3bSJed Brown } 4465*0a96aa3bSJed Brown PetscFunctionReturn(0); 4466*0a96aa3bSJed Brown } 4467*0a96aa3bSJed Brown 4468*0a96aa3bSJed Brown static PetscErrorCode DMSetFromOptions_pforest(PetscOptionItems *PetscOptionsObject,DM dm) 4469*0a96aa3bSJed Brown { 4470*0a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 4471*0a96aa3bSJed Brown char stringBuffer[256]; 4472*0a96aa3bSJed Brown PetscBool flg; 4473*0a96aa3bSJed Brown PetscErrorCode ierr; 4474*0a96aa3bSJed Brown 4475*0a96aa3bSJed Brown PetscFunctionBegin; 4476*0a96aa3bSJed Brown ierr = DMSetFromOptions_Forest(PetscOptionsObject,dm);CHKERRQ(ierr); 4477*0a96aa3bSJed Brown ierr = PetscOptionsHead(PetscOptionsObject,"DM" P4EST_STRING " options");CHKERRQ(ierr); 4478*0a96aa3bSJed Brown ierr = PetscOptionsBool("-dm_p4est_partition_for_coarsening","partition forest to allow for coarsening","DMP4estSetPartitionForCoarsening",pforest->partition_for_coarsening,&(pforest->partition_for_coarsening),NULL);CHKERRQ(ierr); 4479*0a96aa3bSJed Brown ierr = PetscOptionsString("-dm_p4est_ghost_label_name","the name of the ghost label when converting from a DMPlex",NULL,NULL,stringBuffer,sizeof(stringBuffer),&flg);CHKERRQ(ierr); 4480*0a96aa3bSJed Brown ierr = PetscOptionsTail();CHKERRQ(ierr); 4481*0a96aa3bSJed Brown if (flg) { 4482*0a96aa3bSJed Brown ierr = PetscFree(pforest->ghostName);CHKERRQ(ierr); 4483*0a96aa3bSJed Brown ierr = PetscStrallocpy(stringBuffer,&pforest->ghostName);CHKERRQ(ierr); 4484*0a96aa3bSJed Brown } 4485*0a96aa3bSJed Brown PetscFunctionReturn(0); 4486*0a96aa3bSJed Brown } 4487*0a96aa3bSJed Brown 4488*0a96aa3bSJed Brown #if !defined(P4_TO_P8) 4489*0a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP4estGetPartitionForCoarsening 4490*0a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP4estSetPartitionForCoarsening 4491*0a96aa3bSJed Brown #else 4492*0a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP8estGetPartitionForCoarsening 4493*0a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP8estSetPartitionForCoarsening 4494*0a96aa3bSJed Brown #endif 4495*0a96aa3bSJed Brown 4496*0a96aa3bSJed Brown PETSC_EXTERN PetscErrorCode DMPforestGetPartitionForCoarsening(DM dm, PetscBool *flg) 4497*0a96aa3bSJed Brown { 4498*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 4499*0a96aa3bSJed Brown 4500*0a96aa3bSJed Brown PetscFunctionBegin; 4501*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4502*0a96aa3bSJed Brown pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 4503*0a96aa3bSJed Brown *flg = pforest->partition_for_coarsening; 4504*0a96aa3bSJed Brown PetscFunctionReturn(0); 4505*0a96aa3bSJed Brown } 4506*0a96aa3bSJed Brown 4507*0a96aa3bSJed Brown PETSC_EXTERN PetscErrorCode DMPforestSetPartitionForCoarsening(DM dm, PetscBool flg) 4508*0a96aa3bSJed Brown { 4509*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 4510*0a96aa3bSJed Brown 4511*0a96aa3bSJed Brown PetscFunctionBegin; 4512*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4513*0a96aa3bSJed Brown pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 4514*0a96aa3bSJed Brown pforest->partition_for_coarsening = flg; 4515*0a96aa3bSJed Brown PetscFunctionReturn(0); 4516*0a96aa3bSJed Brown } 4517*0a96aa3bSJed Brown 4518*0a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM dm,DM *plex) 4519*0a96aa3bSJed Brown { 4520*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 4521*0a96aa3bSJed Brown PetscErrorCode ierr; 4522*0a96aa3bSJed Brown 4523*0a96aa3bSJed Brown PetscFunctionBegin; 4524*0a96aa3bSJed Brown if (plex) *plex = NULL; 4525*0a96aa3bSJed Brown ierr = DMSetUp(dm);CHKERRQ(ierr); 4526*0a96aa3bSJed Brown pforest = (DM_Forest_pforest*) ((DM_Forest*) dm->data)->data; 4527*0a96aa3bSJed Brown if (!pforest->plex) { 4528*0a96aa3bSJed Brown ierr = DMConvert_pforest_plex(dm,DMPLEX,NULL);CHKERRQ(ierr); 4529*0a96aa3bSJed Brown } 4530*0a96aa3bSJed Brown ierr = DMShareDiscretization(dm,pforest->plex);CHKERRQ(ierr); 4531*0a96aa3bSJed Brown if (plex) *plex = pforest->plex; 4532*0a96aa3bSJed Brown PetscFunctionReturn(0); 4533*0a96aa3bSJed Brown } 4534*0a96aa3bSJed Brown 4535*0a96aa3bSJed Brown #define DMCreateInterpolation_pforest _append_pforest(DMCreateInterpolation) 4536*0a96aa3bSJed Brown static PetscErrorCode DMCreateInterpolation_pforest(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 4537*0a96aa3bSJed Brown { 4538*0a96aa3bSJed Brown PetscSection gsc, gsf; 4539*0a96aa3bSJed Brown PetscInt m, n; 4540*0a96aa3bSJed Brown DM cdm; 4541*0a96aa3bSJed Brown PetscErrorCode ierr; 4542*0a96aa3bSJed Brown 4543*0a96aa3bSJed Brown PetscFunctionBegin; 4544*0a96aa3bSJed Brown ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 4545*0a96aa3bSJed Brown ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 4546*0a96aa3bSJed Brown ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 4547*0a96aa3bSJed Brown ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 4548*0a96aa3bSJed Brown 4549*0a96aa3bSJed Brown ierr = MatCreate(PetscObjectComm((PetscObject) dmFine), interpolation);CHKERRQ(ierr); 4550*0a96aa3bSJed Brown ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 4551*0a96aa3bSJed Brown ierr = MatSetType(*interpolation, MATAIJ);CHKERRQ(ierr); 4552*0a96aa3bSJed Brown 4553*0a96aa3bSJed Brown ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 4554*0a96aa3bSJed Brown if (cdm != dmCoarse) SETERRQ(PetscObjectComm((PetscObject)dmFine),PETSC_ERR_SUP,"Only interpolation from coarse DM for now"); 4555*0a96aa3bSJed Brown 4556*0a96aa3bSJed Brown { 4557*0a96aa3bSJed Brown DM plexF, plexC; 4558*0a96aa3bSJed Brown PetscSF sf; 4559*0a96aa3bSJed Brown PetscInt *cids; 4560*0a96aa3bSJed Brown PetscInt dofPerDim[4] = {1,1,1,1}; 4561*0a96aa3bSJed Brown 4562*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dmCoarse,&plexC);CHKERRQ(ierr); 4563*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dmFine,&plexF);CHKERRQ(ierr); 4564*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids);CHKERRQ(ierr); 4565*0a96aa3bSJed Brown ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 4566*0a96aa3bSJed Brown ierr = DMPlexComputeInterpolatorTree(plexC, plexF, sf, cids, *interpolation);CHKERRQ(ierr); 4567*0a96aa3bSJed Brown ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 4568*0a96aa3bSJed Brown ierr = PetscFree(cids);CHKERRQ(ierr); 4569*0a96aa3bSJed Brown } 4570*0a96aa3bSJed Brown ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 4571*0a96aa3bSJed Brown /* Use naive scaling */ 4572*0a96aa3bSJed Brown ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 4573*0a96aa3bSJed Brown PetscFunctionReturn(0); 4574*0a96aa3bSJed Brown } 4575*0a96aa3bSJed Brown 4576*0a96aa3bSJed Brown #define DMCreateInjection_pforest _append_pforest(DMCreateInjection) 4577*0a96aa3bSJed Brown static PetscErrorCode DMCreateInjection_pforest(DM dmCoarse, DM dmFine, Mat *injection) 4578*0a96aa3bSJed Brown { 4579*0a96aa3bSJed Brown PetscSection gsc, gsf; 4580*0a96aa3bSJed Brown PetscInt m, n; 4581*0a96aa3bSJed Brown DM cdm; 4582*0a96aa3bSJed Brown PetscErrorCode ierr; 4583*0a96aa3bSJed Brown 4584*0a96aa3bSJed Brown PetscFunctionBegin; 4585*0a96aa3bSJed Brown ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 4586*0a96aa3bSJed Brown ierr = PetscSectionGetConstrainedStorageSize(gsf, &n);CHKERRQ(ierr); 4587*0a96aa3bSJed Brown ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 4588*0a96aa3bSJed Brown ierr = PetscSectionGetConstrainedStorageSize(gsc, &m);CHKERRQ(ierr); 4589*0a96aa3bSJed Brown 4590*0a96aa3bSJed Brown ierr = MatCreate(PetscObjectComm((PetscObject) dmFine), injection);CHKERRQ(ierr); 4591*0a96aa3bSJed Brown ierr = MatSetSizes(*injection, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 4592*0a96aa3bSJed Brown ierr = MatSetType(*injection, MATAIJ);CHKERRQ(ierr); 4593*0a96aa3bSJed Brown 4594*0a96aa3bSJed Brown ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 4595*0a96aa3bSJed Brown if (cdm != dmCoarse) SETERRQ(PetscObjectComm((PetscObject)dmFine),PETSC_ERR_SUP,"Only injection to coarse DM for now"); 4596*0a96aa3bSJed Brown 4597*0a96aa3bSJed Brown { 4598*0a96aa3bSJed Brown DM plexF, plexC; 4599*0a96aa3bSJed Brown PetscSF sf; 4600*0a96aa3bSJed Brown PetscInt *cids; 4601*0a96aa3bSJed Brown PetscInt dofPerDim[4] = {1,1,1,1}; 4602*0a96aa3bSJed Brown 4603*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dmCoarse,&plexC);CHKERRQ(ierr); 4604*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dmFine,&plexF);CHKERRQ(ierr); 4605*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids);CHKERRQ(ierr); 4606*0a96aa3bSJed Brown ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 4607*0a96aa3bSJed Brown ierr = DMPlexComputeInjectorTree(plexC, plexF, sf, cids, *injection);CHKERRQ(ierr); 4608*0a96aa3bSJed Brown ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 4609*0a96aa3bSJed Brown ierr = PetscFree(cids);CHKERRQ(ierr); 4610*0a96aa3bSJed Brown } 4611*0a96aa3bSJed Brown ierr = MatViewFromOptions(*injection, NULL, "-inject_mat_view");CHKERRQ(ierr); 4612*0a96aa3bSJed Brown /* Use naive scaling */ 4613*0a96aa3bSJed Brown PetscFunctionReturn(0); 4614*0a96aa3bSJed Brown } 4615*0a96aa3bSJed Brown 4616*0a96aa3bSJed Brown #define DMForestTransferVecFromBase_pforest _append_pforest(DMForestTransferVecFromBase) 4617*0a96aa3bSJed Brown static PetscErrorCode DMForestTransferVecFromBase_pforest(DM dm, Vec vecIn, Vec vecOut) 4618*0a96aa3bSJed Brown { 4619*0a96aa3bSJed Brown DM dmIn, dmVecIn, base, basec, plex, coarseDM; 4620*0a96aa3bSJed Brown DM *hierarchy; 4621*0a96aa3bSJed Brown PetscSF sfRed = NULL; 4622*0a96aa3bSJed Brown PetscDS ds; 4623*0a96aa3bSJed Brown Vec vecInLocal, vecOutLocal; 4624*0a96aa3bSJed Brown DMLabel subpointMap; 4625*0a96aa3bSJed Brown PetscInt minLevel, mh, n_hi, i; 4626*0a96aa3bSJed Brown PetscBool hiforest, *hierarchy_forest; 4627*0a96aa3bSJed Brown PetscErrorCode ierr; 4628*0a96aa3bSJed Brown 4629*0a96aa3bSJed Brown PetscFunctionBegin; 4630*0a96aa3bSJed Brown ierr = VecGetDM(vecIn,&dmVecIn);CHKERRQ(ierr); 4631*0a96aa3bSJed Brown ierr = DMGetDS(dmVecIn,&ds);CHKERRQ(ierr); 4632*0a96aa3bSJed Brown if (!ds) SETERRQ(PetscObjectComm((PetscObject)dmVecIn),PETSC_ERR_SUP,"Cannot transfer without a PetscDS object"); 4633*0a96aa3bSJed Brown { /* we cannot stick user contexts into function callbacks for DMProjectFieldLocal! */ 4634*0a96aa3bSJed Brown PetscSection section; 4635*0a96aa3bSJed Brown PetscInt Nf; 4636*0a96aa3bSJed Brown 4637*0a96aa3bSJed Brown ierr = DMGetLocalSection(dmVecIn,§ion);CHKERRQ(ierr); 4638*0a96aa3bSJed Brown ierr = PetscSectionGetNumFields(section,&Nf);CHKERRQ(ierr); 4639*0a96aa3bSJed Brown if (Nf > 3) SETERRQ1(PetscObjectComm((PetscObject)dmVecIn),PETSC_ERR_SUP,"Number of fields %D are currently not supported! Send an email at petsc-dev@mcs.anl.gov",Nf); 4640*0a96aa3bSJed Brown } 4641*0a96aa3bSJed Brown ierr = DMForestGetMinimumRefinement(dm,&minLevel);CHKERRQ(ierr); 4642*0a96aa3bSJed Brown if (minLevel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot transfer with minimum refinement set to %D. Rerun with DMForestSetMinimumRefinement(dm,0)",minLevel); 4643*0a96aa3bSJed Brown ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr); 4644*0a96aa3bSJed Brown if (!base) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing base DM"); 4645*0a96aa3bSJed Brown 4646*0a96aa3bSJed Brown ierr = VecSet(vecOut,0.0);CHKERRQ(ierr); 4647*0a96aa3bSJed Brown if (dmVecIn == base) { /* sequential runs */ 4648*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)vecIn);CHKERRQ(ierr); 4649*0a96aa3bSJed Brown } else { 4650*0a96aa3bSJed Brown PetscSection secIn, secInRed; 4651*0a96aa3bSJed Brown Vec vecInRed, vecInLocal; 4652*0a96aa3bSJed Brown 4653*0a96aa3bSJed Brown ierr = PetscObjectQuery((PetscObject)base,"_base_migration_sf",(PetscObject*)&sfRed);CHKERRQ(ierr); 4654*0a96aa3bSJed Brown if (!sfRed) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not the DM set with DMForestSetBaseDM()"); 4655*0a96aa3bSJed Brown ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dmVecIn),&secInRed);CHKERRQ(ierr); 4656*0a96aa3bSJed Brown ierr = VecCreate(PETSC_COMM_SELF,&vecInRed);CHKERRQ(ierr); 4657*0a96aa3bSJed Brown ierr = DMGetLocalSection(dmVecIn,&secIn);CHKERRQ(ierr); 4658*0a96aa3bSJed Brown ierr = DMGetLocalVector(dmVecIn,&vecInLocal);CHKERRQ(ierr); 4659*0a96aa3bSJed Brown ierr = DMGlobalToLocalBegin(dmVecIn,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 4660*0a96aa3bSJed Brown ierr = DMGlobalToLocalEnd(dmVecIn,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 4661*0a96aa3bSJed Brown ierr = DMPlexDistributeField(dmVecIn,sfRed,secIn,vecInLocal,secInRed,vecInRed);CHKERRQ(ierr); 4662*0a96aa3bSJed Brown ierr = DMRestoreLocalVector(dmVecIn,&vecInLocal);CHKERRQ(ierr); 4663*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&secInRed);CHKERRQ(ierr); 4664*0a96aa3bSJed Brown vecIn = vecInRed; 4665*0a96aa3bSJed Brown } 4666*0a96aa3bSJed Brown 4667*0a96aa3bSJed Brown /* we first search through the AdaptivityForest hierarchy 4668*0a96aa3bSJed Brown once we found the first disconnected forest, we upsweep the DM hierarchy */ 4669*0a96aa3bSJed Brown hiforest = PETSC_TRUE; 4670*0a96aa3bSJed Brown 4671*0a96aa3bSJed Brown /* upsweep to the coarsest DM */ 4672*0a96aa3bSJed Brown n_hi = 0; 4673*0a96aa3bSJed Brown coarseDM = dm; 4674*0a96aa3bSJed Brown do { 4675*0a96aa3bSJed Brown PetscBool isforest; 4676*0a96aa3bSJed Brown 4677*0a96aa3bSJed Brown dmIn = coarseDM; 4678*0a96aa3bSJed Brown /* need to call DMSetUp to have the hierarchy recursively setup */ 4679*0a96aa3bSJed Brown ierr = DMSetUp(dmIn);CHKERRQ(ierr); 4680*0a96aa3bSJed Brown ierr = DMIsForest(dmIn,&isforest);CHKERRQ(ierr); 4681*0a96aa3bSJed Brown if (!isforest) SETERRQ1(PetscObjectComm((PetscObject)dmIn),PETSC_ERR_SUP,"Cannot currently transfer through a mixed hierarchy! Found DM type %s",((PetscObject)dmIn)->type_name); 4682*0a96aa3bSJed Brown coarseDM = NULL; 4683*0a96aa3bSJed Brown if (hiforest) { 4684*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(dmIn,&coarseDM);CHKERRQ(ierr); 4685*0a96aa3bSJed Brown } 4686*0a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 4687*0a96aa3bSJed Brown hiforest = PETSC_FALSE; 4688*0a96aa3bSJed Brown ierr = DMGetCoarseDM(dmIn,&coarseDM);CHKERRQ(ierr); 4689*0a96aa3bSJed Brown } 4690*0a96aa3bSJed Brown n_hi++; 4691*0a96aa3bSJed Brown } while (coarseDM); 4692*0a96aa3bSJed Brown 4693*0a96aa3bSJed Brown ierr = PetscMalloc2(n_hi,&hierarchy,n_hi,&hierarchy_forest);CHKERRQ(ierr); 4694*0a96aa3bSJed Brown 4695*0a96aa3bSJed Brown i = 0; 4696*0a96aa3bSJed Brown hiforest = PETSC_TRUE; 4697*0a96aa3bSJed Brown coarseDM = dm; 4698*0a96aa3bSJed Brown do { 4699*0a96aa3bSJed Brown dmIn = coarseDM; 4700*0a96aa3bSJed Brown coarseDM = NULL; 4701*0a96aa3bSJed Brown if (hiforest) { 4702*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(dmIn,&coarseDM);CHKERRQ(ierr); 4703*0a96aa3bSJed Brown } 4704*0a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */ 4705*0a96aa3bSJed Brown hiforest = PETSC_FALSE; 4706*0a96aa3bSJed Brown ierr = DMGetCoarseDM(dmIn,&coarseDM);CHKERRQ(ierr); 4707*0a96aa3bSJed Brown } 4708*0a96aa3bSJed Brown i++; 4709*0a96aa3bSJed Brown hierarchy[n_hi - i] = dmIn; 4710*0a96aa3bSJed Brown } while (coarseDM); 4711*0a96aa3bSJed Brown 4712*0a96aa3bSJed Brown /* project base vector on the coarsest forest (minimum refinement = 0) */ 4713*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dmIn,&plex);CHKERRQ(ierr); 4714*0a96aa3bSJed Brown 4715*0a96aa3bSJed Brown /* Check this plex is compatible with the base */ 4716*0a96aa3bSJed Brown { 4717*0a96aa3bSJed Brown IS gnum[2]; 4718*0a96aa3bSJed Brown PetscInt ncells[2],gncells[2]; 4719*0a96aa3bSJed Brown 4720*0a96aa3bSJed Brown ierr = DMPlexGetCellNumbering(base,&gnum[0]);CHKERRQ(ierr); 4721*0a96aa3bSJed Brown ierr = DMPlexGetCellNumbering(plex,&gnum[1]);CHKERRQ(ierr); 4722*0a96aa3bSJed Brown ierr = ISGetMinMax(gnum[0],NULL,&ncells[0]);CHKERRQ(ierr); 4723*0a96aa3bSJed Brown ierr = ISGetMinMax(gnum[1],NULL,&ncells[1]);CHKERRQ(ierr); 4724*0a96aa3bSJed Brown ierr = MPIU_Allreduce(ncells,gncells,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 4725*0a96aa3bSJed Brown if (gncells[0] != gncells[1]) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Invalid number of base cells! Expected %D, found %D",gncells[0]+1,gncells[1]+1); 4726*0a96aa3bSJed Brown } 4727*0a96aa3bSJed Brown 4728*0a96aa3bSJed Brown ierr = DMGetLabel(dmIn,"_forest_base_subpoint_map",&subpointMap);CHKERRQ(ierr); 4729*0a96aa3bSJed Brown if (!subpointMap) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing _forest_base_subpoint_map label"); 4730*0a96aa3bSJed Brown 4731*0a96aa3bSJed Brown ierr = DMPlexGetMaxProjectionHeight(base,&mh);CHKERRQ(ierr); 4732*0a96aa3bSJed Brown ierr = DMPlexSetMaxProjectionHeight(plex,mh);CHKERRQ(ierr); 4733*0a96aa3bSJed Brown 4734*0a96aa3bSJed Brown ierr = DMClone(base,&basec);CHKERRQ(ierr); 4735*0a96aa3bSJed Brown ierr = DMCopyDisc(dmVecIn,basec);CHKERRQ(ierr); 4736*0a96aa3bSJed Brown if (sfRed) { 4737*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)vecIn);CHKERRQ(ierr); 4738*0a96aa3bSJed Brown vecInLocal = vecIn; 4739*0a96aa3bSJed Brown } else { 4740*0a96aa3bSJed Brown ierr = DMCreateLocalVector(basec,&vecInLocal);CHKERRQ(ierr); 4741*0a96aa3bSJed Brown ierr = DMGlobalToLocalBegin(basec,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 4742*0a96aa3bSJed Brown ierr = DMGlobalToLocalEnd(basec,vecIn,INSERT_VALUES,vecInLocal);CHKERRQ(ierr); 4743*0a96aa3bSJed Brown } 4744*0a96aa3bSJed Brown 4745*0a96aa3bSJed Brown ierr = DMGetLocalVector(dmIn,&vecOutLocal);CHKERRQ(ierr); 4746*0a96aa3bSJed Brown { /* get degrees of freedom ordered onto dmIn */ 4747*0a96aa3bSJed Brown PetscSF basetocoarse; 4748*0a96aa3bSJed Brown PetscInt bStart, bEnd, nroots; 4749*0a96aa3bSJed Brown PetscInt iStart, iEnd, nleaves, leaf; 4750*0a96aa3bSJed Brown PetscMPIInt rank; 4751*0a96aa3bSJed Brown PetscSFNode *remotes; 4752*0a96aa3bSJed Brown PetscSection secIn, secOut; 4753*0a96aa3bSJed Brown PetscInt *remoteOffsets; 4754*0a96aa3bSJed Brown PetscSF transferSF; 4755*0a96aa3bSJed Brown const PetscScalar *inArray; 4756*0a96aa3bSJed Brown PetscScalar *outArray; 4757*0a96aa3bSJed Brown 4758*0a96aa3bSJed Brown ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)basec), &rank);CHKERRMPI(ierr); 4759*0a96aa3bSJed Brown ierr = DMPlexGetChart(basec, &bStart, &bEnd);CHKERRQ(ierr); 4760*0a96aa3bSJed Brown nroots = PetscMax(bEnd - bStart, 0); 4761*0a96aa3bSJed Brown ierr = DMPlexGetChart(plex, &iStart, &iEnd);CHKERRQ(ierr); 4762*0a96aa3bSJed Brown nleaves = PetscMax(iEnd - iStart, 0); 4763*0a96aa3bSJed Brown 4764*0a96aa3bSJed Brown ierr = PetscMalloc1(nleaves, &remotes);CHKERRQ(ierr); 4765*0a96aa3bSJed Brown for (leaf = iStart; leaf < iEnd; leaf++) { 4766*0a96aa3bSJed Brown PetscInt index; 4767*0a96aa3bSJed Brown 4768*0a96aa3bSJed Brown remotes[leaf - iStart].rank = rank; 4769*0a96aa3bSJed Brown ierr = DMLabelGetValue(subpointMap, leaf, &index);CHKERRQ(ierr); 4770*0a96aa3bSJed Brown remotes[leaf - iStart].index = index; 4771*0a96aa3bSJed Brown } 4772*0a96aa3bSJed Brown 4773*0a96aa3bSJed Brown ierr = PetscSFCreate(PetscObjectComm((PetscObject)basec), &basetocoarse);CHKERRQ(ierr); 4774*0a96aa3bSJed Brown ierr = PetscSFSetGraph(basetocoarse, nroots, nleaves, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER);CHKERRQ(ierr); 4775*0a96aa3bSJed Brown ierr = PetscSFSetUp(basetocoarse);CHKERRQ(ierr); 4776*0a96aa3bSJed Brown ierr = DMGetLocalSection(basec,&secIn);CHKERRQ(ierr); 4777*0a96aa3bSJed Brown ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dmIn),&secOut);CHKERRQ(ierr); 4778*0a96aa3bSJed Brown ierr = PetscSFDistributeSection(basetocoarse, secIn, &remoteOffsets, secOut);CHKERRQ(ierr); 4779*0a96aa3bSJed Brown ierr = PetscSFCreateSectionSF(basetocoarse, secIn, remoteOffsets, secOut, &transferSF);CHKERRQ(ierr); 4780*0a96aa3bSJed Brown ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 4781*0a96aa3bSJed Brown ierr = VecGetArrayWrite(vecOutLocal, &outArray);CHKERRQ(ierr); 4782*0a96aa3bSJed Brown ierr = VecGetArrayRead(vecInLocal, &inArray);CHKERRQ(ierr); 4783*0a96aa3bSJed Brown ierr = PetscSFBcastBegin(transferSF, MPIU_SCALAR, inArray, outArray,MPI_REPLACE);CHKERRQ(ierr); 4784*0a96aa3bSJed Brown ierr = PetscSFBcastEnd(transferSF, MPIU_SCALAR, inArray, outArray,MPI_REPLACE);CHKERRQ(ierr); 4785*0a96aa3bSJed Brown ierr = VecRestoreArrayRead(vecInLocal, &inArray);CHKERRQ(ierr); 4786*0a96aa3bSJed Brown ierr = VecRestoreArrayWrite(vecOutLocal, &outArray);CHKERRQ(ierr); 4787*0a96aa3bSJed Brown ierr = PetscSFDestroy(&transferSF);CHKERRQ(ierr); 4788*0a96aa3bSJed Brown ierr = PetscSectionDestroy(&secOut);CHKERRQ(ierr); 4789*0a96aa3bSJed Brown ierr = PetscSFDestroy(&basetocoarse);CHKERRQ(ierr); 4790*0a96aa3bSJed Brown } 4791*0a96aa3bSJed Brown ierr = VecDestroy(&vecInLocal);CHKERRQ(ierr); 4792*0a96aa3bSJed Brown ierr = DMDestroy(&basec);CHKERRQ(ierr); 4793*0a96aa3bSJed Brown ierr = VecDestroy(&vecIn);CHKERRQ(ierr); 4794*0a96aa3bSJed Brown 4795*0a96aa3bSJed Brown /* output */ 4796*0a96aa3bSJed Brown if (n_hi > 1) { /* downsweep the stored hierarchy */ 4797*0a96aa3bSJed Brown Vec vecOut1, vecOut2; 4798*0a96aa3bSJed Brown DM fineDM; 4799*0a96aa3bSJed Brown 4800*0a96aa3bSJed Brown ierr = DMGetGlobalVector(dmIn,&vecOut1);CHKERRQ(ierr); 4801*0a96aa3bSJed Brown ierr = DMLocalToGlobal(dmIn,vecOutLocal,INSERT_VALUES,vecOut1);CHKERRQ(ierr); 4802*0a96aa3bSJed Brown ierr = DMRestoreLocalVector(dmIn,&vecOutLocal);CHKERRQ(ierr); 4803*0a96aa3bSJed Brown for (i = 1; i < n_hi-1; i++) { 4804*0a96aa3bSJed Brown fineDM = hierarchy[i]; 4805*0a96aa3bSJed Brown ierr = DMGetGlobalVector(fineDM,&vecOut2);CHKERRQ(ierr); 4806*0a96aa3bSJed Brown ierr = DMForestTransferVec(dmIn,vecOut1,fineDM,vecOut2,PETSC_TRUE,0.0);CHKERRQ(ierr); 4807*0a96aa3bSJed Brown ierr = DMRestoreGlobalVector(dmIn,&vecOut1);CHKERRQ(ierr); 4808*0a96aa3bSJed Brown vecOut1 = vecOut2; 4809*0a96aa3bSJed Brown dmIn = fineDM; 4810*0a96aa3bSJed Brown } 4811*0a96aa3bSJed Brown ierr = DMForestTransferVec(dmIn,vecOut1,dm,vecOut,PETSC_TRUE,0.0);CHKERRQ(ierr); 4812*0a96aa3bSJed Brown ierr = DMRestoreGlobalVector(dmIn,&vecOut1);CHKERRQ(ierr); 4813*0a96aa3bSJed Brown } else { 4814*0a96aa3bSJed Brown ierr = DMLocalToGlobal(dmIn,vecOutLocal,INSERT_VALUES,vecOut);CHKERRQ(ierr); 4815*0a96aa3bSJed Brown ierr = DMRestoreLocalVector(dmIn,&vecOutLocal);CHKERRQ(ierr); 4816*0a96aa3bSJed Brown } 4817*0a96aa3bSJed Brown ierr = PetscFree2(hierarchy,hierarchy_forest);CHKERRQ(ierr); 4818*0a96aa3bSJed Brown PetscFunctionReturn(0); 4819*0a96aa3bSJed Brown } 4820*0a96aa3bSJed Brown 4821*0a96aa3bSJed Brown #define DMForestTransferVec_pforest _append_pforest(DMForestTransferVec) 4822*0a96aa3bSJed Brown static PetscErrorCode DMForestTransferVec_pforest(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time) 4823*0a96aa3bSJed Brown { 4824*0a96aa3bSJed Brown DM adaptIn, adaptOut, plexIn, plexOut; 4825*0a96aa3bSJed Brown DM_Forest *forestIn, *forestOut, *forestAdaptIn, *forestAdaptOut; 4826*0a96aa3bSJed Brown PetscInt dofPerDim[] = {1, 1, 1, 1}; 4827*0a96aa3bSJed Brown PetscSF inSF = NULL, outSF = NULL; 4828*0a96aa3bSJed Brown PetscInt *inCids = NULL, *outCids = NULL; 4829*0a96aa3bSJed Brown DMAdaptFlag purposeIn, purposeOut; 4830*0a96aa3bSJed Brown PetscErrorCode ierr; 4831*0a96aa3bSJed Brown 4832*0a96aa3bSJed Brown PetscFunctionBegin; 4833*0a96aa3bSJed Brown forestOut = (DM_Forest *) dmOut->data; 4834*0a96aa3bSJed Brown forestIn = (DM_Forest *) dmIn->data; 4835*0a96aa3bSJed Brown 4836*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(dmOut,&adaptOut);CHKERRQ(ierr); 4837*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityPurpose(dmOut,&purposeOut);CHKERRQ(ierr); 4838*0a96aa3bSJed Brown forestAdaptOut = adaptOut ? (DM_Forest *) adaptOut->data : NULL; 4839*0a96aa3bSJed Brown 4840*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityForest(dmIn,&adaptIn);CHKERRQ(ierr); 4841*0a96aa3bSJed Brown ierr = DMForestGetAdaptivityPurpose(dmIn,&purposeIn);CHKERRQ(ierr); 4842*0a96aa3bSJed Brown forestAdaptIn = adaptIn ? (DM_Forest *) adaptIn->data : NULL; 4843*0a96aa3bSJed Brown 4844*0a96aa3bSJed Brown if (forestAdaptOut == forestIn) { 4845*0a96aa3bSJed Brown switch (purposeOut) { 4846*0a96aa3bSJed Brown case DM_ADAPT_REFINE: 4847*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids);CHKERRQ(ierr); 4848*0a96aa3bSJed Brown ierr = PetscSFSetUp(inSF);CHKERRQ(ierr); 4849*0a96aa3bSJed Brown break; 4850*0a96aa3bSJed Brown case DM_ADAPT_COARSEN: 4851*0a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 4852*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_TRUE,&outCids);CHKERRQ(ierr); 4853*0a96aa3bSJed Brown ierr = PetscSFSetUp(outSF);CHKERRQ(ierr); 4854*0a96aa3bSJed Brown break; 4855*0a96aa3bSJed Brown default: 4856*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids);CHKERRQ(ierr); 4857*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_FALSE,&outCids);CHKERRQ(ierr); 4858*0a96aa3bSJed Brown ierr = PetscSFSetUp(inSF);CHKERRQ(ierr); 4859*0a96aa3bSJed Brown ierr = PetscSFSetUp(outSF);CHKERRQ(ierr); 4860*0a96aa3bSJed Brown } 4861*0a96aa3bSJed Brown } else if (forestAdaptIn == forestOut) { 4862*0a96aa3bSJed Brown switch (purposeIn) { 4863*0a96aa3bSJed Brown case DM_ADAPT_REFINE: 4864*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_TRUE,&inCids);CHKERRQ(ierr); 4865*0a96aa3bSJed Brown ierr = PetscSFSetUp(outSF);CHKERRQ(ierr); 4866*0a96aa3bSJed Brown break; 4867*0a96aa3bSJed Brown case DM_ADAPT_COARSEN: 4868*0a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST: 4869*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids);CHKERRQ(ierr); 4870*0a96aa3bSJed Brown ierr = PetscSFSetUp(inSF);CHKERRQ(ierr); 4871*0a96aa3bSJed Brown break; 4872*0a96aa3bSJed Brown default: 4873*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmIn,dmOut,dofPerDim,&inSF,PETSC_TRUE,&inCids);CHKERRQ(ierr); 4874*0a96aa3bSJed Brown ierr = DMPforestGetTransferSF_Internal(dmOut,dmIn,dofPerDim,&outSF,PETSC_FALSE,&outCids);CHKERRQ(ierr); 4875*0a96aa3bSJed Brown ierr = PetscSFSetUp(inSF);CHKERRQ(ierr); 4876*0a96aa3bSJed Brown ierr = PetscSFSetUp(outSF);CHKERRQ(ierr); 4877*0a96aa3bSJed Brown } 4878*0a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dmIn),PETSC_ERR_SUP,"Only support transfer from pre-adaptivity to post-adaptivity right now"); 4879*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dmIn,&plexIn);CHKERRQ(ierr); 4880*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dmOut,&plexOut);CHKERRQ(ierr); 4881*0a96aa3bSJed Brown 4882*0a96aa3bSJed Brown ierr = DMPlexTransferVecTree(plexIn,vecIn,plexOut,vecOut,inSF,outSF,inCids,outCids,useBCs,time);CHKERRQ(ierr); 4883*0a96aa3bSJed Brown ierr = PetscFree(inCids);CHKERRQ(ierr); 4884*0a96aa3bSJed Brown ierr = PetscFree(outCids);CHKERRQ(ierr); 4885*0a96aa3bSJed Brown ierr = PetscSFDestroy(&inSF);CHKERRQ(ierr); 4886*0a96aa3bSJed Brown ierr = PetscSFDestroy(&outSF);CHKERRQ(ierr); 4887*0a96aa3bSJed Brown ierr = PetscFree(inCids);CHKERRQ(ierr); 4888*0a96aa3bSJed Brown ierr = PetscFree(outCids);CHKERRQ(ierr); 4889*0a96aa3bSJed Brown PetscFunctionReturn(0); 4890*0a96aa3bSJed Brown } 4891*0a96aa3bSJed Brown 4892*0a96aa3bSJed Brown #define DMCreateCoordinateDM_pforest _append_pforest(DMCreateCoordinateDM) 4893*0a96aa3bSJed Brown static PetscErrorCode DMCreateCoordinateDM_pforest(DM dm,DM *cdm) 4894*0a96aa3bSJed Brown { 4895*0a96aa3bSJed Brown DM plex; 4896*0a96aa3bSJed Brown PetscErrorCode ierr; 4897*0a96aa3bSJed Brown 4898*0a96aa3bSJed Brown PetscFunctionBegin; 4899*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4900*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 4901*0a96aa3bSJed Brown ierr = DMGetCoordinateDM(plex,cdm);CHKERRQ(ierr); 4902*0a96aa3bSJed Brown ierr = PetscObjectReference((PetscObject)*cdm);CHKERRQ(ierr); 4903*0a96aa3bSJed Brown PetscFunctionReturn(0); 4904*0a96aa3bSJed Brown } 4905*0a96aa3bSJed Brown 4906*0a96aa3bSJed Brown #define VecViewLocal_pforest _append_pforest(VecViewLocal) 4907*0a96aa3bSJed Brown static PetscErrorCode VecViewLocal_pforest(Vec vec,PetscViewer viewer) 4908*0a96aa3bSJed Brown { 4909*0a96aa3bSJed Brown DM dm, plex; 4910*0a96aa3bSJed Brown PetscErrorCode ierr; 4911*0a96aa3bSJed Brown 4912*0a96aa3bSJed Brown PetscFunctionBegin; 4913*0a96aa3bSJed Brown ierr = VecGetDM(vec,&dm);CHKERRQ(ierr); 4914*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 4915*0a96aa3bSJed Brown ierr = VecSetDM(vec,plex);CHKERRQ(ierr); 4916*0a96aa3bSJed Brown ierr = VecView_Plex_Local(vec,viewer);CHKERRQ(ierr); 4917*0a96aa3bSJed Brown ierr = VecSetDM(vec,dm);CHKERRQ(ierr); 4918*0a96aa3bSJed Brown PetscFunctionReturn(0); 4919*0a96aa3bSJed Brown } 4920*0a96aa3bSJed Brown 4921*0a96aa3bSJed Brown #define VecView_pforest _append_pforest(VecView) 4922*0a96aa3bSJed Brown static PetscErrorCode VecView_pforest(Vec vec,PetscViewer viewer) 4923*0a96aa3bSJed Brown { 4924*0a96aa3bSJed Brown DM dm, plex; 4925*0a96aa3bSJed Brown PetscErrorCode ierr; 4926*0a96aa3bSJed Brown 4927*0a96aa3bSJed Brown PetscFunctionBegin; 4928*0a96aa3bSJed Brown ierr = VecGetDM(vec,&dm);CHKERRQ(ierr); 4929*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 4930*0a96aa3bSJed Brown ierr = VecSetDM(vec,plex);CHKERRQ(ierr); 4931*0a96aa3bSJed Brown ierr = VecView_Plex(vec,viewer);CHKERRQ(ierr); 4932*0a96aa3bSJed Brown ierr = VecSetDM(vec,dm);CHKERRQ(ierr); 4933*0a96aa3bSJed Brown PetscFunctionReturn(0); 4934*0a96aa3bSJed Brown } 4935*0a96aa3bSJed Brown 4936*0a96aa3bSJed Brown #define VecView_pforest_Native _infix_pforest(VecView,_Native) 4937*0a96aa3bSJed Brown static PetscErrorCode VecView_pforest_Native(Vec vec,PetscViewer viewer) 4938*0a96aa3bSJed Brown { 4939*0a96aa3bSJed Brown DM dm, plex; 4940*0a96aa3bSJed Brown PetscErrorCode ierr; 4941*0a96aa3bSJed Brown 4942*0a96aa3bSJed Brown PetscFunctionBegin; 4943*0a96aa3bSJed Brown ierr = VecGetDM(vec,&dm);CHKERRQ(ierr); 4944*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 4945*0a96aa3bSJed Brown ierr = VecSetDM(vec,plex);CHKERRQ(ierr); 4946*0a96aa3bSJed Brown ierr = VecView_Plex_Native(vec,viewer);CHKERRQ(ierr); 4947*0a96aa3bSJed Brown ierr = VecSetDM(vec,dm);CHKERRQ(ierr); 4948*0a96aa3bSJed Brown PetscFunctionReturn(0); 4949*0a96aa3bSJed Brown } 4950*0a96aa3bSJed Brown 4951*0a96aa3bSJed Brown #define VecLoad_pforest _append_pforest(VecLoad) 4952*0a96aa3bSJed Brown static PetscErrorCode VecLoad_pforest(Vec vec,PetscViewer viewer) 4953*0a96aa3bSJed Brown { 4954*0a96aa3bSJed Brown DM dm, plex; 4955*0a96aa3bSJed Brown PetscErrorCode ierr; 4956*0a96aa3bSJed Brown 4957*0a96aa3bSJed Brown PetscFunctionBegin; 4958*0a96aa3bSJed Brown ierr = VecGetDM(vec,&dm);CHKERRQ(ierr); 4959*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 4960*0a96aa3bSJed Brown ierr = VecSetDM(vec,plex);CHKERRQ(ierr); 4961*0a96aa3bSJed Brown ierr = VecLoad_Plex(vec,viewer);CHKERRQ(ierr); 4962*0a96aa3bSJed Brown ierr = VecSetDM(vec,dm);CHKERRQ(ierr); 4963*0a96aa3bSJed Brown PetscFunctionReturn(0); 4964*0a96aa3bSJed Brown } 4965*0a96aa3bSJed Brown 4966*0a96aa3bSJed Brown #define VecLoad_pforest_Native _infix_pforest(VecLoad,_Native) 4967*0a96aa3bSJed Brown static PetscErrorCode VecLoad_pforest_Native(Vec vec,PetscViewer viewer) 4968*0a96aa3bSJed Brown { 4969*0a96aa3bSJed Brown DM dm, plex; 4970*0a96aa3bSJed Brown PetscErrorCode ierr; 4971*0a96aa3bSJed Brown 4972*0a96aa3bSJed Brown PetscFunctionBegin; 4973*0a96aa3bSJed Brown ierr = VecGetDM(vec,&dm);CHKERRQ(ierr); 4974*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 4975*0a96aa3bSJed Brown ierr = VecSetDM(vec,plex);CHKERRQ(ierr); 4976*0a96aa3bSJed Brown ierr = VecLoad_Plex_Native(vec,viewer);CHKERRQ(ierr); 4977*0a96aa3bSJed Brown ierr = VecSetDM(vec,dm);CHKERRQ(ierr); 4978*0a96aa3bSJed Brown PetscFunctionReturn(0); 4979*0a96aa3bSJed Brown } 4980*0a96aa3bSJed Brown 4981*0a96aa3bSJed Brown #define DMCreateGlobalVector_pforest _append_pforest(DMCreateGlobalVector) 4982*0a96aa3bSJed Brown static PetscErrorCode DMCreateGlobalVector_pforest(DM dm,Vec *vec) 4983*0a96aa3bSJed Brown { 4984*0a96aa3bSJed Brown PetscErrorCode ierr; 4985*0a96aa3bSJed Brown 4986*0a96aa3bSJed Brown PetscFunctionBegin; 4987*0a96aa3bSJed Brown ierr = DMCreateGlobalVector_Section_Private(dm,vec);CHKERRQ(ierr); 4988*0a96aa3bSJed Brown /* ierr = VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM);CHKERRQ(ierr); */ 4989*0a96aa3bSJed Brown ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_pforest);CHKERRQ(ierr); 4990*0a96aa3bSJed Brown ierr = VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_pforest_Native);CHKERRQ(ierr); 4991*0a96aa3bSJed Brown ierr = VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_pforest);CHKERRQ(ierr); 4992*0a96aa3bSJed Brown ierr = VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_pforest_Native);CHKERRQ(ierr); 4993*0a96aa3bSJed Brown PetscFunctionReturn(0); 4994*0a96aa3bSJed Brown } 4995*0a96aa3bSJed Brown 4996*0a96aa3bSJed Brown #define DMCreateLocalVector_pforest _append_pforest(DMCreateLocalVector) 4997*0a96aa3bSJed Brown static PetscErrorCode DMCreateLocalVector_pforest(DM dm,Vec *vec) 4998*0a96aa3bSJed Brown { 4999*0a96aa3bSJed Brown PetscErrorCode ierr; 5000*0a96aa3bSJed Brown 5001*0a96aa3bSJed Brown PetscFunctionBegin; 5002*0a96aa3bSJed Brown ierr = DMCreateLocalVector_Section_Private(dm,vec);CHKERRQ(ierr); 5003*0a96aa3bSJed Brown ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecViewLocal_pforest);CHKERRQ(ierr); 5004*0a96aa3bSJed Brown PetscFunctionReturn(0); 5005*0a96aa3bSJed Brown } 5006*0a96aa3bSJed Brown 5007*0a96aa3bSJed Brown #define DMCreateMatrix_pforest _append_pforest(DMCreateMatrix) 5008*0a96aa3bSJed Brown static PetscErrorCode DMCreateMatrix_pforest(DM dm,Mat *mat) 5009*0a96aa3bSJed Brown { 5010*0a96aa3bSJed Brown DM plex; 5011*0a96aa3bSJed Brown PetscErrorCode ierr; 5012*0a96aa3bSJed Brown 5013*0a96aa3bSJed Brown PetscFunctionBegin; 5014*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5015*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5016*0a96aa3bSJed Brown if (plex->prealloc_only != dm->prealloc_only) plex->prealloc_only = dm->prealloc_only; /* maybe this should go into forest->plex */ 5017*0a96aa3bSJed Brown ierr = DMCreateMatrix(plex,mat);CHKERRQ(ierr); 5018*0a96aa3bSJed Brown ierr = MatSetDM(*mat,dm);CHKERRQ(ierr); 5019*0a96aa3bSJed Brown PetscFunctionReturn(0); 5020*0a96aa3bSJed Brown } 5021*0a96aa3bSJed Brown 5022*0a96aa3bSJed Brown #define DMProjectFunctionLocal_pforest _append_pforest(DMProjectFunctionLocal) 5023*0a96aa3bSJed Brown static PetscErrorCode DMProjectFunctionLocal_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs) (PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void*), void **ctxs, InsertMode mode, Vec localX) 5024*0a96aa3bSJed Brown { 5025*0a96aa3bSJed Brown DM plex; 5026*0a96aa3bSJed Brown PetscErrorCode ierr; 5027*0a96aa3bSJed Brown 5028*0a96aa3bSJed Brown PetscFunctionBegin; 5029*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5030*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5031*0a96aa3bSJed Brown ierr = DMProjectFunctionLocal(plex,time,funcs,ctxs,mode,localX);CHKERRQ(ierr); 5032*0a96aa3bSJed Brown PetscFunctionReturn(0); 5033*0a96aa3bSJed Brown } 5034*0a96aa3bSJed Brown 5035*0a96aa3bSJed Brown #define DMProjectFunctionLabelLocal_pforest _append_pforest(DMProjectFunctionLabelLocal) 5036*0a96aa3bSJed 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) 5037*0a96aa3bSJed Brown { 5038*0a96aa3bSJed Brown DM plex; 5039*0a96aa3bSJed Brown PetscErrorCode ierr; 5040*0a96aa3bSJed Brown 5041*0a96aa3bSJed Brown PetscFunctionBegin; 5042*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5043*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5044*0a96aa3bSJed Brown ierr = DMProjectFunctionLabelLocal(plex,time,label,numIds,ids,Ncc,comps,funcs,ctxs,mode,localX);CHKERRQ(ierr); 5045*0a96aa3bSJed Brown PetscFunctionReturn(0); 5046*0a96aa3bSJed Brown } 5047*0a96aa3bSJed Brown 5048*0a96aa3bSJed Brown #define DMProjectFieldLocal_pforest _append_pforest(DMProjectFieldLocal) 5049*0a96aa3bSJed Brown PetscErrorCode DMProjectFieldLocal_pforest(DM dm, PetscReal time, Vec localU,void (**funcs) (PetscInt, PetscInt, PetscInt, 5050*0a96aa3bSJed Brown const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 5051*0a96aa3bSJed Brown const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 5052*0a96aa3bSJed Brown PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),InsertMode mode, Vec localX) 5053*0a96aa3bSJed Brown { 5054*0a96aa3bSJed Brown DM plex; 5055*0a96aa3bSJed Brown PetscErrorCode ierr; 5056*0a96aa3bSJed Brown 5057*0a96aa3bSJed Brown PetscFunctionBegin; 5058*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5059*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5060*0a96aa3bSJed Brown ierr = DMProjectFieldLocal(plex,time,localU,funcs,mode,localX);CHKERRQ(ierr); 5061*0a96aa3bSJed Brown PetscFunctionReturn(0); 5062*0a96aa3bSJed Brown } 5063*0a96aa3bSJed Brown 5064*0a96aa3bSJed Brown #define DMComputeL2Diff_pforest _append_pforest(DMComputeL2Diff) 5065*0a96aa3bSJed Brown PetscErrorCode DMComputeL2Diff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs) (PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void*), void **ctxs, Vec X, PetscReal *diff) 5066*0a96aa3bSJed Brown { 5067*0a96aa3bSJed Brown DM plex; 5068*0a96aa3bSJed Brown PetscErrorCode ierr; 5069*0a96aa3bSJed Brown 5070*0a96aa3bSJed Brown PetscFunctionBegin; 5071*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5072*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5073*0a96aa3bSJed Brown ierr = DMComputeL2Diff(plex,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 5074*0a96aa3bSJed Brown PetscFunctionReturn(0); 5075*0a96aa3bSJed Brown } 5076*0a96aa3bSJed Brown 5077*0a96aa3bSJed Brown #define DMComputeL2FieldDiff_pforest _append_pforest(DMComputeL2FieldDiff) 5078*0a96aa3bSJed Brown PetscErrorCode DMComputeL2FieldDiff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs) (PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void*), void **ctxs, Vec X, PetscReal diff[]) 5079*0a96aa3bSJed Brown { 5080*0a96aa3bSJed Brown DM plex; 5081*0a96aa3bSJed Brown PetscErrorCode ierr; 5082*0a96aa3bSJed Brown 5083*0a96aa3bSJed Brown PetscFunctionBegin; 5084*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5085*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5086*0a96aa3bSJed Brown ierr = DMComputeL2FieldDiff(plex,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 5087*0a96aa3bSJed Brown PetscFunctionReturn(0); 5088*0a96aa3bSJed Brown } 5089*0a96aa3bSJed Brown 5090*0a96aa3bSJed Brown #define DMCreatelocalsection_pforest _append_pforest(DMCreatelocalsection) 5091*0a96aa3bSJed Brown static PetscErrorCode DMCreatelocalsection_pforest(DM dm) 5092*0a96aa3bSJed Brown { 5093*0a96aa3bSJed Brown DM plex; 5094*0a96aa3bSJed Brown PetscSection section; 5095*0a96aa3bSJed Brown PetscErrorCode ierr; 5096*0a96aa3bSJed Brown 5097*0a96aa3bSJed Brown PetscFunctionBegin; 5098*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5099*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5100*0a96aa3bSJed Brown ierr = DMGetLocalSection(plex,§ion);CHKERRQ(ierr); 5101*0a96aa3bSJed Brown ierr = DMSetLocalSection(dm,section);CHKERRQ(ierr); 5102*0a96aa3bSJed Brown PetscFunctionReturn(0); 5103*0a96aa3bSJed Brown } 5104*0a96aa3bSJed Brown 5105*0a96aa3bSJed Brown #define DMCreateDefaultConstraints_pforest _append_pforest(DMCreateDefaultConstraints) 5106*0a96aa3bSJed Brown static PetscErrorCode DMCreateDefaultConstraints_pforest(DM dm) 5107*0a96aa3bSJed Brown { 5108*0a96aa3bSJed Brown DM plex; 5109*0a96aa3bSJed Brown Mat mat; 5110*0a96aa3bSJed Brown PetscSection section; 5111*0a96aa3bSJed Brown PetscErrorCode ierr; 5112*0a96aa3bSJed Brown 5113*0a96aa3bSJed Brown PetscFunctionBegin; 5114*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5115*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5116*0a96aa3bSJed Brown ierr = DMGetDefaultConstraints(plex,§ion,&mat);CHKERRQ(ierr); 5117*0a96aa3bSJed Brown ierr = DMSetDefaultConstraints(dm,section,mat);CHKERRQ(ierr); 5118*0a96aa3bSJed Brown PetscFunctionReturn(0); 5119*0a96aa3bSJed Brown } 5120*0a96aa3bSJed Brown 5121*0a96aa3bSJed Brown #define DMGetDimPoints_pforest _append_pforest(DMGetDimPoints) 5122*0a96aa3bSJed Brown static PetscErrorCode DMGetDimPoints_pforest(DM dm, PetscInt dim, PetscInt *cStart, PetscInt *cEnd) 5123*0a96aa3bSJed Brown { 5124*0a96aa3bSJed Brown DM plex; 5125*0a96aa3bSJed Brown PetscErrorCode ierr; 5126*0a96aa3bSJed Brown 5127*0a96aa3bSJed Brown PetscFunctionBegin; 5128*0a96aa3bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5129*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5130*0a96aa3bSJed Brown ierr = DMGetDimPoints(plex,dim,cStart,cEnd);CHKERRQ(ierr); 5131*0a96aa3bSJed Brown PetscFunctionReturn(0); 5132*0a96aa3bSJed Brown } 5133*0a96aa3bSJed Brown 5134*0a96aa3bSJed Brown /* Need to forward declare */ 5135*0a96aa3bSJed Brown #define DMInitialize_pforest _append_pforest(DMInitialize) 5136*0a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm); 5137*0a96aa3bSJed Brown 5138*0a96aa3bSJed Brown #define DMClone_pforest _append_pforest(DMClone) 5139*0a96aa3bSJed Brown static PetscErrorCode DMClone_pforest(DM dm, DM *newdm) 5140*0a96aa3bSJed Brown { 5141*0a96aa3bSJed Brown PetscErrorCode ierr; 5142*0a96aa3bSJed Brown 5143*0a96aa3bSJed Brown PetscFunctionBegin; 5144*0a96aa3bSJed Brown ierr = DMClone_Forest(dm,newdm);CHKERRQ(ierr); 5145*0a96aa3bSJed Brown ierr = DMInitialize_pforest(*newdm);CHKERRQ(ierr); 5146*0a96aa3bSJed Brown PetscFunctionReturn(0); 5147*0a96aa3bSJed Brown } 5148*0a96aa3bSJed Brown 5149*0a96aa3bSJed Brown #define DMForestCreateCellChart_pforest _append_pforest(DMForestCreateCellChart) 5150*0a96aa3bSJed Brown static PetscErrorCode DMForestCreateCellChart_pforest(DM dm, PetscInt *cStart, PetscInt *cEnd) 5151*0a96aa3bSJed Brown { 5152*0a96aa3bSJed Brown DM_Forest *forest; 5153*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 5154*0a96aa3bSJed Brown PetscInt overlap; 5155*0a96aa3bSJed Brown PetscErrorCode ierr; 5156*0a96aa3bSJed Brown 5157*0a96aa3bSJed Brown PetscFunctionBegin; 5158*0a96aa3bSJed Brown ierr = DMSetUp(dm);CHKERRQ(ierr); 5159*0a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 5160*0a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 5161*0a96aa3bSJed Brown *cStart = 0; 5162*0a96aa3bSJed Brown ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr); 5163*0a96aa3bSJed Brown if (overlap && pforest->ghost) { 5164*0a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[pforest->forest->mpisize]; 5165*0a96aa3bSJed Brown } else { 5166*0a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants; 5167*0a96aa3bSJed Brown } 5168*0a96aa3bSJed Brown PetscFunctionReturn(0); 5169*0a96aa3bSJed Brown } 5170*0a96aa3bSJed Brown 5171*0a96aa3bSJed Brown #define DMForestCreateCellSF_pforest _append_pforest(DMForestCreateCellSF) 5172*0a96aa3bSJed Brown static PetscErrorCode DMForestCreateCellSF_pforest(DM dm, PetscSF *cellSF) 5173*0a96aa3bSJed Brown { 5174*0a96aa3bSJed Brown DM_Forest *forest; 5175*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 5176*0a96aa3bSJed Brown PetscMPIInt rank; 5177*0a96aa3bSJed Brown PetscInt overlap; 5178*0a96aa3bSJed Brown PetscInt cStart, cEnd, cLocalStart, cLocalEnd; 5179*0a96aa3bSJed Brown PetscInt nRoots, nLeaves, *mine = NULL; 5180*0a96aa3bSJed Brown PetscSFNode *remote = NULL; 5181*0a96aa3bSJed Brown PetscSF sf; 5182*0a96aa3bSJed Brown PetscErrorCode ierr; 5183*0a96aa3bSJed Brown 5184*0a96aa3bSJed Brown PetscFunctionBegin; 5185*0a96aa3bSJed Brown ierr = DMForestGetCellChart(dm,&cStart,&cEnd);CHKERRQ(ierr); 5186*0a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 5187*0a96aa3bSJed Brown pforest = (DM_Forest_pforest*) forest->data; 5188*0a96aa3bSJed Brown nRoots = cEnd - cStart; 5189*0a96aa3bSJed Brown cLocalStart = pforest->cLocalStart; 5190*0a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd; 5191*0a96aa3bSJed Brown nLeaves = 0; 5192*0a96aa3bSJed Brown ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr); 5193*0a96aa3bSJed Brown ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr); 5194*0a96aa3bSJed Brown if (overlap && pforest->ghost) { 5195*0a96aa3bSJed Brown PetscSFNode *mirror; 5196*0a96aa3bSJed Brown p4est_quadrant_t *mirror_array; 5197*0a96aa3bSJed Brown PetscInt nMirror, nGhostPre, nSelf, q; 5198*0a96aa3bSJed Brown void **mirrorPtrs; 5199*0a96aa3bSJed Brown 5200*0a96aa3bSJed Brown nMirror = (PetscInt) pforest->ghost->mirrors.elem_count; 5201*0a96aa3bSJed Brown nSelf = cLocalEnd - cLocalStart; 5202*0a96aa3bSJed Brown nLeaves = nRoots - nSelf; 5203*0a96aa3bSJed Brown nGhostPre = (PetscInt) pforest->ghost->proc_offsets[rank]; 5204*0a96aa3bSJed Brown ierr = PetscMalloc1(nLeaves,&mine);CHKERRQ(ierr); 5205*0a96aa3bSJed Brown ierr = PetscMalloc1(nLeaves,&remote);CHKERRQ(ierr); 5206*0a96aa3bSJed Brown ierr = PetscMalloc2(nMirror,&mirror,nMirror,&mirrorPtrs);CHKERRQ(ierr); 5207*0a96aa3bSJed Brown mirror_array = (p4est_quadrant_t*) pforest->ghost->mirrors.array; 5208*0a96aa3bSJed Brown for (q = 0; q < nMirror; q++) { 5209*0a96aa3bSJed Brown p4est_quadrant_t *mir = &(mirror_array[q]); 5210*0a96aa3bSJed Brown 5211*0a96aa3bSJed Brown mirror[q].rank = rank; 5212*0a96aa3bSJed Brown mirror[q].index = (PetscInt) mir->p.piggy3.local_num + cLocalStart; 5213*0a96aa3bSJed Brown mirrorPtrs[q] = (void*) &(mirror[q]); 5214*0a96aa3bSJed Brown } 5215*0a96aa3bSJed Brown PetscStackCallP4est(p4est_ghost_exchange_custom,(pforest->forest,pforest->ghost,sizeof(PetscSFNode),mirrorPtrs,remote)); 5216*0a96aa3bSJed Brown ierr = PetscFree2(mirror,mirrorPtrs);CHKERRQ(ierr); 5217*0a96aa3bSJed Brown for (q = 0; q < nGhostPre; q++) mine[q] = q; 5218*0a96aa3bSJed Brown for (; q < nLeaves; q++) mine[q] = (q - nGhostPre) + cLocalEnd; 5219*0a96aa3bSJed Brown } 5220*0a96aa3bSJed Brown ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&sf);CHKERRQ(ierr); 5221*0a96aa3bSJed Brown ierr = PetscSFSetGraph(sf,nRoots,nLeaves,mine,PETSC_OWN_POINTER,remote,PETSC_OWN_POINTER);CHKERRQ(ierr); 5222*0a96aa3bSJed Brown *cellSF = sf; 5223*0a96aa3bSJed Brown PetscFunctionReturn(0); 5224*0a96aa3bSJed Brown } 5225*0a96aa3bSJed Brown 5226*0a96aa3bSJed Brown static PetscErrorCode DMCreateNeumannOverlap_pforest(DM dm, IS* ovl, Mat *J, PetscErrorCode (**setup)(Mat, PetscReal, Vec, Vec, PetscReal, IS, void*), void **setup_ctx) 5227*0a96aa3bSJed Brown { 5228*0a96aa3bSJed Brown DM plex; 5229*0a96aa3bSJed Brown PetscErrorCode ierr; 5230*0a96aa3bSJed Brown 5231*0a96aa3bSJed Brown PetscFunctionBegin; 5232*0a96aa3bSJed Brown ierr = DMPforestGetPlex(dm,&plex);CHKERRQ(ierr); 5233*0a96aa3bSJed Brown ierr = DMCreateNeumannOverlap_Plex(plex,ovl,J,setup,setup_ctx);CHKERRQ(ierr); 5234*0a96aa3bSJed Brown if (!*setup) { 5235*0a96aa3bSJed Brown ierr = PetscObjectQueryFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", setup);CHKERRQ(ierr); 5236*0a96aa3bSJed Brown if (*setup) { 5237*0a96aa3bSJed Brown ierr = PetscObjectCompose((PetscObject)*ovl, "_DM_Original_HPDDM", (PetscObject)dm);CHKERRQ(ierr); 5238*0a96aa3bSJed Brown } 5239*0a96aa3bSJed Brown } 5240*0a96aa3bSJed Brown PetscFunctionReturn(0); 5241*0a96aa3bSJed Brown } 5242*0a96aa3bSJed Brown 5243*0a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm) 5244*0a96aa3bSJed Brown { 5245*0a96aa3bSJed Brown PetscErrorCode ierr; 5246*0a96aa3bSJed Brown 5247*0a96aa3bSJed Brown PetscFunctionBegin; 5248*0a96aa3bSJed Brown dm->ops->setup = DMSetUp_pforest; 5249*0a96aa3bSJed Brown dm->ops->view = DMView_pforest; 5250*0a96aa3bSJed Brown dm->ops->clone = DMClone_pforest; 5251*0a96aa3bSJed Brown dm->ops->createinterpolation = DMCreateInterpolation_pforest; 5252*0a96aa3bSJed Brown dm->ops->createinjection = DMCreateInjection_pforest; 5253*0a96aa3bSJed Brown dm->ops->setfromoptions = DMSetFromOptions_pforest; 5254*0a96aa3bSJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_pforest; 5255*0a96aa3bSJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_pforest; 5256*0a96aa3bSJed Brown dm->ops->createlocalvector = DMCreateLocalVector_pforest; 5257*0a96aa3bSJed Brown dm->ops->creatematrix = DMCreateMatrix_pforest; 5258*0a96aa3bSJed Brown dm->ops->projectfunctionlocal = DMProjectFunctionLocal_pforest; 5259*0a96aa3bSJed Brown dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_pforest; 5260*0a96aa3bSJed Brown dm->ops->projectfieldlocal = DMProjectFieldLocal_pforest; 5261*0a96aa3bSJed Brown dm->ops->createlocalsection = DMCreatelocalsection_pforest; 5262*0a96aa3bSJed Brown dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_pforest; 5263*0a96aa3bSJed Brown dm->ops->computel2diff = DMComputeL2Diff_pforest; 5264*0a96aa3bSJed Brown dm->ops->computel2fielddiff = DMComputeL2FieldDiff_pforest; 5265*0a96aa3bSJed Brown dm->ops->getdimpoints = DMGetDimPoints_pforest; 5266*0a96aa3bSJed Brown 5267*0a96aa3bSJed Brown ierr = PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_plex_pforest) "_C",DMConvert_plex_pforest);CHKERRQ(ierr); 5268*0a96aa3bSJed Brown ierr = PetscObjectComposeFunction((PetscObject)dm,PetscStringize(DMConvert_pforest_plex) "_C",DMConvert_pforest_plex);CHKERRQ(ierr); 5269*0a96aa3bSJed Brown ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",DMCreateNeumannOverlap_pforest);CHKERRQ(ierr); 5270*0a96aa3bSJed Brown ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",DMForestGetPartitionOverlap);CHKERRQ(ierr); 5271*0a96aa3bSJed Brown PetscFunctionReturn(0); 5272*0a96aa3bSJed Brown } 5273*0a96aa3bSJed Brown 5274*0a96aa3bSJed Brown #define DMCreate_pforest _append_pforest(DMCreate) 5275*0a96aa3bSJed Brown PETSC_EXTERN PetscErrorCode DMCreate_pforest(DM dm) 5276*0a96aa3bSJed Brown { 5277*0a96aa3bSJed Brown DM_Forest *forest; 5278*0a96aa3bSJed Brown DM_Forest_pforest *pforest; 5279*0a96aa3bSJed Brown PetscErrorCode ierr; 5280*0a96aa3bSJed Brown 5281*0a96aa3bSJed Brown PetscFunctionBegin; 5282*0a96aa3bSJed Brown ierr = PetscP4estInitialize();CHKERRQ(ierr); 5283*0a96aa3bSJed Brown ierr = DMCreate_Forest(dm);CHKERRQ(ierr); 5284*0a96aa3bSJed Brown ierr = DMInitialize_pforest(dm);CHKERRQ(ierr); 5285*0a96aa3bSJed Brown ierr = DMSetDimension(dm,P4EST_DIM);CHKERRQ(ierr); 5286*0a96aa3bSJed Brown 5287*0a96aa3bSJed Brown /* set forest defaults */ 5288*0a96aa3bSJed Brown ierr = DMForestSetTopology(dm,"unit");CHKERRQ(ierr); 5289*0a96aa3bSJed Brown ierr = DMForestSetMinimumRefinement(dm,0);CHKERRQ(ierr); 5290*0a96aa3bSJed Brown ierr = DMForestSetInitialRefinement(dm,0);CHKERRQ(ierr); 5291*0a96aa3bSJed Brown ierr = DMForestSetMaximumRefinement(dm,P4EST_QMAXLEVEL);CHKERRQ(ierr); 5292*0a96aa3bSJed Brown ierr = DMForestSetGradeFactor(dm,2);CHKERRQ(ierr); 5293*0a96aa3bSJed Brown ierr = DMForestSetAdjacencyDimension(dm,0);CHKERRQ(ierr); 5294*0a96aa3bSJed Brown ierr = DMForestSetPartitionOverlap(dm,0);CHKERRQ(ierr); 5295*0a96aa3bSJed Brown 5296*0a96aa3bSJed Brown /* create p4est data */ 5297*0a96aa3bSJed Brown ierr = PetscNewLog(dm,&pforest);CHKERRQ(ierr); 5298*0a96aa3bSJed Brown 5299*0a96aa3bSJed Brown forest = (DM_Forest*) dm->data; 5300*0a96aa3bSJed Brown forest->data = pforest; 5301*0a96aa3bSJed Brown forest->destroy = DMForestDestroy_pforest; 5302*0a96aa3bSJed Brown forest->ftemplate = DMForestTemplate_pforest; 5303*0a96aa3bSJed Brown forest->transfervec = DMForestTransferVec_pforest; 5304*0a96aa3bSJed Brown forest->transfervecfrombase = DMForestTransferVecFromBase_pforest; 5305*0a96aa3bSJed Brown forest->createcellchart = DMForestCreateCellChart_pforest; 5306*0a96aa3bSJed Brown forest->createcellsf = DMForestCreateCellSF_pforest; 5307*0a96aa3bSJed Brown forest->clearadaptivityforest = DMForestClearAdaptivityForest_pforest; 5308*0a96aa3bSJed Brown forest->getadaptivitysuccess = DMForestGetAdaptivitySuccess_pforest; 5309*0a96aa3bSJed Brown pforest->topo = NULL; 5310*0a96aa3bSJed Brown pforest->forest = NULL; 5311*0a96aa3bSJed Brown pforest->ghost = NULL; 5312*0a96aa3bSJed Brown pforest->lnodes = NULL; 5313*0a96aa3bSJed Brown pforest->partition_for_coarsening = PETSC_TRUE; 5314*0a96aa3bSJed Brown pforest->coarsen_hierarchy = PETSC_FALSE; 5315*0a96aa3bSJed Brown pforest->cLocalStart = -1; 5316*0a96aa3bSJed Brown pforest->cLocalEnd = -1; 5317*0a96aa3bSJed Brown pforest->labelsFinalized = PETSC_FALSE; 5318*0a96aa3bSJed Brown pforest->ghostName = NULL; 5319*0a96aa3bSJed Brown PetscFunctionReturn(0); 5320*0a96aa3bSJed Brown } 5321*0a96aa3bSJed Brown 5322*0a96aa3bSJed Brown #endif /* defined(PETSC_HAVE_P4EST) */ 5323