1a4963045SJacob Faibussowitsch #pragma once
23ea99036SJacob Faibussowitsch
30a96aa3bSJed Brown #include <petscds.h>
4707c51c7SToby Isaac #include <petscfe.h>
50a96aa3bSJed Brown #include <petsc/private/dmimpl.h>
60a96aa3bSJed Brown #include <petsc/private/dmforestimpl.h>
70a96aa3bSJed Brown #include <petsc/private/dmpleximpl.h>
80a96aa3bSJed Brown #include <petsc/private/dmlabelimpl.h>
90a96aa3bSJed Brown #include <petsc/private/viewerimpl.h>
100a96aa3bSJed Brown #include <../src/sys/classes/viewer/impls/vtk/vtkvimpl.h>
110a96aa3bSJed Brown #include "petsc_p4est_package.h"
120a96aa3bSJed Brown
130a96aa3bSJed Brown #if defined(PETSC_HAVE_P4EST)
140a96aa3bSJed Brown
150a96aa3bSJed Brown #if !defined(P4_TO_P8)
160a96aa3bSJed Brown #include <p4est.h>
170a96aa3bSJed Brown #include <p4est_extended.h>
180a96aa3bSJed Brown #include <p4est_geometry.h>
190a96aa3bSJed Brown #include <p4est_ghost.h>
200a96aa3bSJed Brown #include <p4est_lnodes.h>
210a96aa3bSJed Brown #include <p4est_vtk.h>
220a96aa3bSJed Brown #include <p4est_plex.h>
230a96aa3bSJed Brown #include <p4est_bits.h>
240a96aa3bSJed Brown #include <p4est_algorithms.h>
250a96aa3bSJed Brown #else
260a96aa3bSJed Brown #include <p8est.h>
270a96aa3bSJed Brown #include <p8est_extended.h>
280a96aa3bSJed Brown #include <p8est_geometry.h>
290a96aa3bSJed Brown #include <p8est_ghost.h>
300a96aa3bSJed Brown #include <p8est_lnodes.h>
310a96aa3bSJed Brown #include <p8est_vtk.h>
320a96aa3bSJed Brown #include <p8est_plex.h>
330a96aa3bSJed Brown #include <p8est_bits.h>
340a96aa3bSJed Brown #include <p8est_algorithms.h>
350a96aa3bSJed Brown #endif
360a96aa3bSJed Brown
379371c9d4SSatish Balay typedef enum {
389371c9d4SSatish Balay PATTERN_HASH,
399371c9d4SSatish Balay PATTERN_FRACTAL,
409371c9d4SSatish Balay PATTERN_CORNER,
419371c9d4SSatish Balay PATTERN_CENTER,
429371c9d4SSatish Balay PATTERN_COUNT
439371c9d4SSatish Balay } DMRefinePattern;
440a96aa3bSJed Brown static const char *DMRefinePatternName[PATTERN_COUNT] = {"hash", "fractal", "corner", "center"};
450a96aa3bSJed Brown
469371c9d4SSatish Balay typedef struct _DMRefinePatternCtx {
470a96aa3bSJed Brown PetscInt corner;
480a96aa3bSJed Brown PetscBool fractal[P4EST_CHILDREN];
490a96aa3bSJed Brown PetscReal hashLikelihood;
500a96aa3bSJed Brown PetscInt maxLevel;
510a96aa3bSJed Brown p4est_refine_t refine_fn;
529371c9d4SSatish Balay } DMRefinePatternCtx;
530a96aa3bSJed Brown
DMRefinePattern_Corner(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrant)54d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Corner(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant)
55d71ae5a4SJacob Faibussowitsch {
560a96aa3bSJed Brown p4est_quadrant_t root, rootcorner;
570a96aa3bSJed Brown DMRefinePatternCtx *ctx;
580a96aa3bSJed Brown
590a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer;
600a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0;
610a96aa3bSJed Brown
620a96aa3bSJed Brown root.x = root.y = 0;
630a96aa3bSJed Brown #if defined(P4_TO_P8)
640a96aa3bSJed Brown root.z = 0;
650a96aa3bSJed Brown #endif
660a96aa3bSJed Brown root.level = 0;
670a96aa3bSJed Brown p4est_quadrant_corner_descendant(&root, &rootcorner, ctx->corner, quadrant->level);
680a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant, &rootcorner)) return 1;
690a96aa3bSJed Brown return 0;
700a96aa3bSJed Brown }
710a96aa3bSJed Brown
DMRefinePattern_Center(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrant)72d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Center(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant)
73d71ae5a4SJacob Faibussowitsch {
740a96aa3bSJed Brown int cid;
750a96aa3bSJed Brown p4est_quadrant_t ancestor, ancestorcorner;
760a96aa3bSJed Brown DMRefinePatternCtx *ctx;
770a96aa3bSJed Brown
780a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer;
790a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0;
800a96aa3bSJed Brown if (quadrant->level <= 1) return 1;
810a96aa3bSJed Brown
820a96aa3bSJed Brown p4est_quadrant_ancestor(quadrant, 1, &ancestor);
830a96aa3bSJed Brown cid = p4est_quadrant_child_id(&ancestor);
840a96aa3bSJed Brown p4est_quadrant_corner_descendant(&ancestor, &ancestorcorner, P4EST_CHILDREN - 1 - cid, quadrant->level);
850a96aa3bSJed Brown if (p4est_quadrant_is_equal(quadrant, &ancestorcorner)) return 1;
860a96aa3bSJed Brown return 0;
870a96aa3bSJed Brown }
880a96aa3bSJed Brown
DMRefinePattern_Fractal(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrant)89d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Fractal(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant)
90d71ae5a4SJacob Faibussowitsch {
910a96aa3bSJed Brown int cid;
920a96aa3bSJed Brown DMRefinePatternCtx *ctx;
930a96aa3bSJed Brown
940a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer;
950a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0;
960a96aa3bSJed Brown if (!quadrant->level) return 1;
970a96aa3bSJed Brown cid = p4est_quadrant_child_id(quadrant);
980a96aa3bSJed Brown if (ctx->fractal[cid ^ ((int)(quadrant->level % P4EST_CHILDREN))]) return 1;
990a96aa3bSJed Brown return 0;
1000a96aa3bSJed Brown }
1010a96aa3bSJed Brown
1020a96aa3bSJed Brown /* simplified from MurmurHash3 by Austin Appleby */
1030a96aa3bSJed Brown #define DMPROT32(x, y) ((x << y) | (x >> (32 - y)))
DMPforestHash(const uint32_t * blocks,uint32_t nblocks)104d71ae5a4SJacob Faibussowitsch static uint32_t DMPforestHash(const uint32_t *blocks, uint32_t nblocks)
105d71ae5a4SJacob Faibussowitsch {
1060a96aa3bSJed Brown uint32_t c1 = 0xcc9e2d51;
1070a96aa3bSJed Brown uint32_t c2 = 0x1b873593;
1080a96aa3bSJed Brown uint32_t r1 = 15;
1090a96aa3bSJed Brown uint32_t r2 = 13;
1100a96aa3bSJed Brown uint32_t m = 5;
1110a96aa3bSJed Brown uint32_t n = 0xe6546b64;
1120a96aa3bSJed Brown uint32_t hash = 0;
1130a96aa3bSJed Brown int len = nblocks * 4;
1140a96aa3bSJed Brown uint32_t i;
1150a96aa3bSJed Brown
1160a96aa3bSJed Brown for (i = 0; i < nblocks; i++) {
1170a96aa3bSJed Brown uint32_t k;
1180a96aa3bSJed Brown
1190a96aa3bSJed Brown k = blocks[i];
1200a96aa3bSJed Brown k *= c1;
1210a96aa3bSJed Brown k = DMPROT32(k, r1);
1220a96aa3bSJed Brown k *= c2;
1230a96aa3bSJed Brown
1240a96aa3bSJed Brown hash ^= k;
1250a96aa3bSJed Brown hash = DMPROT32(hash, r2) * m + n;
1260a96aa3bSJed Brown }
1270a96aa3bSJed Brown
1280a96aa3bSJed Brown hash ^= len;
1290a96aa3bSJed Brown hash ^= (hash >> 16);
1300a96aa3bSJed Brown hash *= 0x85ebca6b;
1310a96aa3bSJed Brown hash ^= (hash >> 13);
1320a96aa3bSJed Brown hash *= 0xc2b2ae35;
1330a96aa3bSJed Brown hash ^= (hash >> 16);
1340a96aa3bSJed Brown
1350a96aa3bSJed Brown return hash;
1360a96aa3bSJed Brown }
1370a96aa3bSJed Brown
1380a96aa3bSJed Brown #if defined(UINT32_MAX)
1390a96aa3bSJed Brown #define DMP4EST_HASH_MAX UINT32_MAX
1400a96aa3bSJed Brown #else
1410a96aa3bSJed Brown #define DMP4EST_HASH_MAX ((uint32_t)0xffffffff)
1420a96aa3bSJed Brown #endif
1430a96aa3bSJed Brown
DMRefinePattern_Hash(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrant)144d71ae5a4SJacob Faibussowitsch static int DMRefinePattern_Hash(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant)
145d71ae5a4SJacob Faibussowitsch {
1460a96aa3bSJed Brown uint32_t data[5];
1470a96aa3bSJed Brown uint32_t result;
1480a96aa3bSJed Brown DMRefinePatternCtx *ctx;
1490a96aa3bSJed Brown
1500a96aa3bSJed Brown ctx = (DMRefinePatternCtx *)p4est->user_pointer;
1510a96aa3bSJed Brown if (quadrant->level >= ctx->maxLevel) return 0;
1520a96aa3bSJed Brown data[0] = ((uint32_t)quadrant->level) << 24;
1530a96aa3bSJed Brown data[1] = (uint32_t)which_tree;
1540a96aa3bSJed Brown data[2] = (uint32_t)quadrant->x;
1550a96aa3bSJed Brown data[3] = (uint32_t)quadrant->y;
1560a96aa3bSJed Brown #if defined(P4_TO_P8)
1570a96aa3bSJed Brown data[4] = (uint32_t)quadrant->z;
1580a96aa3bSJed Brown #endif
1590a96aa3bSJed Brown
1600a96aa3bSJed Brown result = DMPforestHash(data, 2 + P4EST_DIM);
1610a96aa3bSJed Brown if (((double)result / (double)DMP4EST_HASH_MAX) < ctx->hashLikelihood) return 1;
1620a96aa3bSJed Brown return 0;
1630a96aa3bSJed Brown }
1640a96aa3bSJed Brown
1650a96aa3bSJed Brown #define DMConvert_pforest_plex _infix_pforest(DMConvert, _plex)
1660a96aa3bSJed Brown static PetscErrorCode DMConvert_pforest_plex(DM, DMType, DM *);
1670a96aa3bSJed Brown
1680a96aa3bSJed Brown #define DMFTopology_pforest _append_pforest(DMFTopology)
1690a96aa3bSJed Brown typedef struct {
1700a96aa3bSJed Brown PetscInt refct;
1710a96aa3bSJed Brown p4est_connectivity_t *conn;
1720a96aa3bSJed Brown p4est_geometry_t *geom;
1730a96aa3bSJed Brown PetscInt *tree_face_to_uniq; /* p4est does not explicitly enumerate facets, but we must to keep track of labels */
1740a96aa3bSJed Brown } DMFTopology_pforest;
1750a96aa3bSJed Brown
1760a96aa3bSJed Brown #define DM_Forest_pforest _append_pforest(DM_Forest)
1770a96aa3bSJed Brown typedef struct {
1780a96aa3bSJed Brown DMFTopology_pforest *topo;
1790a96aa3bSJed Brown p4est_t *forest;
1800a96aa3bSJed Brown p4est_ghost_t *ghost;
1810a96aa3bSJed Brown p4est_lnodes_t *lnodes;
1820a96aa3bSJed Brown PetscBool partition_for_coarsening;
1830a96aa3bSJed Brown PetscBool coarsen_hierarchy;
1840a96aa3bSJed Brown PetscBool labelsFinalized;
1850a96aa3bSJed Brown PetscBool adaptivitySuccess;
1860a96aa3bSJed Brown PetscInt cLocalStart;
1870a96aa3bSJed Brown PetscInt cLocalEnd;
1880a96aa3bSJed Brown DM plex;
1890a96aa3bSJed Brown char *ghostName;
1900a96aa3bSJed Brown PetscSF pointAdaptToSelfSF;
1910a96aa3bSJed Brown PetscSF pointSelfToAdaptSF;
1920a96aa3bSJed Brown PetscInt *pointAdaptToSelfCids;
1930a96aa3bSJed Brown PetscInt *pointSelfToAdaptCids;
1940a96aa3bSJed Brown } DM_Forest_pforest;
1950a96aa3bSJed Brown
1960a96aa3bSJed Brown #define DM_Forest_geometry_pforest _append_pforest(DM_Forest_geometry)
1970a96aa3bSJed Brown typedef struct {
1980a96aa3bSJed Brown DM base;
1990a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *);
2000a96aa3bSJed Brown void *mapCtx;
2010a96aa3bSJed Brown PetscInt coordDim;
2020a96aa3bSJed Brown p4est_geometry_t *inner;
2039371c9d4SSatish Balay } DM_Forest_geometry_pforest;
2040a96aa3bSJed Brown
2050a96aa3bSJed Brown #define GeometryMapping_pforest _append_pforest(GeometryMapping)
GeometryMapping_pforest(p4est_geometry_t * geom,p4est_topidx_t which_tree,const double abc[3],double xyz[3])206d71ae5a4SJacob Faibussowitsch static void GeometryMapping_pforest(p4est_geometry_t *geom, p4est_topidx_t which_tree, const double abc[3], double xyz[3])
207d71ae5a4SJacob Faibussowitsch {
2080a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest *)geom->user;
2090a96aa3bSJed Brown PetscReal PetscABC[3] = {0.};
2100a96aa3bSJed Brown PetscReal PetscXYZ[3] = {0.};
2110a96aa3bSJed Brown PetscInt i, d = PetscMin(3, geom_pforest->coordDim);
2120a96aa3bSJed Brown double ABC[3];
2130a96aa3bSJed Brown PetscErrorCode ierr;
2140a96aa3bSJed Brown
2150a96aa3bSJed Brown (geom_pforest->inner->X)(geom_pforest->inner, which_tree, abc, ABC);
2160a96aa3bSJed Brown
2170a96aa3bSJed Brown for (i = 0; i < d; i++) PetscABC[i] = ABC[i];
2189371c9d4SSatish Balay ierr = (geom_pforest->map)(geom_pforest->base, (PetscInt)which_tree, geom_pforest->coordDim, PetscABC, PetscXYZ, geom_pforest->mapCtx);
2199371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr);
2200a96aa3bSJed Brown for (i = 0; i < d; i++) xyz[i] = PetscXYZ[i];
2210a96aa3bSJed Brown }
2220a96aa3bSJed Brown
2230a96aa3bSJed Brown #define GeometryDestroy_pforest _append_pforest(GeometryDestroy)
GeometryDestroy_pforest(p4est_geometry_t * geom)224d71ae5a4SJacob Faibussowitsch static void GeometryDestroy_pforest(p4est_geometry_t *geom)
225d71ae5a4SJacob Faibussowitsch {
2260a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest = (DM_Forest_geometry_pforest *)geom->user;
2270a96aa3bSJed Brown PetscErrorCode ierr;
2280a96aa3bSJed Brown
2290a96aa3bSJed Brown p4est_geometry_destroy(geom_pforest->inner);
2309371c9d4SSatish Balay ierr = PetscFree(geom->user);
2319371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr);
2329371c9d4SSatish Balay ierr = PetscFree(geom);
2339371c9d4SSatish Balay PETSC_P4EST_ASSERT(!ierr);
2340a96aa3bSJed Brown }
2350a96aa3bSJed Brown
2360a96aa3bSJed Brown #define DMFTopologyDestroy_pforest _append_pforest(DMFTopologyDestroy)
DMFTopologyDestroy_pforest(DMFTopology_pforest ** topo)237d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFTopologyDestroy_pforest(DMFTopology_pforest **topo)
238d71ae5a4SJacob Faibussowitsch {
2390a96aa3bSJed Brown PetscFunctionBegin;
2404ad8454bSPierre Jolivet if (!*topo) PetscFunctionReturn(PETSC_SUCCESS);
2410a96aa3bSJed Brown if (--((*topo)->refct) > 0) {
2420a96aa3bSJed Brown *topo = NULL;
2433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2440a96aa3bSJed Brown }
245792fecdfSBarry Smith if ((*topo)->geom) PetscCallP4est(p4est_geometry_destroy, ((*topo)->geom));
246792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy, ((*topo)->conn));
2479566063dSJacob Faibussowitsch PetscCall(PetscFree((*topo)->tree_face_to_uniq));
2489566063dSJacob Faibussowitsch PetscCall(PetscFree(*topo));
2490a96aa3bSJed Brown *topo = NULL;
2503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2510a96aa3bSJed Brown }
2520a96aa3bSJed Brown
2530a96aa3bSJed Brown static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *, PetscInt **);
2540a96aa3bSJed Brown
2550a96aa3bSJed Brown #define DMFTopologyCreateBrick_pforest _append_pforest(DMFTopologyCreateBrick)
DMFTopologyCreateBrick_pforest(DM dm,PetscInt N[],PetscInt P[],PetscReal B[],DMFTopology_pforest ** topo,PetscBool useMorton)256d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFTopologyCreateBrick_pforest(DM dm, PetscInt N[], PetscInt P[], PetscReal B[], DMFTopology_pforest **topo, PetscBool useMorton)
257d71ae5a4SJacob Faibussowitsch {
2580a96aa3bSJed Brown double *vertices;
2590a96aa3bSJed Brown PetscInt i, numVerts;
2600a96aa3bSJed Brown
2610a96aa3bSJed Brown PetscFunctionBegin;
26228b400f6SJacob Faibussowitsch PetscCheck(useMorton, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Lexicographic ordering not implemented yet");
2634dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(topo));
2640a96aa3bSJed Brown
2650a96aa3bSJed Brown (*topo)->refct = 1;
2660a96aa3bSJed Brown #if !defined(P4_TO_P8)
267792fecdfSBarry Smith PetscCallP4estReturn((*topo)->conn, p4est_connectivity_new_brick, ((int)N[0], (int)N[1], (P[0] == DM_BOUNDARY_NONE) ? 0 : 1, (P[1] == DM_BOUNDARY_NONE) ? 0 : 1));
2680a96aa3bSJed Brown #else
269792fecdfSBarry Smith PetscCallP4estReturn((*topo)->conn, p8est_connectivity_new_brick, ((int)N[0], (int)N[1], (int)N[2], (P[0] == DM_BOUNDARY_NONE) ? 0 : 1, (P[1] == DM_BOUNDARY_NONE) ? 0 : 1, (P[2] == DM_BOUNDARY_NONE) ? 0 : 1));
2700a96aa3bSJed Brown #endif
2710a96aa3bSJed Brown numVerts = (*topo)->conn->num_vertices;
2720a96aa3bSJed Brown vertices = (*topo)->conn->vertices;
2730a96aa3bSJed Brown for (i = 0; i < 3 * numVerts; i++) {
2740a96aa3bSJed Brown PetscInt j = i % 3;
2750a96aa3bSJed Brown
2760a96aa3bSJed Brown vertices[i] = B[2 * j] + (vertices[i] / N[j]) * (B[2 * j + 1] - B[2 * j]);
2770a96aa3bSJed Brown }
2780a96aa3bSJed Brown (*topo)->geom = NULL;
2799566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn, &(*topo)->tree_face_to_uniq));
2803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2810a96aa3bSJed Brown }
2820a96aa3bSJed Brown
2830a96aa3bSJed Brown #define DMFTopologyCreate_pforest _append_pforest(DMFTopologyCreate)
DMFTopologyCreate_pforest(DM dm,DMForestTopology topologyName,DMFTopology_pforest ** topo)284d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFTopologyCreate_pforest(DM dm, DMForestTopology topologyName, DMFTopology_pforest **topo)
285d71ae5a4SJacob Faibussowitsch {
2860a96aa3bSJed Brown const char *name = (const char *)topologyName;
2870a96aa3bSJed Brown const char *prefix;
2880a96aa3bSJed Brown PetscBool isBrick, isShell, isSphere, isMoebius;
2890a96aa3bSJed Brown
2900a96aa3bSJed Brown PetscFunctionBegin;
2910a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2924f572ea9SToby Isaac PetscAssertPointer(name, 2);
2934f572ea9SToby Isaac PetscAssertPointer(topo, 3);
2949566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "brick", &isBrick));
2959566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "shell", &isShell));
2969566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "sphere", &isSphere));
2979566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "moebius", &isMoebius));
2989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
2990a96aa3bSJed Brown if (isBrick) {
3000a96aa3bSJed Brown PetscBool flgN, flgP, flgM, flgB, useMorton = PETSC_TRUE, periodic = PETSC_FALSE;
3010a96aa3bSJed Brown PetscInt N[3] = {2, 2, 2}, P[3] = {0, 0, 0}, nretN = P4EST_DIM, nretP = P4EST_DIM, nretB = 2 * P4EST_DIM, i;
3024fb89dddSMatthew G. Knepley PetscReal B[6] = {0.0, 1.0, 0.0, 1.0, 0.0, 1.0}, Lstart[3] = {0., 0., 0.}, L[3] = {-1.0, -1.0, -1.0}, maxCell[3] = {-1.0, -1.0, -1.0};
3030a96aa3bSJed Brown
3040a96aa3bSJed Brown if (dm->setfromoptionscalled) {
3059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_size", N, &nretN, &flgN));
3069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_periodicity", P, &nretP, &flgP));
3079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_bounds", B, &nretB, &flgB));
3089566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, prefix, "-dm_p4est_brick_use_morton_curve", &useMorton, &flgM));
3091dca8a05SBarry Smith PetscCheck(!flgN || nretN == P4EST_DIM, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Need to give %d sizes in -dm_p4est_brick_size, gave %" PetscInt_FMT, P4EST_DIM, nretN);
3101dca8a05SBarry Smith PetscCheck(!flgP || nretP == P4EST_DIM, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Need to give %d periodicities in -dm_p4est_brick_periodicity, gave %" PetscInt_FMT, P4EST_DIM, nretP);
3111dca8a05SBarry Smith PetscCheck(!flgB || nretB == 2 * P4EST_DIM, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Need to give %d bounds in -dm_p4est_brick_bounds, gave %" PetscInt_FMT, P4EST_DIM, nretP);
3120a96aa3bSJed Brown }
3130a96aa3bSJed Brown for (i = 0; i < P4EST_DIM; i++) {
3140a96aa3bSJed Brown P[i] = (P[i] ? DM_BOUNDARY_PERIODIC : DM_BOUNDARY_NONE);
3150a96aa3bSJed Brown periodic = (PetscBool)(P[i] || periodic);
3160a96aa3bSJed Brown if (!flgB) B[2 * i + 1] = N[i];
3176858538eSMatthew G. Knepley if (P[i]) {
3184fb89dddSMatthew G. Knepley Lstart[i] = B[2 * i + 0];
3194fb89dddSMatthew G. Knepley L[i] = B[2 * i + 1] - B[2 * i + 0];
3206858538eSMatthew G. Knepley maxCell[i] = 1.1 * (L[i] / N[i]);
3216858538eSMatthew G. Knepley }
3220a96aa3bSJed Brown }
3239566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm, N, P, B, topo, useMorton));
3244fb89dddSMatthew G. Knepley if (periodic) PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
3250a96aa3bSJed Brown } else {
3264dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(topo));
3270a96aa3bSJed Brown
3280a96aa3bSJed Brown (*topo)->refct = 1;
329792fecdfSBarry Smith PetscCallP4estReturn((*topo)->conn, p4est_connectivity_new_byname, (name));
3300a96aa3bSJed Brown (*topo)->geom = NULL;
3311baa6e33SBarry Smith if (isMoebius) PetscCall(DMSetCoordinateDim(dm, 3));
3320a96aa3bSJed Brown #if defined(P4_TO_P8)
3330a96aa3bSJed Brown if (isShell) {
3340a96aa3bSJed Brown PetscReal R2 = 1., R1 = .55;
3350a96aa3bSJed Brown
3360a96aa3bSJed Brown if (dm->setfromoptionscalled) {
3379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_shell_outer_radius", &R2, NULL));
3389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_shell_inner_radius", &R1, NULL));
3390a96aa3bSJed Brown }
340792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom, p8est_geometry_new_shell, ((*topo)->conn, R2, R1));
3410a96aa3bSJed Brown } else if (isSphere) {
3420a96aa3bSJed Brown PetscReal R2 = 1., R1 = 0.191728, R0 = 0.039856;
3430a96aa3bSJed Brown
3440a96aa3bSJed Brown if (dm->setfromoptionscalled) {
3459566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_outer_radius", &R2, NULL));
3469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_inner_radius", &R1, NULL));
3479566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_sphere_core_radius", &R0, NULL));
3480a96aa3bSJed Brown }
349792fecdfSBarry Smith PetscCallP4estReturn((*topo)->geom, p8est_geometry_new_sphere, ((*topo)->conn, R2, R1, R0));
3500a96aa3bSJed Brown }
3510a96aa3bSJed Brown #endif
3529566063dSJacob Faibussowitsch PetscCall(PforestConnectivityEnumerateFacets((*topo)->conn, &(*topo)->tree_face_to_uniq));
3530a96aa3bSJed Brown }
3543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3550a96aa3bSJed Brown }
3560a96aa3bSJed Brown
3570a96aa3bSJed Brown #define DMConvert_plex_pforest _append_pforest(DMConvert_plex)
DMConvert_plex_pforest(DM dm,DMType newtype,DM * pforest)358d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMConvert_plex_pforest(DM dm, DMType newtype, DM *pforest)
359d71ae5a4SJacob Faibussowitsch {
3600a96aa3bSJed Brown MPI_Comm comm;
3610a96aa3bSJed Brown PetscBool isPlex;
3620a96aa3bSJed Brown PetscInt dim;
3630a96aa3bSJed Brown void *ctx;
3640a96aa3bSJed Brown
3650a96aa3bSJed Brown PetscFunctionBegin;
3660a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3670a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm);
3689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isPlex));
36928b400f6SJacob Faibussowitsch PetscCheck(isPlex, comm, PETSC_ERR_ARG_WRONG, "Expected DM type %s, got %s", DMPLEX, ((PetscObject)dm)->type_name);
3709566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
37163a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM, comm, PETSC_ERR_ARG_WRONG, "Expected DM dimension %d, got %" PetscInt_FMT, P4EST_DIM, dim);
3729566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, pforest));
3739566063dSJacob Faibussowitsch PetscCall(DMSetType(*pforest, DMPFOREST));
3749566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(*pforest, dm));
3759566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dm, &ctx));
3769566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(*pforest, ctx));
3779566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *pforest));
3783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3790a96aa3bSJed Brown }
3800a96aa3bSJed Brown
3810a96aa3bSJed Brown #define DMForestDestroy_pforest _append_pforest(DMForestDestroy)
DMForestDestroy_pforest(DM dm)382d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestDestroy_pforest(DM dm)
383d71ae5a4SJacob Faibussowitsch {
3840a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data;
3850a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data;
3860a96aa3bSJed Brown
3870a96aa3bSJed Brown PetscFunctionBegin;
3880a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
389792fecdfSBarry Smith if (pforest->lnodes) PetscCallP4est(p4est_lnodes_destroy, (pforest->lnodes));
3900a96aa3bSJed Brown pforest->lnodes = NULL;
391792fecdfSBarry Smith if (pforest->ghost) PetscCallP4est(p4est_ghost_destroy, (pforest->ghost));
3920a96aa3bSJed Brown pforest->ghost = NULL;
393792fecdfSBarry Smith if (pforest->forest) PetscCallP4est(p4est_destroy, (pforest->forest));
3940a96aa3bSJed Brown pforest->forest = NULL;
3959566063dSJacob Faibussowitsch PetscCall(DMFTopologyDestroy_pforest(&pforest->topo));
3969566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName));
3979566063dSJacob Faibussowitsch PetscCall(DMDestroy(&pforest->plex));
3989566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointAdaptToSelfSF));
3999566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pforest->pointSelfToAdaptSF));
4009566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids));
4019566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids));
4029566063dSJacob Faibussowitsch PetscCall(PetscFree(forest->data));
4033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4040a96aa3bSJed Brown }
4050a96aa3bSJed Brown
4060a96aa3bSJed Brown #define DMForestTemplate_pforest _append_pforest(DMForestTemplate)
DMForestTemplate_pforest(DM dm,DM tdm)407d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestTemplate_pforest(DM dm, DM tdm)
408d71ae5a4SJacob Faibussowitsch {
4090a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data;
4100a96aa3bSJed Brown DM_Forest_pforest *tpforest = (DM_Forest_pforest *)((DM_Forest *)tdm->data)->data;
4110a96aa3bSJed Brown
4120a96aa3bSJed Brown PetscFunctionBegin;
4130a96aa3bSJed Brown if (pforest->topo) pforest->topo->refct++;
414f4f49eeaSPierre Jolivet PetscCall(DMFTopologyDestroy_pforest(&tpforest->topo));
4150a96aa3bSJed Brown tpforest->topo = pforest->topo;
4163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4170a96aa3bSJed Brown }
4180a96aa3bSJed Brown
4190a96aa3bSJed Brown #define DMPlexCreateConnectivity_pforest _append_pforest(DMPlexCreateConnectivity)
4200a96aa3bSJed Brown static PetscErrorCode DMPlexCreateConnectivity_pforest(DM, p4est_connectivity_t **, PetscInt **);
4210a96aa3bSJed Brown
4229371c9d4SSatish Balay typedef struct _PforestAdaptCtx {
4230a96aa3bSJed Brown PetscInt maxLevel;
4240a96aa3bSJed Brown PetscInt minLevel;
4250a96aa3bSJed Brown PetscInt currLevel;
4260a96aa3bSJed Brown PetscBool anyChange;
4279371c9d4SSatish Balay } PforestAdaptCtx;
4280a96aa3bSJed Brown
pforest_coarsen_currlevel(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrants[])429d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_currlevel(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[])
430d71ae5a4SJacob Faibussowitsch {
4310a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer;
4320a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel;
4330a96aa3bSJed Brown PetscInt currLevel = ctx->currLevel;
4340a96aa3bSJed Brown
4350a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0;
4360a96aa3bSJed Brown return (int)((PetscInt)quadrants[0]->level == currLevel);
4370a96aa3bSJed Brown }
4380a96aa3bSJed Brown
pforest_coarsen_uniform(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrants[])439d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_uniform(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[])
440d71ae5a4SJacob Faibussowitsch {
4410a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer;
4420a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel;
4430a96aa3bSJed Brown
4440a96aa3bSJed Brown return (int)((PetscInt)quadrants[0]->level > minLevel);
4450a96aa3bSJed Brown }
4460a96aa3bSJed Brown
pforest_coarsen_flag_any(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrants[])447d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_flag_any(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[])
448d71ae5a4SJacob Faibussowitsch {
4490a96aa3bSJed Brown PetscInt i;
4500a96aa3bSJed Brown PetscBool any = PETSC_FALSE;
4510a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer;
4520a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel;
4530a96aa3bSJed Brown
4540a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0;
4550a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) {
4560a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_KEEP) {
4570a96aa3bSJed Brown any = PETSC_FALSE;
4580a96aa3bSJed Brown break;
4590a96aa3bSJed Brown }
4600a96aa3bSJed Brown if (quadrants[i]->p.user_int == DM_ADAPT_COARSEN) {
4610a96aa3bSJed Brown any = PETSC_TRUE;
4620a96aa3bSJed Brown break;
4630a96aa3bSJed Brown }
4640a96aa3bSJed Brown }
4650a96aa3bSJed Brown return any ? 1 : 0;
4660a96aa3bSJed Brown }
4670a96aa3bSJed Brown
pforest_coarsen_flag_all(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrants[])468d71ae5a4SJacob Faibussowitsch static int pforest_coarsen_flag_all(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrants[])
469d71ae5a4SJacob Faibussowitsch {
4700a96aa3bSJed Brown PetscInt i;
4710a96aa3bSJed Brown PetscBool all = PETSC_TRUE;
4720a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer;
4730a96aa3bSJed Brown PetscInt minLevel = ctx->minLevel;
4740a96aa3bSJed Brown
4750a96aa3bSJed Brown if (quadrants[0]->level <= minLevel) return 0;
4760a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) {
4770a96aa3bSJed Brown if (quadrants[i]->p.user_int != DM_ADAPT_COARSEN) {
4780a96aa3bSJed Brown all = PETSC_FALSE;
4790a96aa3bSJed Brown break;
4800a96aa3bSJed Brown }
4810a96aa3bSJed Brown }
4820a96aa3bSJed Brown return all ? 1 : 0;
4830a96aa3bSJed Brown }
4840a96aa3bSJed Brown
pforest_init_determine(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrant)485d71ae5a4SJacob Faibussowitsch static void pforest_init_determine(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant)
486d71ae5a4SJacob Faibussowitsch {
4870a96aa3bSJed Brown quadrant->p.user_int = DM_ADAPT_DETERMINE;
4880a96aa3bSJed Brown }
4890a96aa3bSJed Brown
pforest_refine_uniform(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrant)490d71ae5a4SJacob Faibussowitsch static int pforest_refine_uniform(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant)
491d71ae5a4SJacob Faibussowitsch {
4920a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer;
4930a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel;
4940a96aa3bSJed Brown
4954ad8454bSPierre Jolivet return (PetscInt)quadrant->level < maxLevel;
4960a96aa3bSJed Brown }
4970a96aa3bSJed Brown
pforest_refine_flag(p4est_t * p4est,p4est_topidx_t which_tree,p4est_quadrant_t * quadrant)498d71ae5a4SJacob Faibussowitsch static int pforest_refine_flag(p4est_t *p4est, p4est_topidx_t which_tree, p4est_quadrant_t *quadrant)
499d71ae5a4SJacob Faibussowitsch {
5000a96aa3bSJed Brown PforestAdaptCtx *ctx = (PforestAdaptCtx *)p4est->user_pointer;
5010a96aa3bSJed Brown PetscInt maxLevel = ctx->maxLevel;
5020a96aa3bSJed Brown
5030a96aa3bSJed Brown if ((PetscInt)quadrant->level >= maxLevel) return 0;
5040a96aa3bSJed Brown
5054ad8454bSPierre Jolivet return quadrant->p.user_int == DM_ADAPT_REFINE;
5060a96aa3bSJed Brown }
5070a96aa3bSJed Brown
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)508d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestComputeLocalCellTransferSF_loop(p4est_t *p4estFrom, PetscInt FromOffset, p4est_t *p4estTo, PetscInt ToOffset, p4est_topidx_t flt, p4est_topidx_t llt, PetscInt *toFineLeavesCount, PetscInt *toLeaves, PetscSFNode *fromRoots, PetscInt *fromFineLeavesCount, PetscInt *fromLeaves, PetscSFNode *toRoots)
509d71ae5a4SJacob Faibussowitsch {
5100a96aa3bSJed Brown PetscMPIInt rank = p4estFrom->mpirank;
5110a96aa3bSJed Brown p4est_topidx_t t;
5120a96aa3bSJed Brown PetscInt toFineLeaves = 0, fromFineLeaves = 0;
5130a96aa3bSJed Brown
5140a96aa3bSJed Brown PetscFunctionBegin;
5155a96e07bSStefano Zampini /* -Wmaybe-uninitialized */
5165a96e07bSStefano Zampini *toFineLeavesCount = 0;
5175a96e07bSStefano Zampini *fromFineLeavesCount = 0;
5180a96aa3bSJed Brown for (t = flt; t <= llt; t++) { /* count roots and leaves */
5190a96aa3bSJed Brown p4est_tree_t *treeFrom = &(((p4est_tree_t *)p4estFrom->trees->array)[t]);
5200a96aa3bSJed Brown p4est_tree_t *treeTo = &(((p4est_tree_t *)p4estTo->trees->array)[t]);
5210a96aa3bSJed Brown p4est_quadrant_t *firstFrom = &treeFrom->first_desc;
5220a96aa3bSJed Brown p4est_quadrant_t *firstTo = &treeTo->first_desc;
5230a96aa3bSJed Brown PetscInt numFrom = (PetscInt)treeFrom->quadrants.elem_count;
5240a96aa3bSJed Brown PetscInt numTo = (PetscInt)treeTo->quadrants.elem_count;
5250a96aa3bSJed Brown p4est_quadrant_t *quadsFrom = (p4est_quadrant_t *)treeFrom->quadrants.array;
5260a96aa3bSJed Brown p4est_quadrant_t *quadsTo = (p4est_quadrant_t *)treeTo->quadrants.array;
5270a96aa3bSJed Brown PetscInt currentFrom, currentTo;
5280a96aa3bSJed Brown PetscInt treeOffsetFrom = (PetscInt)treeFrom->quadrants_offset;
5290a96aa3bSJed Brown PetscInt treeOffsetTo = (PetscInt)treeTo->quadrants_offset;
5300a96aa3bSJed Brown int comp;
5310a96aa3bSJed Brown
532792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (firstFrom, firstTo));
53328b400f6SJacob Faibussowitsch PetscCheck(comp, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "non-matching partitions");
5340a96aa3bSJed Brown
5350a96aa3bSJed Brown for (currentFrom = 0, currentTo = 0; currentFrom < numFrom && currentTo < numTo;) {
5360a96aa3bSJed Brown p4est_quadrant_t *quadFrom = &quadsFrom[currentFrom];
5370a96aa3bSJed Brown p4est_quadrant_t *quadTo = &quadsTo[currentTo];
5380a96aa3bSJed Brown
5390a96aa3bSJed Brown if (quadFrom->level == quadTo->level) {
5400a96aa3bSJed Brown if (toLeaves) {
5410a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset;
5420a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank;
5430a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset;
5440a96aa3bSJed Brown }
5450a96aa3bSJed Brown toFineLeaves++;
5460a96aa3bSJed Brown currentFrom++;
5470a96aa3bSJed Brown currentTo++;
5480a96aa3bSJed Brown } else {
5490a96aa3bSJed Brown int fromIsAncestor;
5500a96aa3bSJed Brown
551792fecdfSBarry Smith PetscCallP4estReturn(fromIsAncestor, p4est_quadrant_is_ancestor, (quadFrom, quadTo));
5520a96aa3bSJed Brown if (fromIsAncestor) {
5530a96aa3bSJed Brown p4est_quadrant_t lastDesc;
5540a96aa3bSJed Brown
5550a96aa3bSJed Brown if (toLeaves) {
5560a96aa3bSJed Brown toLeaves[toFineLeaves] = currentTo + treeOffsetTo + ToOffset;
5570a96aa3bSJed Brown fromRoots[toFineLeaves].rank = rank;
5580a96aa3bSJed Brown fromRoots[toFineLeaves].index = currentFrom + treeOffsetFrom + FromOffset;
5590a96aa3bSJed Brown }
5600a96aa3bSJed Brown toFineLeaves++;
5610a96aa3bSJed Brown currentTo++;
562792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant, (quadFrom, &lastDesc, quadTo->level));
563792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (quadTo, &lastDesc));
5640a96aa3bSJed Brown if (comp) currentFrom++;
5650a96aa3bSJed Brown } else {
5660a96aa3bSJed Brown p4est_quadrant_t lastDesc;
5670a96aa3bSJed Brown
5680a96aa3bSJed Brown if (fromLeaves) {
5690a96aa3bSJed Brown fromLeaves[fromFineLeaves] = currentFrom + treeOffsetFrom + FromOffset;
5700a96aa3bSJed Brown toRoots[fromFineLeaves].rank = rank;
5710a96aa3bSJed Brown toRoots[fromFineLeaves].index = currentTo + treeOffsetTo + ToOffset;
5720a96aa3bSJed Brown }
5730a96aa3bSJed Brown fromFineLeaves++;
5740a96aa3bSJed Brown currentFrom++;
575792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_last_descendant, (quadTo, &lastDesc, quadFrom->level));
576792fecdfSBarry Smith PetscCallP4estReturn(comp, p4est_quadrant_is_equal, (quadFrom, &lastDesc));
5770a96aa3bSJed Brown if (comp) currentTo++;
5780a96aa3bSJed Brown }
5790a96aa3bSJed Brown }
5800a96aa3bSJed Brown }
5810a96aa3bSJed Brown }
5820a96aa3bSJed Brown *toFineLeavesCount = toFineLeaves;
5830a96aa3bSJed Brown *fromFineLeavesCount = fromFineLeaves;
5843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
5850a96aa3bSJed Brown }
5860a96aa3bSJed Brown
5870a96aa3bSJed Brown /* Compute the maximum level across all the trees */
DMPforestGetRefinementLevel(DM dm,PetscInt * lev)588d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetRefinementLevel(DM dm, PetscInt *lev)
589d71ae5a4SJacob Faibussowitsch {
5900a96aa3bSJed Brown p4est_topidx_t t, flt, llt;
5910a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data;
5920a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data;
5930a96aa3bSJed Brown PetscInt maxlevelloc = 0;
5940a96aa3bSJed Brown p4est_t *p4est;
5950a96aa3bSJed Brown
5960a96aa3bSJed Brown PetscFunctionBegin;
59728b400f6SJacob Faibussowitsch PetscCheck(pforest, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing DM_Forest_pforest");
59828b400f6SJacob Faibussowitsch PetscCheck(pforest->forest, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing p4est_t");
5990a96aa3bSJed Brown p4est = pforest->forest;
6000a96aa3bSJed Brown flt = p4est->first_local_tree;
6010a96aa3bSJed Brown llt = p4est->last_local_tree;
6020a96aa3bSJed Brown for (t = flt; t <= llt; t++) {
6030a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4est->trees->array)[t]);
6040a96aa3bSJed Brown maxlevelloc = PetscMax((PetscInt)tree->maxlevel, maxlevelloc);
6050a96aa3bSJed Brown }
606462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&maxlevelloc, lev, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
6073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
6080a96aa3bSJed Brown }
6090a96aa3bSJed Brown
6100a96aa3bSJed Brown /* Puts identity in coarseToFine */
6110a96aa3bSJed Brown /* assumes a matching partition */
DMPforestComputeLocalCellTransferSF(MPI_Comm comm,p4est_t * p4estFrom,PetscInt FromOffset,p4est_t * p4estTo,PetscInt ToOffset,PetscSF * fromCoarseToFine,PetscSF * toCoarseFromFine)612d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestComputeLocalCellTransferSF(MPI_Comm comm, p4est_t *p4estFrom, PetscInt FromOffset, p4est_t *p4estTo, PetscInt ToOffset, PetscSF *fromCoarseToFine, PetscSF *toCoarseFromFine)
613d71ae5a4SJacob Faibussowitsch {
6140a96aa3bSJed Brown p4est_topidx_t flt, llt;
6150a96aa3bSJed Brown PetscSF fromCoarse, toCoarse;
6160a96aa3bSJed Brown PetscInt numRootsFrom, numRootsTo, numLeavesFrom, numLeavesTo;
6170a96aa3bSJed Brown PetscInt *fromLeaves = NULL, *toLeaves = NULL;
6180a96aa3bSJed Brown PetscSFNode *fromRoots = NULL, *toRoots = NULL;
6190a96aa3bSJed Brown
6200a96aa3bSJed Brown PetscFunctionBegin;
6210a96aa3bSJed Brown flt = p4estFrom->first_local_tree;
6220a96aa3bSJed Brown llt = p4estFrom->last_local_tree;
6239566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &fromCoarse));
62448a46eb9SPierre Jolivet if (toCoarseFromFine) PetscCall(PetscSFCreate(comm, &toCoarse));
6250a96aa3bSJed Brown numRootsFrom = p4estFrom->local_num_quadrants + FromOffset;
6260a96aa3bSJed Brown numRootsTo = p4estTo->local_num_quadrants + ToOffset;
6279566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom, FromOffset, p4estTo, ToOffset, flt, llt, &numLeavesTo, NULL, NULL, &numLeavesFrom, NULL, NULL));
6289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo, &toLeaves));
6299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesTo, &fromRoots));
6300a96aa3bSJed Brown if (toCoarseFromFine) {
6319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom, &fromLeaves));
6329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeavesFrom, &fromRoots));
6330a96aa3bSJed Brown }
6349566063dSJacob Faibussowitsch PetscCall(DMPforestComputeLocalCellTransferSF_loop(p4estFrom, FromOffset, p4estTo, ToOffset, flt, llt, &numLeavesTo, toLeaves, fromRoots, &numLeavesFrom, fromLeaves, toRoots));
6350a96aa3bSJed Brown if (!ToOffset && (numLeavesTo == numRootsTo)) { /* compress */
6369566063dSJacob Faibussowitsch PetscCall(PetscFree(toLeaves));
6379566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(fromCoarse, numRootsFrom, numLeavesTo, NULL, PETSC_OWN_POINTER, fromRoots, PETSC_OWN_POINTER));
6381baa6e33SBarry Smith } else PetscCall(PetscSFSetGraph(fromCoarse, numRootsFrom, numLeavesTo, toLeaves, PETSC_OWN_POINTER, fromRoots, PETSC_OWN_POINTER));
6390a96aa3bSJed Brown *fromCoarseToFine = fromCoarse;
6400a96aa3bSJed Brown if (toCoarseFromFine) {
6419566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(toCoarse, numRootsTo, numLeavesFrom, fromLeaves, PETSC_OWN_POINTER, toRoots, PETSC_OWN_POINTER));
6420a96aa3bSJed Brown *toCoarseFromFine = toCoarse;
6430a96aa3bSJed Brown }
6443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
6450a96aa3bSJed Brown }
6460a96aa3bSJed Brown
6470a96aa3bSJed Brown /* range of processes whose B sections overlap this ranks A section */
DMPforestComputeOverlappingRanks(PetscMPIInt size,PetscMPIInt rank,p4est_t * p4estA,p4est_t * p4estB,PetscInt * startB,PetscInt * endB)648d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestComputeOverlappingRanks(PetscMPIInt size, PetscMPIInt rank, p4est_t *p4estA, p4est_t *p4estB, PetscInt *startB, PetscInt *endB)
649d71ae5a4SJacob Faibussowitsch {
650f4f49eeaSPierre Jolivet p4est_quadrant_t *myCoarseStart = &p4estA->global_first_position[rank];
651f4f49eeaSPierre Jolivet p4est_quadrant_t *myCoarseEnd = &p4estA->global_first_position[rank + 1];
6520a96aa3bSJed Brown p4est_quadrant_t *globalFirstB = p4estB->global_first_position;
6530a96aa3bSJed Brown
6540a96aa3bSJed Brown PetscFunctionBegin;
6550a96aa3bSJed Brown *startB = -1;
6560a96aa3bSJed Brown *endB = -1;
6570a96aa3bSJed Brown if (p4estA->local_num_quadrants) {
6580a96aa3bSJed Brown PetscInt lo, hi, guess;
6590a96aa3bSJed Brown /* binary search to find interval containing myCoarseStart */
6600a96aa3bSJed Brown lo = 0;
6610a96aa3bSJed Brown hi = size;
6620a96aa3bSJed Brown guess = rank;
6630a96aa3bSJed Brown while (1) {
6640a96aa3bSJed Brown int startCompMy, myCompEnd;
6650a96aa3bSJed Brown
666792fecdfSBarry Smith PetscCallP4estReturn(startCompMy, p4est_quadrant_compare_piggy, (&globalFirstB[guess], myCoarseStart));
667792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd, p4est_quadrant_compare_piggy, (myCoarseStart, &globalFirstB[guess + 1]));
6680a96aa3bSJed Brown if (startCompMy <= 0 && myCompEnd < 0) {
6690a96aa3bSJed Brown *startB = guess;
6700a96aa3bSJed Brown break;
6710a96aa3bSJed Brown } else if (startCompMy > 0) { /* guess is to high */
6720a96aa3bSJed Brown hi = guess;
6730a96aa3bSJed Brown } else { /* guess is to low */
6740a96aa3bSJed Brown lo = guess + 1;
6750a96aa3bSJed Brown }
6760a96aa3bSJed Brown guess = lo + (hi - lo) / 2;
6770a96aa3bSJed Brown }
6780a96aa3bSJed Brown /* reset bounds, but not guess */
6790a96aa3bSJed Brown lo = 0;
6800a96aa3bSJed Brown hi = size;
6810a96aa3bSJed Brown while (1) {
6820a96aa3bSJed Brown int startCompMy, myCompEnd;
6830a96aa3bSJed Brown
684792fecdfSBarry Smith PetscCallP4estReturn(startCompMy, p4est_quadrant_compare_piggy, (&globalFirstB[guess], myCoarseEnd));
685792fecdfSBarry Smith PetscCallP4estReturn(myCompEnd, p4est_quadrant_compare_piggy, (myCoarseEnd, &globalFirstB[guess + 1]));
6860a96aa3bSJed Brown if (startCompMy < 0 && myCompEnd <= 0) { /* notice that the comparison operators are different from above */
6870a96aa3bSJed Brown *endB = guess + 1;
6880a96aa3bSJed Brown break;
6890a96aa3bSJed Brown } else if (startCompMy >= 0) { /* guess is to high */
6900a96aa3bSJed Brown hi = guess;
6910a96aa3bSJed Brown } else { /* guess is to low */
6920a96aa3bSJed Brown lo = guess + 1;
6930a96aa3bSJed Brown }
6940a96aa3bSJed Brown guess = lo + (hi - lo) / 2;
6950a96aa3bSJed Brown }
6960a96aa3bSJed Brown }
6973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
6980a96aa3bSJed Brown }
6990a96aa3bSJed Brown
7000a96aa3bSJed Brown static PetscErrorCode DMPforestGetPlex(DM, DM *);
7010a96aa3bSJed Brown
7020a96aa3bSJed Brown #define DMSetUp_pforest _append_pforest(DMSetUp)
DMSetUp_pforest(DM dm)703d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetUp_pforest(DM dm)
704d71ae5a4SJacob Faibussowitsch {
7050a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data;
7060a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data;
7070a96aa3bSJed Brown DM base, adaptFrom;
7080a96aa3bSJed Brown DMForestTopology topoName;
7090a96aa3bSJed Brown PetscSF preCoarseToFine = NULL, coarseToPreFine = NULL;
7100a96aa3bSJed Brown PforestAdaptCtx ctx;
7110a96aa3bSJed Brown
7120a96aa3bSJed Brown PetscFunctionBegin;
7131690c2aeSBarry Smith ctx.minLevel = PETSC_INT_MAX;
7140a96aa3bSJed Brown ctx.maxLevel = 0;
7150a96aa3bSJed Brown ctx.currLevel = 0;
7160a96aa3bSJed Brown ctx.anyChange = PETSC_FALSE;
7170a96aa3bSJed Brown /* sanity check */
7189566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm, &adaptFrom));
7199566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base));
7209566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm, &topoName));
7211dca8a05SBarry Smith PetscCheck(adaptFrom || base || topoName, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "A forest needs a topology, a base DM, or a DM to adapt from");
7220a96aa3bSJed Brown
7230a96aa3bSJed Brown /* === Step 1: DMFTopology === */
7240a96aa3bSJed Brown if (adaptFrom) { /* reference already created topology */
7250a96aa3bSJed Brown PetscBool ispforest;
7260a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest *)adaptFrom->data;
7270a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest *)aforest->data;
7280a96aa3bSJed Brown
7299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)adaptFrom, DMPFOREST, &ispforest));
73028b400f6SJacob Faibussowitsch PetscCheck(ispforest, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NOTSAMETYPE, "Trying to adapt from %s, which is not %s", ((PetscObject)adaptFrom)->type_name, DMPFOREST);
73128b400f6SJacob Faibussowitsch PetscCheck(apforest->topo, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "The pre-adaptation forest must have a topology");
7329566063dSJacob Faibussowitsch PetscCall(DMSetUp(adaptFrom));
7339566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base));
7349566063dSJacob Faibussowitsch PetscCall(DMForestGetTopology(dm, &topoName));
7350a96aa3bSJed Brown } else if (base) { /* construct a connectivity from base */
7360a96aa3bSJed Brown PetscBool isPlex, isDA;
7370a96aa3bSJed Brown
7389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)base, &topoName));
7399566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm, topoName));
7409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base, DMPLEX, &isPlex));
7419566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)base, DMDA, &isDA));
7420a96aa3bSJed Brown if (isPlex) {
7430a96aa3bSJed Brown MPI_Comm comm = PetscObjectComm((PetscObject)dm);
7440a96aa3bSJed Brown PetscInt depth;
7450a96aa3bSJed Brown PetscMPIInt size;
7460a96aa3bSJed Brown p4est_connectivity_t *conn = NULL;
7470a96aa3bSJed Brown DMFTopology_pforest *topo;
7480a96aa3bSJed Brown PetscInt *tree_face_to_uniq = NULL;
7490a96aa3bSJed Brown
7509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(base, &depth));
7510a96aa3bSJed Brown if (depth == 1) {
7520a96aa3bSJed Brown DM connDM;
7530a96aa3bSJed Brown
7549566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(base, &connDM));
7550a96aa3bSJed Brown base = connDM;
7569566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm, base));
7579566063dSJacob Faibussowitsch PetscCall(DMDestroy(&connDM));
75863a3b9bcSJacob Faibussowitsch } else PetscCheck(depth == P4EST_DIM, comm, PETSC_ERR_ARG_WRONG, "Base plex is neither interpolated nor uninterpolated? depth %" PetscInt_FMT ", expected 2 or %d", depth, P4EST_DIM + 1);
7599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
7600a96aa3bSJed Brown if (size > 1) {
7610a96aa3bSJed Brown DM dmRedundant;
7620a96aa3bSJed Brown PetscSF sf;
7630a96aa3bSJed Brown
7649566063dSJacob Faibussowitsch PetscCall(DMPlexGetRedundantDM(base, &sf, &dmRedundant));
76528b400f6SJacob Faibussowitsch PetscCheck(dmRedundant, comm, PETSC_ERR_PLIB, "Could not create redundant DM");
7669566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dmRedundant, "_base_migration_sf", (PetscObject)sf));
7679566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf));
7680a96aa3bSJed Brown base = dmRedundant;
7699566063dSJacob Faibussowitsch PetscCall(DMForestSetBaseDM(dm, base));
7709566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRedundant));
7710a96aa3bSJed Brown }
7729566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(base, NULL, "-dm_p4est_base_view"));
7739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConnectivity_pforest(base, &conn, &tree_face_to_uniq));
7744dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&topo));
7750a96aa3bSJed Brown topo->refct = 1;
7760a96aa3bSJed Brown topo->conn = conn;
7770a96aa3bSJed Brown topo->geom = NULL;
7780a96aa3bSJed Brown {
7790a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *);
7800a96aa3bSJed Brown void *mapCtx;
7810a96aa3bSJed Brown
7829566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx));
7830a96aa3bSJed Brown if (map) {
7840a96aa3bSJed Brown DM_Forest_geometry_pforest *geom_pforest;
7850a96aa3bSJed Brown p4est_geometry_t *geom;
7860a96aa3bSJed Brown
7879566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom_pforest));
7889566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &geom_pforest->coordDim));
7890a96aa3bSJed Brown geom_pforest->map = map;
7900a96aa3bSJed Brown geom_pforest->mapCtx = mapCtx;
791792fecdfSBarry Smith PetscCallP4estReturn(geom_pforest->inner, p4est_geometry_new_connectivity, (conn));
7929566063dSJacob Faibussowitsch PetscCall(PetscNew(&geom));
7930a96aa3bSJed Brown geom->name = topoName;
7940a96aa3bSJed Brown geom->user = geom_pforest;
7950a96aa3bSJed Brown geom->X = GeometryMapping_pforest;
7960a96aa3bSJed Brown geom->destroy = GeometryDestroy_pforest;
7970a96aa3bSJed Brown topo->geom = geom;
7980a96aa3bSJed Brown }
7990a96aa3bSJed Brown }
8000a96aa3bSJed Brown topo->tree_face_to_uniq = tree_face_to_uniq;
8010a96aa3bSJed Brown pforest->topo = topo;
80228b400f6SJacob Faibussowitsch } else PetscCheck(!isDA, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Not implemented yet");
8030a96aa3bSJed Brown #if 0
8040a96aa3bSJed Brown PetscInt N[3], P[3];
8050a96aa3bSJed Brown
8060a96aa3bSJed Brown /* get the sizes, periodicities */
8070a96aa3bSJed Brown /* ... */
8080a96aa3bSJed Brown /* don't use Morton order */
8099566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreateBrick_pforest(dm,N,P,&pforest->topo,PETSC_FALSE));
8100a96aa3bSJed Brown #endif
8110a96aa3bSJed Brown {
8120a96aa3bSJed Brown PetscInt numLabels, l;
8130a96aa3bSJed Brown
8149566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(base, &numLabels));
8150a96aa3bSJed Brown for (l = 0; l < numLabels; l++) {
8160a96aa3bSJed Brown PetscBool isDepth, isGhost, isVTK, isDim, isCellType;
8170a96aa3bSJed Brown DMLabel label, labelNew;
8180a96aa3bSJed Brown PetscInt defVal;
8190a96aa3bSJed Brown const char *name;
8200a96aa3bSJed Brown
8219566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(base, l, &name));
8229566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(base, l, &label));
8239566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth));
8240a96aa3bSJed Brown if (isDepth) continue;
8259566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "dim", &isDim));
8260a96aa3bSJed Brown if (isDim) continue;
8279566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType));
8280a96aa3bSJed Brown if (isCellType) continue;
8299566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost));
8300a96aa3bSJed Brown if (isGhost) continue;
8319566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK));
8320a96aa3bSJed Brown if (isVTK) continue;
8339566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name));
8349566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &labelNew));
8359566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defVal));
8369566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew, defVal));
8370a96aa3bSJed Brown }
8380a96aa3bSJed Brown /* map dm points (internal plex) to base
8390a96aa3bSJed Brown we currently create the subpoint_map for the entire hierarchy, starting from the finest forest
8400a96aa3bSJed Brown and propagating back to the coarsest
8410a96aa3bSJed Brown This is not an optimal approach, since we need the map only on the coarsest level
8420a96aa3bSJed Brown during DMForestTransferVecFromBase */
8439566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &l));
84448a46eb9SPierre Jolivet if (!l) PetscCall(DMCreateLabel(dm, "_forest_base_subpoint_map"));
8450a96aa3bSJed Brown }
8460a96aa3bSJed Brown } else { /* construct from topology name */
8470a96aa3bSJed Brown DMFTopology_pforest *topo;
8480a96aa3bSJed Brown
8499566063dSJacob Faibussowitsch PetscCall(DMFTopologyCreate_pforest(dm, topoName, &topo));
8500a96aa3bSJed Brown pforest->topo = topo;
8510a96aa3bSJed Brown /* TODO: construct base? */
8520a96aa3bSJed Brown }
8530a96aa3bSJed Brown
8540a96aa3bSJed Brown /* === Step 2: get the leaves of the forest === */
8550a96aa3bSJed Brown if (adaptFrom) { /* start with the old forest */
8560a96aa3bSJed Brown DMLabel adaptLabel;
8570a96aa3bSJed Brown PetscInt defaultValue;
8580a96aa3bSJed Brown PetscInt numValues, numValuesGlobal, cLocalStart, count;
8590a96aa3bSJed Brown DM_Forest *aforest = (DM_Forest *)adaptFrom->data;
8600a96aa3bSJed Brown DM_Forest_pforest *apforest = (DM_Forest_pforest *)aforest->data;
8610a96aa3bSJed Brown PetscBool computeAdaptSF;
8620a96aa3bSJed Brown p4est_topidx_t flt, llt, t;
8630a96aa3bSJed Brown
8640a96aa3bSJed Brown flt = apforest->forest->first_local_tree;
8650a96aa3bSJed Brown llt = apforest->forest->last_local_tree;
8660a96aa3bSJed Brown cLocalStart = apforest->cLocalStart;
8679566063dSJacob Faibussowitsch PetscCall(DMForestGetComputeAdaptivitySF(dm, &computeAdaptSF));
868792fecdfSBarry Smith PetscCallP4estReturn(pforest->forest, p4est_copy, (apforest->forest, 0)); /* 0 indicates no data copying */
8699566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm, &adaptLabel));
8700a96aa3bSJed Brown if (adaptLabel) {
8710a96aa3bSJed Brown /* apply the refinement/coarsening by flags, plus minimum/maximum refinement */
8729566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(adaptLabel, &numValues));
873462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&numValues, &numValuesGlobal, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)adaptFrom)));
8749566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(adaptLabel, &defaultValue));
8750a96aa3bSJed Brown if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN_LAST) { /* uniform coarsen of the last level only (equivalent to DM_ADAPT_COARSEN for conforming grids) */
8769566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel));
8779566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm, &ctx.currLevel));
8780a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx;
879792fecdfSBarry Smith PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_currlevel, NULL));
8800a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm;
881792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL));
8820a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */
88348a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), pforest->forest, 0, apforest->forest, apforest->cLocalStart, &coarseToPreFine, NULL));
8840a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_COARSEN) { /* uniform coarsen */
8859566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel));
8860a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx;
887792fecdfSBarry Smith PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_uniform, NULL));
8880a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm;
889792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL));
8900a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */
89148a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), pforest->forest, 0, apforest->forest, apforest->cLocalStart, &coarseToPreFine, NULL));
8920a96aa3bSJed Brown } else if (!numValuesGlobal && defaultValue == DM_ADAPT_REFINE) { /* uniform refine */
8939566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &ctx.maxLevel));
8940a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx;
895792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 0, pforest_refine_uniform, NULL));
8960a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm;
897792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL));
8980a96aa3bSJed Brown /* we will have to change the offset after we compute the overlap */
89948a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), apforest->forest, apforest->cLocalStart, pforest->forest, 0, &preCoarseToFine, NULL));
9000a96aa3bSJed Brown } else if (numValuesGlobal) {
9010a96aa3bSJed Brown p4est_t *p4est = pforest->forest;
9020a96aa3bSJed Brown PetscInt *cellFlags;
9030a96aa3bSJed Brown DMForestAdaptivityStrategy strategy;
9040a96aa3bSJed Brown PetscSF cellSF;
9050a96aa3bSJed Brown PetscInt c, cStart, cEnd;
9060a96aa3bSJed Brown PetscBool adaptAny;
9070a96aa3bSJed Brown
9089566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &ctx.maxLevel));
9099566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &ctx.minLevel));
9109566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityStrategy(dm, &strategy));
9119566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(strategy, "any", 3, &adaptAny));
9129566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(adaptFrom, &cStart, &cEnd));
9139566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(adaptFrom, &cellSF));
9149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cStart, &cellFlags));
9159566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; c++) PetscCall(DMLabelGetValue(adaptLabel, c, &cellFlags[c - cStart]));
9160a96aa3bSJed Brown if (cellSF) {
9170a96aa3bSJed Brown if (adaptAny) {
9189566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MAX));
9199566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MAX));
9200a96aa3bSJed Brown } else {
9219566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MIN));
9229566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(cellSF, MPIU_INT, cellFlags, cellFlags, MPI_MIN));
9230a96aa3bSJed Brown }
9240a96aa3bSJed Brown }
9250a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) {
9260a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4est->trees->array)[t]);
9270a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count, i;
9280a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array;
9290a96aa3bSJed Brown
9300a96aa3bSJed Brown for (i = 0; i < numQuads; i++) {
9310a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i];
9320a96aa3bSJed Brown q->p.user_int = cellFlags[count++];
9330a96aa3bSJed Brown }
9340a96aa3bSJed Brown }
9359566063dSJacob Faibussowitsch PetscCall(PetscFree(cellFlags));
9360a96aa3bSJed Brown
9370a96aa3bSJed Brown pforest->forest->user_pointer = (void *)&ctx;
938792fecdfSBarry Smith if (adaptAny) PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_flag_any, pforest_init_determine));
939792fecdfSBarry Smith else PetscCallP4est(p4est_coarsen, (pforest->forest, 0, pforest_coarsen_flag_all, pforest_init_determine));
940792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 0, pforest_refine_flag, NULL));
9410a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm;
942792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL));
94348a46eb9SPierre Jolivet if (computeAdaptSF) PetscCall(DMPforestComputeLocalCellTransferSF(PetscObjectComm((PetscObject)dm), apforest->forest, apforest->cLocalStart, pforest->forest, 0, &preCoarseToFine, &coarseToPreFine));
9440a96aa3bSJed Brown }
9450a96aa3bSJed Brown for (t = flt, count = cLocalStart; t <= llt; t++) {
9460a96aa3bSJed Brown p4est_tree_t *atree = &(((p4est_tree_t *)apforest->forest->trees->array)[t]);
9470a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)pforest->forest->trees->array)[t]);
9480a96aa3bSJed Brown PetscInt anumQuads = (PetscInt)atree->quadrants.elem_count, i;
9490a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count;
9500a96aa3bSJed Brown p4est_quadrant_t *aquads = (p4est_quadrant_t *)atree->quadrants.array;
9510a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array;
9520a96aa3bSJed Brown
9530a96aa3bSJed Brown if (anumQuads != numQuads) {
9540a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE;
9550a96aa3bSJed Brown } else {
9560a96aa3bSJed Brown for (i = 0; i < numQuads; i++) {
9570a96aa3bSJed Brown p4est_quadrant_t *aq = &aquads[i];
9580a96aa3bSJed Brown p4est_quadrant_t *q = &quads[i];
9590a96aa3bSJed Brown
9600a96aa3bSJed Brown if (aq->level != q->level) {
9610a96aa3bSJed Brown ctx.anyChange = PETSC_TRUE;
9620a96aa3bSJed Brown break;
9630a96aa3bSJed Brown }
9640a96aa3bSJed Brown }
9650a96aa3bSJed Brown }
966ad540459SPierre Jolivet if (ctx.anyChange) break;
9670a96aa3bSJed Brown }
9680a96aa3bSJed Brown }
9690a96aa3bSJed Brown {
9700a96aa3bSJed Brown PetscInt numLabels, l;
9710a96aa3bSJed Brown
9729566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(adaptFrom, &numLabels));
9730a96aa3bSJed Brown for (l = 0; l < numLabels; l++) {
9740a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK;
9750a96aa3bSJed Brown DMLabel label, labelNew;
9760a96aa3bSJed Brown PetscInt defVal;
9770a96aa3bSJed Brown const char *name;
9780a96aa3bSJed Brown
9799566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(adaptFrom, l, &name));
9809566063dSJacob Faibussowitsch PetscCall(DMGetLabelByNum(adaptFrom, l, &label));
9819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth));
9820a96aa3bSJed Brown if (isDepth) continue;
9839566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType));
9840a96aa3bSJed Brown if (isCellType) continue;
9859566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost));
9860a96aa3bSJed Brown if (isGhost) continue;
9879566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK));
9880a96aa3bSJed Brown if (isVTK) continue;
9899566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name));
9909566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &labelNew));
9919566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defVal));
9929566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(labelNew, defVal));
9930a96aa3bSJed Brown }
9940a96aa3bSJed Brown }
9950a96aa3bSJed Brown } else { /* initial */
9960a96aa3bSJed Brown PetscInt initLevel, minLevel;
99766c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI)
99866c0a4b5SToby Isaac sc_MPI_Comm comm = sc_MPI_COMM_WORLD;
99966c0a4b5SToby Isaac #else
100066c0a4b5SToby Isaac MPI_Comm comm = PetscObjectComm((PetscObject)dm);
100166c0a4b5SToby Isaac #endif
10020a96aa3bSJed Brown
10039566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm, &initLevel));
10049566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel));
10059371c9d4SSatish Balay PetscCallP4estReturn(pforest->forest, p4est_new_ext,
10069371c9d4SSatish Balay (comm, pforest->topo->conn, 0, /* minimum number of quadrants per processor */
10070a96aa3bSJed Brown initLevel, /* level of refinement */
10080a96aa3bSJed Brown 1, /* uniform refinement */
10090a96aa3bSJed Brown 0, /* we don't allocate any per quadrant data */
10100a96aa3bSJed Brown NULL, /* there is no special quadrant initialization */
10110a96aa3bSJed Brown (void *)dm)); /* this dm is the user context */
10120a96aa3bSJed Brown
10130a96aa3bSJed Brown if (initLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE;
10140a96aa3bSJed Brown if (dm->setfromoptionscalled) {
10150a96aa3bSJed Brown PetscBool flgPattern, flgFractal;
10160a96aa3bSJed Brown PetscInt corner = 0;
10170a96aa3bSJed Brown PetscInt corners[P4EST_CHILDREN], ncorner = P4EST_CHILDREN;
10180a96aa3bSJed Brown PetscReal likelihood = 1. / P4EST_DIM;
10190a96aa3bSJed Brown PetscInt pattern;
10200a96aa3bSJed Brown const char *prefix;
10210a96aa3bSJed Brown
10229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
10239566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEList(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_pattern", DMRefinePatternName, PATTERN_COUNT, &pattern, &flgPattern));
10249566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_corner", &corner, NULL));
10259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_fractal_corners", corners, &ncorner, &flgFractal));
10269566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)dm)->options, prefix, "-dm_p4est_refine_hash_likelihood", &likelihood, NULL));
10270a96aa3bSJed Brown
10280a96aa3bSJed Brown if (flgPattern) {
10290a96aa3bSJed Brown DMRefinePatternCtx *ctx;
10300a96aa3bSJed Brown PetscInt maxLevel;
10310a96aa3bSJed Brown
10329566063dSJacob Faibussowitsch PetscCall(DMForestGetMaximumRefinement(dm, &maxLevel));
10334dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ctx));
10340a96aa3bSJed Brown ctx->maxLevel = PetscMin(maxLevel, P4EST_QMAXLEVEL);
10350a96aa3bSJed Brown if (initLevel + ctx->maxLevel > minLevel) pforest->coarsen_hierarchy = PETSC_TRUE;
10360a96aa3bSJed Brown switch (pattern) {
10370a96aa3bSJed Brown case PATTERN_HASH:
10380a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Hash;
10390a96aa3bSJed Brown ctx->hashLikelihood = likelihood;
10400a96aa3bSJed Brown break;
10410a96aa3bSJed Brown case PATTERN_CORNER:
10420a96aa3bSJed Brown ctx->corner = corner;
10430a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Corner;
10440a96aa3bSJed Brown break;
1045d71ae5a4SJacob Faibussowitsch case PATTERN_CENTER:
1046d71ae5a4SJacob Faibussowitsch ctx->refine_fn = DMRefinePattern_Center;
1047d71ae5a4SJacob Faibussowitsch break;
10480a96aa3bSJed Brown case PATTERN_FRACTAL:
10490a96aa3bSJed Brown if (flgFractal) {
10500a96aa3bSJed Brown PetscInt i;
10510a96aa3bSJed Brown
10520a96aa3bSJed Brown for (i = 0; i < ncorner; i++) ctx->fractal[corners[i]] = PETSC_TRUE;
10530a96aa3bSJed Brown } else {
10540a96aa3bSJed Brown #if !defined(P4_TO_P8)
10550a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[1] = ctx->fractal[2] = PETSC_TRUE;
10560a96aa3bSJed Brown #else
10570a96aa3bSJed Brown ctx->fractal[0] = ctx->fractal[3] = ctx->fractal[5] = ctx->fractal[6] = PETSC_TRUE;
10580a96aa3bSJed Brown #endif
10590a96aa3bSJed Brown }
10600a96aa3bSJed Brown ctx->refine_fn = DMRefinePattern_Fractal;
10610a96aa3bSJed Brown break;
1062d71ae5a4SJacob Faibussowitsch default:
1063d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Not a valid refinement pattern");
10640a96aa3bSJed Brown }
10650a96aa3bSJed Brown
10660a96aa3bSJed Brown pforest->forest->user_pointer = (void *)ctx;
1067792fecdfSBarry Smith PetscCallP4est(p4est_refine, (pforest->forest, 1, ctx->refine_fn, NULL));
1068792fecdfSBarry Smith PetscCallP4est(p4est_balance, (pforest->forest, P4EST_CONNECT_FULL, NULL));
10699566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx));
10700a96aa3bSJed Brown pforest->forest->user_pointer = (void *)dm;
10710a96aa3bSJed Brown }
10720a96aa3bSJed Brown }
10730a96aa3bSJed Brown }
10740a96aa3bSJed Brown if (pforest->coarsen_hierarchy) {
10750a96aa3bSJed Brown PetscInt initLevel, currLevel, minLevel;
10760a96aa3bSJed Brown
10779566063dSJacob Faibussowitsch PetscCall(DMPforestGetRefinementLevel(dm, &currLevel));
10789566063dSJacob Faibussowitsch PetscCall(DMForestGetInitialRefinement(dm, &initLevel));
10799566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel));
1080156acca6SStefano Zampini /* allow using PCMG and SNESFAS */
1081156acca6SStefano Zampini PetscCall(DMSetRefineLevel(dm, currLevel - minLevel));
10820a96aa3bSJed Brown if (currLevel > minLevel) {
10830a96aa3bSJed Brown DM_Forest_pforest *coarse_pforest;
10840a96aa3bSJed Brown DMLabel coarsen;
10850a96aa3bSJed Brown DM coarseDM;
10860a96aa3bSJed Brown
10879566063dSJacob Faibussowitsch PetscCall(DMForestTemplate(dm, MPI_COMM_NULL, &coarseDM));
10889566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityPurpose(coarseDM, DM_ADAPT_COARSEN));
10899566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "coarsen", &coarsen));
10909566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(coarsen, DM_ADAPT_COARSEN));
10919566063dSJacob Faibussowitsch PetscCall(DMForestSetAdaptivityLabel(coarseDM, coarsen));
10929566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&coarsen));
10939566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM));
10949566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM));
10950a96aa3bSJed Brown initLevel = currLevel == initLevel ? initLevel - 1 : initLevel;
10969566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(coarseDM, initLevel));
10979566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(coarseDM, minLevel));
10980a96aa3bSJed Brown coarse_pforest = (DM_Forest_pforest *)((DM_Forest *)coarseDM->data)->data;
10990a96aa3bSJed Brown coarse_pforest->coarsen_hierarchy = PETSC_TRUE;
11000a96aa3bSJed Brown }
11010a96aa3bSJed Brown }
11020a96aa3bSJed Brown
11030a96aa3bSJed Brown { /* repartitioning and overlap */
11040a96aa3bSJed Brown PetscMPIInt size, rank;
11050a96aa3bSJed Brown
11069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
11079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1108217f96c1SStefano Zampini if (size > 1 && (pforest->partition_for_coarsening || forest->cellWeights || forest->weightCapacity != 1. || forest->weightsFactor != 1.)) {
11090a96aa3bSJed Brown PetscBool copyForest = PETSC_FALSE;
11100a96aa3bSJed Brown p4est_t *forest_copy = NULL;
11110a96aa3bSJed Brown p4est_gloidx_t shipped = 0;
11120a96aa3bSJed Brown
11130a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) copyForest = PETSC_TRUE;
1114792fecdfSBarry Smith if (copyForest) PetscCallP4estReturn(forest_copy, p4est_copy, (pforest->forest, 0));
11150a96aa3bSJed Brown
1116966bd95aSPierre Jolivet PetscCheck(!forest->cellWeights && forest->weightCapacity == 1. && forest->weightsFactor == 1., PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Non-uniform partition cases not implemented yet");
1117792fecdfSBarry Smith PetscCallP4estReturn(shipped, p4est_partition_ext, (pforest->forest, (int)pforest->partition_for_coarsening, NULL));
11180a96aa3bSJed Brown if (shipped) ctx.anyChange = PETSC_TRUE;
11190a96aa3bSJed Brown if (forest_copy) {
11200a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) {
11210a96aa3bSJed Brown PetscSF repartSF; /* repartSF has roots in the old partition */
11220a96aa3bSJed Brown PetscInt pStart = -1, pEnd = -1, p;
11230a96aa3bSJed Brown PetscInt numRoots, numLeaves;
11240a96aa3bSJed Brown PetscSFNode *repartRoots;
11250a96aa3bSJed Brown p4est_gloidx_t postStart = pforest->forest->global_first_quadrant[rank];
11260a96aa3bSJed Brown p4est_gloidx_t postEnd = pforest->forest->global_first_quadrant[rank + 1];
11270a96aa3bSJed Brown p4est_gloidx_t partOffset = postStart;
11280a96aa3bSJed Brown
11290a96aa3bSJed Brown numRoots = (PetscInt)(forest_copy->global_first_quadrant[rank + 1] - forest_copy->global_first_quadrant[rank]);
11300a96aa3bSJed Brown numLeaves = (PetscInt)(postEnd - postStart);
11319566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(size, rank, pforest->forest, forest_copy, &pStart, &pEnd));
11329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((PetscInt)pforest->forest->local_num_quadrants, &repartRoots));
11330a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) {
11340a96aa3bSJed Brown p4est_gloidx_t preStart = forest_copy->global_first_quadrant[p];
11350a96aa3bSJed Brown p4est_gloidx_t preEnd = forest_copy->global_first_quadrant[p + 1];
11360a96aa3bSJed Brown
11370a96aa3bSJed Brown if (preEnd == preStart) continue;
113808401ef6SPierre Jolivet PetscCheck(preStart <= postStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Bad partition overlap computation");
11390a96aa3bSJed Brown preEnd = preEnd > postEnd ? postEnd : preEnd;
11406497c311SBarry Smith for (p4est_gloidx_t q = partOffset; q < preEnd; q++) {
11410a96aa3bSJed Brown repartRoots[q - postStart].rank = p;
11426497c311SBarry Smith repartRoots[q - postStart].index = (PetscInt)(partOffset - preStart);
11430a96aa3bSJed Brown }
11440a96aa3bSJed Brown partOffset = preEnd;
11450a96aa3bSJed Brown }
11469566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &repartSF));
11479566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(repartSF, numRoots, numLeaves, NULL, PETSC_OWN_POINTER, repartRoots, PETSC_OWN_POINTER));
11489566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(repartSF));
11490a96aa3bSJed Brown if (preCoarseToFine) {
11500a96aa3bSJed Brown PetscSF repartSFembed, preCoarseToFineNew;
11510a96aa3bSJed Brown PetscInt nleaves;
11520a96aa3bSJed Brown const PetscInt *leaves;
11530a96aa3bSJed Brown
11549566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine));
11559566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine, NULL, &nleaves, &leaves, NULL));
11560a96aa3bSJed Brown if (leaves) {
11579566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(repartSF, nleaves, leaves, &repartSFembed));
11580a96aa3bSJed Brown } else {
11590a96aa3bSJed Brown repartSFembed = repartSF;
11609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)repartSFembed));
11610a96aa3bSJed Brown }
11629566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(preCoarseToFine, repartSFembed, &preCoarseToFineNew));
11639566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine));
11649566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFembed));
11650a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew;
11660a96aa3bSJed Brown }
11670a96aa3bSJed Brown if (coarseToPreFine) {
11680a96aa3bSJed Brown PetscSF repartSFinv, coarseToPreFineNew;
11690a96aa3bSJed Brown
11709566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(repartSF, &repartSFinv));
11719566063dSJacob Faibussowitsch PetscCall(PetscSFCompose(repartSFinv, coarseToPreFine, &coarseToPreFineNew));
11729566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine));
11739566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSFinv));
11740a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew;
11750a96aa3bSJed Brown }
11769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&repartSF));
11770a96aa3bSJed Brown }
1178792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (forest_copy));
11790a96aa3bSJed Brown }
11800a96aa3bSJed Brown }
11810a96aa3bSJed Brown if (size > 1) {
11820a96aa3bSJed Brown PetscInt overlap;
11830a96aa3bSJed Brown
11849566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap));
11850a96aa3bSJed Brown
11860a96aa3bSJed Brown if (adaptFrom) {
11870a96aa3bSJed Brown PetscInt aoverlap;
11880a96aa3bSJed Brown
11899566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(adaptFrom, &aoverlap));
1190ad540459SPierre Jolivet if (aoverlap != overlap) ctx.anyChange = PETSC_TRUE;
11910a96aa3bSJed Brown }
11920a96aa3bSJed Brown
11930a96aa3bSJed Brown if (overlap > 0) {
11940a96aa3bSJed Brown PetscInt i, cLocalStart;
11950a96aa3bSJed Brown PetscInt cEnd;
11960a96aa3bSJed Brown PetscSF preCellSF = NULL, cellSF = NULL;
11970a96aa3bSJed Brown
1198792fecdfSBarry Smith PetscCallP4estReturn(pforest->ghost, p4est_ghost_new, (pforest->forest, P4EST_CONNECT_FULL));
1199792fecdfSBarry Smith PetscCallP4estReturn(pforest->lnodes, p4est_lnodes_new, (pforest->forest, pforest->ghost, -P4EST_DIM));
1200792fecdfSBarry Smith PetscCallP4est(p4est_ghost_support_lnodes, (pforest->forest, pforest->lnodes, pforest->ghost));
1201792fecdfSBarry Smith for (i = 1; i < overlap; i++) PetscCallP4est(p4est_ghost_expand_by_lnodes, (pforest->forest, pforest->lnodes, pforest->ghost));
12020a96aa3bSJed Brown
12030a96aa3bSJed Brown cLocalStart = pforest->cLocalStart = pforest->ghost->proc_offsets[rank];
12040a96aa3bSJed Brown cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[size];
12050a96aa3bSJed Brown
12060a96aa3bSJed Brown /* shift sfs by cLocalStart, expand by cell SFs */
12070a96aa3bSJed Brown if (preCoarseToFine || coarseToPreFine) {
12089566063dSJacob Faibussowitsch if (adaptFrom) PetscCall(DMForestGetCellSF(adaptFrom, &preCellSF));
12090a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE;
12109566063dSJacob Faibussowitsch PetscCall(DMForestGetCellSF(dm, &cellSF));
12110a96aa3bSJed Brown }
12120a96aa3bSJed Brown if (preCoarseToFine) {
12130a96aa3bSJed Brown PetscSF preCoarseToFineNew;
12140a96aa3bSJed Brown PetscInt nleaves, nroots, *leavesNew, i, nleavesNew;
12150a96aa3bSJed Brown const PetscInt *leaves;
12160a96aa3bSJed Brown const PetscSFNode *remotes;
12170a96aa3bSJed Brown PetscSFNode *remotesAll;
12180a96aa3bSJed Brown
12199566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(preCoarseToFine));
12209566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCoarseToFine, &nroots, &nleaves, &leaves, &remotes));
12219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd, &remotesAll));
12220a96aa3bSJed Brown for (i = 0; i < cEnd; i++) {
12230a96aa3bSJed Brown remotesAll[i].rank = -1;
12240a96aa3bSJed Brown remotesAll[i].index = -1;
12250a96aa3bSJed Brown }
12260a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesAll[(leaves ? leaves[i] : i) + cLocalStart] = remotes[i];
12279566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(cellSF));
12286497c311SBarry Smith PetscCall(PetscSFBcastBegin(cellSF, MPIU_SF_NODE, remotesAll, remotesAll, MPI_REPLACE));
12296497c311SBarry Smith PetscCall(PetscSFBcastEnd(cellSF, MPIU_SF_NODE, remotesAll, remotesAll, MPI_REPLACE));
12300a96aa3bSJed Brown nleavesNew = 0;
12310a96aa3bSJed Brown for (i = 0; i < nleaves; i++) {
12320a96aa3bSJed Brown if (remotesAll[i].rank >= 0) nleavesNew++;
12330a96aa3bSJed Brown }
12349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesNew, &leavesNew));
12350a96aa3bSJed Brown nleavesNew = 0;
12360a96aa3bSJed Brown for (i = 0; i < nleaves; i++) {
12370a96aa3bSJed Brown if (remotesAll[i].rank >= 0) {
12380a96aa3bSJed Brown leavesNew[nleavesNew] = i;
12390a96aa3bSJed Brown if (i > nleavesNew) remotesAll[nleavesNew] = remotesAll[i];
12400a96aa3bSJed Brown nleavesNew++;
12410a96aa3bSJed Brown }
12420a96aa3bSJed Brown }
12439566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &preCoarseToFineNew));
12440a96aa3bSJed Brown if (nleavesNew < cEnd) {
12459566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew, nroots, nleavesNew, leavesNew, PETSC_OWN_POINTER, remotesAll, PETSC_COPY_VALUES));
12460a96aa3bSJed Brown } else { /* all cells are leaves */
12479566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew));
12489566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(preCoarseToFineNew, nroots, nleavesNew, NULL, PETSC_OWN_POINTER, remotesAll, PETSC_COPY_VALUES));
12490a96aa3bSJed Brown }
12509566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesAll));
12519566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&preCoarseToFine));
12520a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew;
12530a96aa3bSJed Brown preCoarseToFine = preCoarseToFineNew;
12540a96aa3bSJed Brown }
12550a96aa3bSJed Brown if (coarseToPreFine) {
12560a96aa3bSJed Brown PetscSF coarseToPreFineNew;
12570a96aa3bSJed Brown PetscInt nleaves, nroots, i, nleavesCellSF, nleavesExpanded, *leavesNew;
12580a96aa3bSJed Brown const PetscInt *leaves;
12590a96aa3bSJed Brown const PetscSFNode *remotes;
12600a96aa3bSJed Brown PetscSFNode *remotesNew, *remotesNewRoot, *remotesExpanded;
12610a96aa3bSJed Brown
12629566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(coarseToPreFine));
12639566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToPreFine, &nroots, &nleaves, &leaves, &remotes));
12649566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(preCellSF, NULL, &nleavesCellSF, NULL, NULL));
12659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nroots, &remotesNewRoot));
12669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotesNew));
12670a96aa3bSJed Brown for (i = 0; i < nroots; i++) {
12680a96aa3bSJed Brown remotesNewRoot[i].rank = rank;
12690a96aa3bSJed Brown remotesNewRoot[i].index = i + cLocalStart;
12700a96aa3bSJed Brown }
12716497c311SBarry Smith PetscCall(PetscSFBcastBegin(coarseToPreFine, MPIU_SF_NODE, remotesNewRoot, remotesNew, MPI_REPLACE));
12726497c311SBarry Smith PetscCall(PetscSFBcastEnd(coarseToPreFine, MPIU_SF_NODE, remotesNewRoot, remotesNew, MPI_REPLACE));
12739566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNewRoot));
12749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesCellSF, &remotesExpanded));
12750a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) {
12760a96aa3bSJed Brown remotesExpanded[i].rank = -1;
12770a96aa3bSJed Brown remotesExpanded[i].index = -1;
12780a96aa3bSJed Brown }
12790a96aa3bSJed Brown for (i = 0; i < nleaves; i++) remotesExpanded[leaves ? leaves[i] : i] = remotesNew[i];
12809566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesNew));
12816497c311SBarry Smith PetscCall(PetscSFBcastBegin(preCellSF, MPIU_SF_NODE, remotesExpanded, remotesExpanded, MPI_REPLACE));
12826497c311SBarry Smith PetscCall(PetscSFBcastEnd(preCellSF, MPIU_SF_NODE, remotesExpanded, remotesExpanded, MPI_REPLACE));
12830a96aa3bSJed Brown
12840a96aa3bSJed Brown nleavesExpanded = 0;
12850a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) {
12860a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) nleavesExpanded++;
12870a96aa3bSJed Brown }
12889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesExpanded, &leavesNew));
12890a96aa3bSJed Brown nleavesExpanded = 0;
12900a96aa3bSJed Brown for (i = 0; i < nleavesCellSF; i++) {
12910a96aa3bSJed Brown if (remotesExpanded[i].rank >= 0) {
12920a96aa3bSJed Brown leavesNew[nleavesExpanded] = i;
12930a96aa3bSJed Brown if (i > nleavesExpanded) remotesExpanded[nleavesExpanded] = remotes[i];
12940a96aa3bSJed Brown nleavesExpanded++;
12950a96aa3bSJed Brown }
12960a96aa3bSJed Brown }
12979566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &coarseToPreFineNew));
12980a96aa3bSJed Brown if (nleavesExpanded < nleavesCellSF) {
12999566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew, cEnd, nleavesExpanded, leavesNew, PETSC_OWN_POINTER, remotesExpanded, PETSC_COPY_VALUES));
13000a96aa3bSJed Brown } else {
13019566063dSJacob Faibussowitsch PetscCall(PetscFree(leavesNew));
13029566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(coarseToPreFineNew, cEnd, nleavesExpanded, NULL, PETSC_OWN_POINTER, remotesExpanded, PETSC_COPY_VALUES));
13030a96aa3bSJed Brown }
13049566063dSJacob Faibussowitsch PetscCall(PetscFree(remotesExpanded));
13059566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToPreFine));
13060a96aa3bSJed Brown coarseToPreFine = coarseToPreFineNew;
13070a96aa3bSJed Brown }
13080a96aa3bSJed Brown }
13090a96aa3bSJed Brown }
13100a96aa3bSJed Brown }
13110a96aa3bSJed Brown forest->preCoarseToFine = preCoarseToFine;
13120a96aa3bSJed Brown forest->coarseToPreFine = coarseToPreFine;
13130a96aa3bSJed Brown dm->setupcalled = PETSC_TRUE;
13145440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&ctx.anyChange, &pforest->adaptivitySuccess, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
13159566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, NULL));
13163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13170a96aa3bSJed Brown }
13180a96aa3bSJed Brown
13190a96aa3bSJed Brown #define DMForestGetAdaptivitySuccess_pforest _append_pforest(DMForestGetAdaptivitySuccess)
DMForestGetAdaptivitySuccess_pforest(DM dm,PetscBool * success)1320d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestGetAdaptivitySuccess_pforest(DM dm, PetscBool *success)
1321d71ae5a4SJacob Faibussowitsch {
13220a96aa3bSJed Brown DM_Forest *forest;
13230a96aa3bSJed Brown DM_Forest_pforest *pforest;
13240a96aa3bSJed Brown
13250a96aa3bSJed Brown PetscFunctionBegin;
13260a96aa3bSJed Brown forest = (DM_Forest *)dm->data;
13270a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data;
13280a96aa3bSJed Brown *success = pforest->adaptivitySuccess;
13293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13300a96aa3bSJed Brown }
13310a96aa3bSJed Brown
13320a96aa3bSJed Brown #define DMView_ASCII_pforest _append_pforest(DMView_ASCII)
DMView_ASCII_pforest(PetscObject odm,PetscViewer viewer)1333d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_ASCII_pforest(PetscObject odm, PetscViewer viewer)
1334d71ae5a4SJacob Faibussowitsch {
13350a96aa3bSJed Brown DM dm = (DM)odm;
13360a96aa3bSJed Brown
13370a96aa3bSJed Brown PetscFunctionBegin;
13380a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
13390a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
13409566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm));
13410a96aa3bSJed Brown switch (viewer->format) {
13420a96aa3bSJed Brown case PETSC_VIEWER_DEFAULT:
13439371c9d4SSatish Balay case PETSC_VIEWER_ASCII_INFO: {
13440a96aa3bSJed Brown PetscInt dim;
13450a96aa3bSJed Brown const char *name;
13460a96aa3bSJed Brown
13479566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name));
13489566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
134963a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "Forest %s in %" PetscInt_FMT " dimensions:\n", name, dim));
135063a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Forest in %" PetscInt_FMT " dimensions:\n", dim));
1351f4d061e9SPierre Jolivet } /* fall through */
13520a96aa3bSJed Brown case PETSC_VIEWER_ASCII_INFO_DETAIL:
13539371c9d4SSatish Balay case PETSC_VIEWER_LOAD_BALANCE: {
13540a96aa3bSJed Brown DM plex;
13550a96aa3bSJed Brown
13569566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
13579566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer));
13589371c9d4SSatish Balay } break;
1359d71ae5a4SJacob Faibussowitsch default:
1360d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]);
13610a96aa3bSJed Brown }
13623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13630a96aa3bSJed Brown }
13640a96aa3bSJed Brown
13650a96aa3bSJed Brown #define DMView_VTK_pforest _append_pforest(DMView_VTK)
DMView_VTK_pforest(PetscObject odm,PetscViewer viewer)1366d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_VTK_pforest(PetscObject odm, PetscViewer viewer)
1367d71ae5a4SJacob Faibussowitsch {
13680a96aa3bSJed Brown DM dm = (DM)odm;
13690a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data;
13700a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data;
13710a96aa3bSJed Brown PetscBool isvtk;
13720a96aa3bSJed Brown PetscReal vtkScale = 1. - PETSC_MACHINE_EPSILON;
13730a96aa3bSJed Brown PetscViewer_VTK *vtk = (PetscViewer_VTK *)viewer->data;
13740a96aa3bSJed Brown const char *name;
13750a96aa3bSJed Brown char *filenameStrip = NULL;
13760a96aa3bSJed Brown PetscBool hasExt;
13770a96aa3bSJed Brown size_t len;
13780a96aa3bSJed Brown p4est_geometry_t *geom;
13790a96aa3bSJed Brown
13800a96aa3bSJed Brown PetscFunctionBegin;
13810a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
13820a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
13839566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm));
13840a96aa3bSJed Brown geom = pforest->topo->geom;
13859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
138628b400f6SJacob Faibussowitsch PetscCheck(isvtk, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name);
13870a96aa3bSJed Brown switch (viewer->format) {
13880a96aa3bSJed Brown case PETSC_VIEWER_VTK_VTU:
138928b400f6SJacob Faibussowitsch PetscCheck(pforest->forest, PetscObjectComm(odm), PETSC_ERR_ARG_WRONG, "DM has not been setup with a valid forest");
13900a96aa3bSJed Brown name = vtk->filename;
13919566063dSJacob Faibussowitsch PetscCall(PetscStrlen(name, &len));
13929566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(name + len - 4, ".vtu", &hasExt));
13930a96aa3bSJed Brown if (hasExt) {
13949566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &filenameStrip));
13950a96aa3bSJed Brown filenameStrip[len - 4] = '\0';
13960a96aa3bSJed Brown name = filenameStrip;
13970a96aa3bSJed Brown }
1398792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4estReturn(geom, p4est_geometry_new_connectivity, (pforest->topo->conn));
13990a96aa3bSJed Brown {
14000a96aa3bSJed Brown p4est_vtk_context_t *pvtk;
14010a96aa3bSJed Brown int footerr;
14020a96aa3bSJed Brown
1403792fecdfSBarry Smith PetscCallP4estReturn(pvtk, p4est_vtk_context_new, (pforest->forest, name));
1404792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_geom, (pvtk, geom));
1405792fecdfSBarry Smith PetscCallP4est(p4est_vtk_context_set_scale, (pvtk, (double)vtkScale));
1406792fecdfSBarry Smith PetscCallP4estReturn(pvtk, p4est_vtk_write_header, (pvtk));
140728b400f6SJacob Faibussowitsch PetscCheck(pvtk, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_header() failed");
14089371c9d4SSatish Balay PetscCallP4estReturn(pvtk, p4est_vtk_write_cell_dataf,
14099371c9d4SSatish Balay (pvtk, 1, /* write tree */
14100a96aa3bSJed Brown 1, /* write level */
14110a96aa3bSJed Brown 1, /* write rank */
14120a96aa3bSJed Brown 0, /* do not wrap rank */
14130a96aa3bSJed Brown 0, /* no scalar fields */
14140a96aa3bSJed Brown 0, /* no vector fields */
14150a96aa3bSJed Brown pvtk));
141628b400f6SJacob Faibussowitsch PetscCheck(pvtk, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_cell_dataf() failed");
1417792fecdfSBarry Smith PetscCallP4estReturn(footerr, p4est_vtk_write_footer, (pvtk));
141828b400f6SJacob Faibussowitsch PetscCheck(!footerr, PetscObjectComm((PetscObject)odm), PETSC_ERR_LIB, P4EST_STRING "_vtk_write_footer() failed");
14190a96aa3bSJed Brown }
1420792fecdfSBarry Smith if (!pforest->topo->geom) PetscCallP4est(p4est_geometry_destroy, (geom));
14219566063dSJacob Faibussowitsch PetscCall(PetscFree(filenameStrip));
14220a96aa3bSJed Brown break;
1423d71ae5a4SJacob Faibussowitsch default:
1424d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]);
14250a96aa3bSJed Brown }
14263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
14270a96aa3bSJed Brown }
14280a96aa3bSJed Brown
14290a96aa3bSJed Brown #define DMView_HDF5_pforest _append_pforest(DMView_HDF5)
DMView_HDF5_pforest(DM dm,PetscViewer viewer)1430d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_HDF5_pforest(DM dm, PetscViewer viewer)
1431d71ae5a4SJacob Faibussowitsch {
14320a96aa3bSJed Brown DM plex;
14330a96aa3bSJed Brown
14340a96aa3bSJed Brown PetscFunctionBegin;
14359566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm));
14369566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
14379566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer));
14383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
14390a96aa3bSJed Brown }
14400a96aa3bSJed Brown
14410a96aa3bSJed Brown #define DMView_GLVis_pforest _append_pforest(DMView_GLVis)
DMView_GLVis_pforest(DM dm,PetscViewer viewer)1442d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_GLVis_pforest(DM dm, PetscViewer viewer)
1443d71ae5a4SJacob Faibussowitsch {
14440a96aa3bSJed Brown DM plex;
14450a96aa3bSJed Brown
14460a96aa3bSJed Brown PetscFunctionBegin;
14479566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm));
14489566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
14499566063dSJacob Faibussowitsch PetscCall(DMView(plex, viewer));
14503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
14510a96aa3bSJed Brown }
14520a96aa3bSJed Brown
14530a96aa3bSJed Brown #define DMView_pforest _append_pforest(DMView)
DMView_pforest(DM dm,PetscViewer viewer)1454d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_pforest(DM dm, PetscViewer viewer)
1455d71ae5a4SJacob Faibussowitsch {
14560a96aa3bSJed Brown PetscBool isascii, isvtk, ishdf5, isglvis;
14570a96aa3bSJed Brown
14580a96aa3bSJed Brown PetscFunctionBegin;
14590a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14600a96aa3bSJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
14619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
14629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
14639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
14649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
14650a96aa3bSJed Brown if (isascii) {
14669566063dSJacob Faibussowitsch PetscCall(DMView_ASCII_pforest((PetscObject)dm, viewer));
14670a96aa3bSJed Brown } else if (isvtk) {
14689566063dSJacob Faibussowitsch PetscCall(DMView_VTK_pforest((PetscObject)dm, viewer));
14690a96aa3bSJed Brown } else if (ishdf5) {
14709566063dSJacob Faibussowitsch PetscCall(DMView_HDF5_pforest(dm, viewer));
14710a96aa3bSJed Brown } else if (isglvis) {
14729566063dSJacob Faibussowitsch PetscCall(DMView_GLVis_pforest(dm, viewer));
14730a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer not supported (not VTK, HDF5, or GLVis)");
14743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
14750a96aa3bSJed Brown }
14760a96aa3bSJed Brown
PforestConnectivityEnumerateFacets(p4est_connectivity_t * conn,PetscInt ** tree_face_to_uniq)1477d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestConnectivityEnumerateFacets(p4est_connectivity_t *conn, PetscInt **tree_face_to_uniq)
1478d71ae5a4SJacob Faibussowitsch {
14790a96aa3bSJed Brown PetscInt *ttf, f, t, g, count;
14800a96aa3bSJed Brown PetscInt numFacets;
14810a96aa3bSJed Brown
14820a96aa3bSJed Brown PetscFunctionBegin;
14830a96aa3bSJed Brown numFacets = conn->num_trees * P4EST_FACES;
14849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFacets, &ttf));
14850a96aa3bSJed Brown for (f = 0; f < numFacets; f++) ttf[f] = -1;
14860a96aa3bSJed Brown for (g = 0, count = 0, t = 0; t < conn->num_trees; t++) {
14870a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++, g++) {
14880a96aa3bSJed Brown if (ttf[g] == -1) {
14890a96aa3bSJed Brown PetscInt ng;
14900a96aa3bSJed Brown
14910a96aa3bSJed Brown ttf[g] = count++;
14920a96aa3bSJed Brown ng = conn->tree_to_tree[g] * P4EST_FACES + (conn->tree_to_face[g] % P4EST_FACES);
14930a96aa3bSJed Brown ttf[ng] = ttf[g];
14940a96aa3bSJed Brown }
14950a96aa3bSJed Brown }
14960a96aa3bSJed Brown }
14970a96aa3bSJed Brown *tree_face_to_uniq = ttf;
14983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
14990a96aa3bSJed Brown }
15000a96aa3bSJed Brown
DMPlexCreateConnectivity_pforest(DM dm,p4est_connectivity_t ** connOut,PetscInt ** tree_face_to_uniq)1501d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConnectivity_pforest(DM dm, p4est_connectivity_t **connOut, PetscInt **tree_face_to_uniq)
1502d71ae5a4SJacob Faibussowitsch {
15030a96aa3bSJed Brown p4est_topidx_t numTrees, numVerts, numCorns, numCtt;
15040a96aa3bSJed Brown PetscSection ctt;
15050a96aa3bSJed Brown #if defined(P4_TO_P8)
15060a96aa3bSJed Brown p4est_topidx_t numEdges, numEtt;
15070a96aa3bSJed Brown PetscSection ett;
15080a96aa3bSJed Brown PetscInt eStart, eEnd, e, ettSize;
15090a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES + P8EST_EDGES;
15100a96aa3bSJed Brown PetscInt edgeOff = 1 + P4EST_FACES;
15110a96aa3bSJed Brown #else
15120a96aa3bSJed Brown PetscInt vertOff = 1 + P4EST_FACES;
15130a96aa3bSJed Brown #endif
15140a96aa3bSJed Brown p4est_connectivity_t *conn;
15150a96aa3bSJed Brown PetscInt cStart, cEnd, c, vStart, vEnd, v, fStart, fEnd, f;
15160a96aa3bSJed Brown PetscInt *star = NULL, *closure = NULL, closureSize, starSize, cttSize;
15170a96aa3bSJed Brown PetscInt *ttf;
15180a96aa3bSJed Brown
15190a96aa3bSJed Brown PetscFunctionBegin;
15200a96aa3bSJed Brown /* 1: count objects, allocate */
15219566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
15229566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cEnd - cStart, &numTrees));
15230a96aa3bSJed Brown numVerts = P4EST_CHILDREN * numTrees;
15249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
15259566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(vEnd - vStart, &numCorns));
15269566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &ctt));
15279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ctt, vStart, vEnd));
15280a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) {
15290a96aa3bSJed Brown PetscInt s;
15300a96aa3bSJed Brown
15319566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star));
15320a96aa3bSJed Brown for (s = 0; s < starSize; s++) {
15330a96aa3bSJed Brown PetscInt p = star[2 * s];
15340a96aa3bSJed Brown
15350a96aa3bSJed Brown if (p >= cStart && p < cEnd) {
15360a96aa3bSJed Brown /* we want to count every time cell p references v, so we see how many times it comes up in the closure. This
15370a96aa3bSJed Brown * only protects against periodicity problems */
15389566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure));
153963a3b9bcSJacob Faibussowitsch PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell %" PetscInt_FMT " with wrong closure size %" PetscInt_FMT " != %d", p, closureSize, P4EST_INSUL);
15400a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) {
15410a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)];
15420a96aa3bSJed Brown
15431dca8a05SBarry Smith PetscCheck(cellVert >= vStart && cellVert < vEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure: vertices");
154448a46eb9SPierre Jolivet if (cellVert == v) PetscCall(PetscSectionAddDof(ctt, v, 1));
15450a96aa3bSJed Brown }
15469566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure));
15470a96aa3bSJed Brown }
15480a96aa3bSJed Brown }
15499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star));
15500a96aa3bSJed Brown }
15519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ctt));
15529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ctt, &cttSize));
15539566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(cttSize, &numCtt));
15540a96aa3bSJed Brown #if defined(P4_TO_P8)
15559566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, P4EST_DIM - 1, &eStart, &eEnd));
15569566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(eEnd - eStart, &numEdges));
15579566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &ett));
15589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(ett, eStart, eEnd));
15590a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) {
15600a96aa3bSJed Brown PetscInt s;
15610a96aa3bSJed Brown
15629566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star));
15630a96aa3bSJed Brown for (s = 0; s < starSize; s++) {
15640a96aa3bSJed Brown PetscInt p = star[2 * s];
15650a96aa3bSJed Brown
15660a96aa3bSJed Brown if (p >= cStart && p < cEnd) {
15670a96aa3bSJed Brown /* we want to count every time cell p references e, so we see how many times it comes up in the closure. This
15680a96aa3bSJed Brown * only protects against periodicity problems */
15699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure));
157008401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell with wrong closure size");
15710a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) {
15720a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)];
15730a96aa3bSJed Brown
15741dca8a05SBarry Smith PetscCheck(cellEdge >= eStart && cellEdge < eEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure: edges");
157548a46eb9SPierre Jolivet if (cellEdge == e) PetscCall(PetscSectionAddDof(ett, e, 1));
15760a96aa3bSJed Brown }
15779566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure));
15780a96aa3bSJed Brown }
15790a96aa3bSJed Brown }
15809566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star));
15810a96aa3bSJed Brown }
15829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(ett));
15839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(ett, &ettSize));
15849566063dSJacob Faibussowitsch PetscCall(P4estTopidxCast(ettSize, &numEtt));
15850a96aa3bSJed Brown
15860a96aa3bSJed Brown /* This routine allocates space for the arrays, which we fill below */
1587792fecdfSBarry Smith PetscCallP4estReturn(conn, p8est_connectivity_new, (numVerts, numTrees, numEdges, numEtt, numCorns, numCtt));
15880a96aa3bSJed Brown #else
1589792fecdfSBarry Smith PetscCallP4estReturn(conn, p4est_connectivity_new, (numVerts, numTrees, numCorns, numCtt));
15900a96aa3bSJed Brown #endif
15910a96aa3bSJed Brown
15920a96aa3bSJed Brown /* 2: visit every face, determine neighboring cells(trees) */
15939566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 1, &fStart, &fEnd));
15949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * P4EST_FACES, &ttf));
15950a96aa3bSJed Brown for (f = fStart; f < fEnd; f++) {
15960a96aa3bSJed Brown PetscInt numSupp, s;
15970a96aa3bSJed Brown PetscInt myFace[2] = {-1, -1};
15981690c2aeSBarry Smith PetscInt myOrnt[2] = {PETSC_INT_MIN, PETSC_INT_MIN};
15990a96aa3bSJed Brown const PetscInt *supp;
16000a96aa3bSJed Brown
16019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &numSupp));
16021dca8a05SBarry Smith PetscCheck(numSupp == 1 || numSupp == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "point %" PetscInt_FMT " has facet with %" PetscInt_FMT " sides: must be 1 or 2 (boundary or conformal)", f, numSupp);
16039566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, f, &supp));
16040a96aa3bSJed Brown
16050a96aa3bSJed Brown for (s = 0; s < numSupp; s++) {
16060a96aa3bSJed Brown PetscInt p = supp[s];
16070a96aa3bSJed Brown
16080a96aa3bSJed Brown if (p >= cEnd) {
16090a96aa3bSJed Brown numSupp--;
16100a96aa3bSJed Brown if (s) supp = &supp[1 - s];
16110a96aa3bSJed Brown break;
16120a96aa3bSJed Brown }
16130a96aa3bSJed Brown }
16140a96aa3bSJed Brown for (s = 0; s < numSupp; s++) {
16150a96aa3bSJed Brown PetscInt p = supp[s], i;
16160a96aa3bSJed Brown PetscInt numCone;
16170a96aa3bSJed Brown DMPolytopeType ct;
16180a96aa3bSJed Brown const PetscInt *cone;
16190a96aa3bSJed Brown const PetscInt *ornt;
16201690c2aeSBarry Smith PetscInt orient = PETSC_INT_MIN;
16210a96aa3bSJed Brown
16229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &numCone));
162363a3b9bcSJacob Faibussowitsch PetscCheck(numCone == P4EST_FACES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "cell %" PetscInt_FMT " has %" PetscInt_FMT " facets, expect %d", p, numCone, P4EST_FACES);
16249566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone));
16259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[0], &ct));
16269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
16270a96aa3bSJed Brown for (i = 0; i < P4EST_FACES; i++) {
16280a96aa3bSJed Brown if (cone[i] == f) {
16290a96aa3bSJed Brown orient = DMPolytopeConvertNewOrientation_Internal(ct, ornt[i]);
16300a96aa3bSJed Brown break;
16310a96aa3bSJed Brown }
16320a96aa3bSJed Brown }
163363a3b9bcSJacob Faibussowitsch PetscCheck(i < P4EST_FACES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "cell %" PetscInt_FMT " faced %" PetscInt_FMT " mismatch", p, f);
16340a96aa3bSJed Brown if (p < cStart || p >= cEnd) {
16350a96aa3bSJed Brown DMPolytopeType ct;
16369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct));
163763a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "cell %" PetscInt_FMT " (%s) should be in [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, DMPolytopeTypes[ct], cStart, cEnd);
16380a96aa3bSJed Brown }
16390a96aa3bSJed Brown ttf[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = f - fStart;
16400a96aa3bSJed Brown if (numSupp == 1) {
16410a96aa3bSJed Brown /* boundary faces indicated by self reference */
16420a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = p - cStart;
16430a96aa3bSJed Brown conn->tree_to_face[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = (int8_t)PetscFaceToP4estFace[i];
16440a96aa3bSJed Brown } else {
16450a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2;
16460a96aa3bSJed Brown
16470a96aa3bSJed Brown conn->tree_to_tree[P4EST_FACES * (p - cStart) + PetscFaceToP4estFace[i]] = supp[1 - s] - cStart;
16480a96aa3bSJed Brown myFace[s] = PetscFaceToP4estFace[i];
16490a96aa3bSJed Brown /* get the orientation of cell p in p4est-type closure to facet f, by composing the p4est-closure to
16500a96aa3bSJed Brown * petsc-closure permutation and the petsc-closure to facet orientation */
16510a96aa3bSJed Brown myOrnt[s] = DihedralCompose(N, orient, DMPolytopeConvertNewOrientation_Internal(ct, P4estFaceToPetscOrnt[myFace[s]]));
16520a96aa3bSJed Brown }
16530a96aa3bSJed Brown }
16540a96aa3bSJed Brown if (numSupp == 2) {
16550a96aa3bSJed Brown for (s = 0; s < numSupp; s++) {
16560a96aa3bSJed Brown PetscInt p = supp[s];
16570a96aa3bSJed Brown PetscInt orntAtoB;
16580a96aa3bSJed Brown PetscInt p4estOrient;
16590a96aa3bSJed Brown const PetscInt N = P4EST_CHILDREN / 2;
16600a96aa3bSJed Brown
16610a96aa3bSJed Brown /* composing the forward permutation with the other cell's inverse permutation gives the self-to-neighbor
16620a96aa3bSJed Brown * permutation of this cell-facet's cone */
16630a96aa3bSJed Brown orntAtoB = DihedralCompose(N, DihedralInvert(N, myOrnt[1 - s]), myOrnt[s]);
16640a96aa3bSJed Brown
16650a96aa3bSJed Brown /* convert cone-description permutation (i.e., edges around facet) to cap-description permutation (i.e.,
16660a96aa3bSJed Brown * vertices around facet) */
16670a96aa3bSJed Brown #if !defined(P4_TO_P8)
16680a96aa3bSJed Brown p4estOrient = orntAtoB < 0 ? -(orntAtoB + 1) : orntAtoB;
16690a96aa3bSJed Brown #else
16700a96aa3bSJed Brown {
16710a96aa3bSJed Brown PetscInt firstVert = orntAtoB < 0 ? ((-orntAtoB) % N) : orntAtoB;
16720a96aa3bSJed Brown PetscInt p4estFirstVert = firstVert < 2 ? firstVert : (firstVert ^ 1);
16730a96aa3bSJed Brown
16740a96aa3bSJed Brown /* swap bits */
16750a96aa3bSJed Brown p4estOrient = ((myFace[s] <= myFace[1 - s]) || (orntAtoB < 0)) ? p4estFirstVert : ((p4estFirstVert >> 1) | ((p4estFirstVert & 1) << 1));
16760a96aa3bSJed Brown }
16770a96aa3bSJed Brown #endif
16780a96aa3bSJed Brown /* encode neighbor face and orientation in tree_to_face per p4est_connectivity standard (see
16790a96aa3bSJed Brown * p4est_connectivity.h, p8est_connectivity.h) */
16806497c311SBarry Smith conn->tree_to_face[P4EST_FACES * (p - cStart) + myFace[s]] = (int8_t)(myFace[1 - s] + p4estOrient * P4EST_FACES);
16810a96aa3bSJed Brown }
16820a96aa3bSJed Brown }
16830a96aa3bSJed Brown }
16840a96aa3bSJed Brown
16850a96aa3bSJed Brown #if defined(P4_TO_P8)
16860a96aa3bSJed Brown /* 3: visit every edge */
16870a96aa3bSJed Brown conn->ett_offset[0] = 0;
16880a96aa3bSJed Brown for (e = eStart; e < eEnd; e++) {
16890a96aa3bSJed Brown PetscInt off, s;
16900a96aa3bSJed Brown
16919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ett, e, &off));
16920a96aa3bSJed Brown conn->ett_offset[e - eStart] = (p4est_topidx_t)off;
16939566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star));
16940a96aa3bSJed Brown for (s = 0; s < starSize; s++) {
16950a96aa3bSJed Brown PetscInt p = star[2 * s];
16960a96aa3bSJed Brown
16970a96aa3bSJed Brown if (p >= cStart && p < cEnd) {
16989566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure));
169908401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure");
17000a96aa3bSJed Brown for (c = 0; c < P8EST_EDGES; c++) {
17010a96aa3bSJed Brown PetscInt cellEdge = closure[2 * (c + edgeOff)];
17020a96aa3bSJed Brown PetscInt cellOrnt = closure[2 * (c + edgeOff) + 1];
17030a96aa3bSJed Brown DMPolytopeType ct;
17040a96aa3bSJed Brown
17059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cellEdge, &ct));
17060a96aa3bSJed Brown cellOrnt = DMPolytopeConvertNewOrientation_Internal(ct, cellOrnt);
17070a96aa3bSJed Brown if (cellEdge == e) {
17080a96aa3bSJed Brown PetscInt p4estEdge = PetscEdgeToP4estEdge[c];
17090a96aa3bSJed Brown PetscInt totalOrient;
17100a96aa3bSJed Brown
17110a96aa3bSJed Brown /* compose p4est-closure to petsc-closure permutation and petsc-closure to edge orientation */
17120a96aa3bSJed Brown totalOrient = DihedralCompose(2, cellOrnt, DMPolytopeConvertNewOrientation_Internal(DM_POLYTOPE_SEGMENT, P4estEdgeToPetscOrnt[p4estEdge]));
17130a96aa3bSJed Brown /* p4est orientations are positive: -2 => 1, -1 => 0 */
17140a96aa3bSJed Brown totalOrient = (totalOrient < 0) ? -(totalOrient + 1) : totalOrient;
17150a96aa3bSJed Brown conn->edge_to_tree[off] = (p4est_locidx_t)(p - cStart);
1716d5b43468SJose E. Roman /* encode cell-edge and orientation in edge_to_edge per p8est_connectivity standard (see
17170a96aa3bSJed Brown * p8est_connectivity.h) */
17186497c311SBarry Smith conn->edge_to_edge[off++] = (int8_t)(p4estEdge + P8EST_EDGES * totalOrient);
17190a96aa3bSJed Brown conn->tree_to_edge[P8EST_EDGES * (p - cStart) + p4estEdge] = e - eStart;
17200a96aa3bSJed Brown }
17210a96aa3bSJed Brown }
17229566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure));
17230a96aa3bSJed Brown }
17240a96aa3bSJed Brown }
17259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star));
17260a96aa3bSJed Brown }
17279566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ett));
17280a96aa3bSJed Brown #endif
17290a96aa3bSJed Brown
17300a96aa3bSJed Brown /* 4: visit every vertex */
17310a96aa3bSJed Brown conn->ctt_offset[0] = 0;
17320a96aa3bSJed Brown for (v = vStart; v < vEnd; v++) {
17330a96aa3bSJed Brown PetscInt off, s;
17340a96aa3bSJed Brown
17359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(ctt, v, &off));
17360a96aa3bSJed Brown conn->ctt_offset[v - vStart] = (p4est_topidx_t)off;
17379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star));
17380a96aa3bSJed Brown for (s = 0; s < starSize; s++) {
17390a96aa3bSJed Brown PetscInt p = star[2 * s];
17400a96aa3bSJed Brown
17410a96aa3bSJed Brown if (p >= cStart && p < cEnd) {
17429566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure));
174308401ef6SPierre Jolivet PetscCheck(closureSize == P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Non-standard closure");
17440a96aa3bSJed Brown for (c = 0; c < P4EST_CHILDREN; c++) {
17450a96aa3bSJed Brown PetscInt cellVert = closure[2 * (c + vertOff)];
17460a96aa3bSJed Brown
17470a96aa3bSJed Brown if (cellVert == v) {
17480a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[c];
17490a96aa3bSJed Brown
17500a96aa3bSJed Brown conn->corner_to_tree[off] = (p4est_locidx_t)(p - cStart);
17510a96aa3bSJed Brown conn->corner_to_corner[off++] = (int8_t)p4estVert;
17520a96aa3bSJed Brown conn->tree_to_corner[P4EST_CHILDREN * (p - cStart) + p4estVert] = v - vStart;
17530a96aa3bSJed Brown }
17540a96aa3bSJed Brown }
17559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, p, PETSC_TRUE, &closureSize, &closure));
17560a96aa3bSJed Brown }
17570a96aa3bSJed Brown }
17589566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star));
17590a96aa3bSJed Brown }
17609566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&ctt));
17610a96aa3bSJed Brown
17620a96aa3bSJed Brown /* 5: Compute the coordinates */
17630a96aa3bSJed Brown {
17640a96aa3bSJed Brown PetscInt coordDim;
17650a96aa3bSJed Brown
17669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim));
17676858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm));
17680a96aa3bSJed Brown for (c = cStart; c < cEnd; c++) {
17690a96aa3bSJed Brown PetscInt dof;
17706858538eSMatthew G. Knepley PetscBool isDG;
17710a96aa3bSJed Brown PetscScalar *cellCoords = NULL;
17726858538eSMatthew G. Knepley const PetscScalar *array;
17730a96aa3bSJed Brown
17746858538eSMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords));
17756858538eSMatthew G. Knepley PetscCheck(dof == P4EST_CHILDREN * coordDim, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Need coordinates at the corners: (dof) %" PetscInt_FMT " != %d * %" PetscInt_FMT " (sdim)", dof, P4EST_CHILDREN, coordDim);
17760a96aa3bSJed Brown for (v = 0; v < P4EST_CHILDREN; v++) {
17770a96aa3bSJed Brown PetscInt i, lim = PetscMin(3, coordDim);
17780a96aa3bSJed Brown PetscInt p4estVert = PetscVertToP4estVert[v];
17790a96aa3bSJed Brown
17800a96aa3bSJed Brown conn->tree_to_vertex[P4EST_CHILDREN * (c - cStart) + v] = P4EST_CHILDREN * (c - cStart) + v;
17810a96aa3bSJed Brown /* p4est vertices are always embedded in R^3 */
17820a96aa3bSJed Brown for (i = 0; i < 3; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = 0.;
17830a96aa3bSJed Brown for (i = 0; i < lim; i++) conn->vertices[3 * (P4EST_CHILDREN * (c - cStart) + p4estVert) + i] = PetscRealPart(cellCoords[v * coordDim + i]);
17840a96aa3bSJed Brown }
17856858538eSMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &dof, &array, &cellCoords));
17860a96aa3bSJed Brown }
17870a96aa3bSJed Brown }
17880a96aa3bSJed Brown
17890a96aa3bSJed Brown #if defined(P4EST_ENABLE_DEBUG)
179008401ef6SPierre Jolivet PetscCheck(p4est_connectivity_is_valid(conn), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Plex to p4est conversion failed");
17910a96aa3bSJed Brown #endif
17920a96aa3bSJed Brown
17930a96aa3bSJed Brown *connOut = conn;
17940a96aa3bSJed Brown
17950a96aa3bSJed Brown *tree_face_to_uniq = ttf;
17963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
17970a96aa3bSJed Brown }
17980a96aa3bSJed Brown
locidx_to_PetscInt(sc_array_t * array)1799d71ae5a4SJacob Faibussowitsch static PetscErrorCode locidx_to_PetscInt(sc_array_t *array)
1800d71ae5a4SJacob Faibussowitsch {
18010a96aa3bSJed Brown sc_array_t *newarray;
18020a96aa3bSJed Brown size_t zz, count = array->elem_count;
18030a96aa3bSJed Brown
18040a96aa3bSJed Brown PetscFunctionBegin;
180508401ef6SPierre Jolivet PetscCheck(array->elem_size == sizeof(p4est_locidx_t), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong locidx size");
18060a96aa3bSJed Brown
18073ba16761SJacob Faibussowitsch if (sizeof(p4est_locidx_t) == sizeof(PetscInt)) PetscFunctionReturn(PETSC_SUCCESS);
18080a96aa3bSJed Brown
18090a96aa3bSJed Brown newarray = sc_array_new_size(sizeof(PetscInt), array->elem_count);
18100a96aa3bSJed Brown for (zz = 0; zz < count; zz++) {
18110a96aa3bSJed Brown p4est_locidx_t il = *((p4est_locidx_t *)sc_array_index(array, zz));
18120a96aa3bSJed Brown PetscInt *ip = (PetscInt *)sc_array_index(newarray, zz);
18130a96aa3bSJed Brown
18140a96aa3bSJed Brown *ip = (PetscInt)il;
18150a96aa3bSJed Brown }
18160a96aa3bSJed Brown
18170a96aa3bSJed Brown sc_array_reset(array);
18180a96aa3bSJed Brown sc_array_init_size(array, sizeof(PetscInt), count);
18190a96aa3bSJed Brown sc_array_copy(array, newarray);
18200a96aa3bSJed Brown sc_array_destroy(newarray);
18213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
18220a96aa3bSJed Brown }
18230a96aa3bSJed Brown
coords_double_to_PetscScalar(sc_array_t * array,PetscInt dim)1824d71ae5a4SJacob Faibussowitsch static PetscErrorCode coords_double_to_PetscScalar(sc_array_t *array, PetscInt dim)
1825d71ae5a4SJacob Faibussowitsch {
18260a96aa3bSJed Brown sc_array_t *newarray;
18270a96aa3bSJed Brown size_t zz, count = array->elem_count;
18280a96aa3bSJed Brown
18290a96aa3bSJed Brown PetscFunctionBegin;
18301dca8a05SBarry Smith PetscCheck(array->elem_size == 3 * sizeof(double), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong coordinate size");
18310a96aa3bSJed Brown #if !defined(PETSC_USE_COMPLEX)
18323ba16761SJacob Faibussowitsch if (sizeof(double) == sizeof(PetscScalar) && dim == 3) PetscFunctionReturn(PETSC_SUCCESS);
18330a96aa3bSJed Brown #endif
18340a96aa3bSJed Brown
18350a96aa3bSJed Brown newarray = sc_array_new_size(dim * sizeof(PetscScalar), array->elem_count);
18360a96aa3bSJed Brown for (zz = 0; zz < count; zz++) {
18370a96aa3bSJed Brown int i;
18380a96aa3bSJed Brown double *id = (double *)sc_array_index(array, zz);
18390a96aa3bSJed Brown PetscScalar *ip = (PetscScalar *)sc_array_index(newarray, zz);
18400a96aa3bSJed Brown
18410a96aa3bSJed Brown for (i = 0; i < dim; i++) ip[i] = 0.;
18420a96aa3bSJed Brown for (i = 0; i < PetscMin(dim, 3); i++) ip[i] = (PetscScalar)id[i];
18430a96aa3bSJed Brown }
18440a96aa3bSJed Brown
18450a96aa3bSJed Brown sc_array_reset(array);
18460a96aa3bSJed Brown sc_array_init_size(array, dim * sizeof(PetscScalar), count);
18470a96aa3bSJed Brown sc_array_copy(array, newarray);
18480a96aa3bSJed Brown sc_array_destroy(newarray);
18493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
18500a96aa3bSJed Brown }
18510a96aa3bSJed Brown
locidx_pair_to_PetscSFNode(sc_array_t * array)1852d71ae5a4SJacob Faibussowitsch static PetscErrorCode locidx_pair_to_PetscSFNode(sc_array_t *array)
1853d71ae5a4SJacob Faibussowitsch {
18540a96aa3bSJed Brown sc_array_t *newarray;
18550a96aa3bSJed Brown size_t zz, count = array->elem_count;
18560a96aa3bSJed Brown
18570a96aa3bSJed Brown PetscFunctionBegin;
18581dca8a05SBarry Smith PetscCheck(array->elem_size == 2 * sizeof(p4est_locidx_t), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Wrong locidx size");
18590a96aa3bSJed Brown
18600a96aa3bSJed Brown newarray = sc_array_new_size(sizeof(PetscSFNode), array->elem_count);
18610a96aa3bSJed Brown for (zz = 0; zz < count; zz++) {
18620a96aa3bSJed Brown p4est_locidx_t *il = (p4est_locidx_t *)sc_array_index(array, zz);
18630a96aa3bSJed Brown PetscSFNode *ip = (PetscSFNode *)sc_array_index(newarray, zz);
18640a96aa3bSJed Brown
18650a96aa3bSJed Brown ip->rank = (PetscInt)il[0];
18660a96aa3bSJed Brown ip->index = (PetscInt)il[1];
18670a96aa3bSJed Brown }
18680a96aa3bSJed Brown
18690a96aa3bSJed Brown sc_array_reset(array);
18700a96aa3bSJed Brown sc_array_init_size(array, sizeof(PetscSFNode), count);
18710a96aa3bSJed Brown sc_array_copy(array, newarray);
18720a96aa3bSJed Brown sc_array_destroy(newarray);
18733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
18740a96aa3bSJed Brown }
18750a96aa3bSJed Brown
P4estToPlex_Local(p4est_t * p4est,DM * plex)1876d71ae5a4SJacob Faibussowitsch static PetscErrorCode P4estToPlex_Local(p4est_t *p4est, DM *plex)
1877d71ae5a4SJacob Faibussowitsch {
18780a96aa3bSJed Brown PetscFunctionBegin;
18790a96aa3bSJed Brown {
18800a96aa3bSJed Brown sc_array_t *points_per_dim = sc_array_new(sizeof(p4est_locidx_t));
18810a96aa3bSJed Brown sc_array_t *cone_sizes = sc_array_new(sizeof(p4est_locidx_t));
18820a96aa3bSJed Brown sc_array_t *cones = sc_array_new(sizeof(p4est_locidx_t));
18830a96aa3bSJed Brown sc_array_t *cone_orientations = sc_array_new(sizeof(p4est_locidx_t));
18840a96aa3bSJed Brown sc_array_t *coords = sc_array_new(3 * sizeof(double));
18850a96aa3bSJed Brown sc_array_t *children = sc_array_new(sizeof(p4est_locidx_t));
18860a96aa3bSJed Brown sc_array_t *parents = sc_array_new(sizeof(p4est_locidx_t));
18870a96aa3bSJed Brown sc_array_t *childids = sc_array_new(sizeof(p4est_locidx_t));
18880a96aa3bSJed Brown sc_array_t *leaves = sc_array_new(sizeof(p4est_locidx_t));
18890a96aa3bSJed Brown sc_array_t *remotes = sc_array_new(2 * sizeof(p4est_locidx_t));
18900a96aa3bSJed Brown p4est_locidx_t first_local_quad;
18910a96aa3bSJed Brown
1892792fecdfSBarry Smith PetscCallP4est(p4est_get_plex_data, (p4est, P4EST_CONNECT_FULL, 0, &first_local_quad, points_per_dim, cone_sizes, cones, cone_orientations, coords, children, parents, childids, leaves, remotes));
18930a96aa3bSJed Brown
18949566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim));
18959566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes));
18969566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones));
18979566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations));
18989566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, P4EST_DIM));
18990a96aa3bSJed Brown
19009566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PETSC_COMM_SELF, plex));
19019566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*plex, P4EST_DIM));
19029566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*plex, P4EST_DIM, (PetscInt *)points_per_dim->array, (PetscInt *)cone_sizes->array, (PetscInt *)cones->array, (PetscInt *)cone_orientations->array, (PetscScalar *)coords->array));
19039566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(*plex));
19040a96aa3bSJed Brown sc_array_destroy(points_per_dim);
19050a96aa3bSJed Brown sc_array_destroy(cone_sizes);
19060a96aa3bSJed Brown sc_array_destroy(cones);
19070a96aa3bSJed Brown sc_array_destroy(cone_orientations);
19080a96aa3bSJed Brown sc_array_destroy(coords);
19090a96aa3bSJed Brown sc_array_destroy(children);
19100a96aa3bSJed Brown sc_array_destroy(parents);
19110a96aa3bSJed Brown sc_array_destroy(childids);
19120a96aa3bSJed Brown sc_array_destroy(leaves);
19130a96aa3bSJed Brown sc_array_destroy(remotes);
19140a96aa3bSJed Brown }
19153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
19160a96aa3bSJed Brown }
19170a96aa3bSJed Brown
19180a96aa3bSJed Brown #define DMReferenceTreeGetChildSymmetry_pforest _append_pforest(DMReferenceTreeGetChildSymmetry)
DMReferenceTreeGetChildSymmetry_pforest(DM dm,PetscInt parent,PetscInt parentOrientA,PetscInt childOrientA,PetscInt childA,PetscInt parentOrientB,PetscInt * childOrientB,PetscInt * childB)1919d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMReferenceTreeGetChildSymmetry_pforest(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB)
1920d71ae5a4SJacob Faibussowitsch {
19210a96aa3bSJed Brown PetscInt coneSize, dStart, dEnd, vStart, vEnd, dim, ABswap, oAvert, oBvert, ABswapVert;
19220a96aa3bSJed Brown
19230a96aa3bSJed Brown PetscFunctionBegin;
19240a96aa3bSJed Brown if (parentOrientA == parentOrientB) {
19250a96aa3bSJed Brown if (childOrientB) *childOrientB = childOrientA;
19260a96aa3bSJed Brown if (childB) *childB = childA;
19273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
19280a96aa3bSJed Brown }
19299566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
19306aad120cSJose E. Roman if (childA >= vStart && childA < vEnd) { /* vertices (always in the middle) are invariant under rotation */
19310a96aa3bSJed Brown if (childOrientB) *childOrientB = 0;
19320a96aa3bSJed Brown if (childB) *childB = childA;
19333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
19340a96aa3bSJed Brown }
19350a96aa3bSJed Brown for (dim = 0; dim < 3; dim++) {
19369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, &dStart, &dEnd));
19370a96aa3bSJed Brown if (parent >= dStart && parent <= dEnd) break;
19380a96aa3bSJed Brown }
193963a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot perform child symmetry for %" PetscInt_FMT "-cells", dim);
194028b400f6SJacob Faibussowitsch PetscCheck(dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "A vertex has no children");
19410a96aa3bSJed Brown if (childA < dStart || childA >= dEnd) { /* a 1-cell in a 2-cell */
19420a96aa3bSJed Brown /* this is a lower-dimensional child: bootstrap */
19430a96aa3bSJed Brown PetscInt size, i, sA = -1, sB, sOrientB, sConeSize;
19440a96aa3bSJed Brown const PetscInt *supp, *coneA, *coneB, *oA, *oB;
19450a96aa3bSJed Brown
19469566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, childA, &size));
19479566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, childA, &supp));
19480a96aa3bSJed Brown
19490a96aa3bSJed Brown /* find a point sA in supp(childA) that has the same parent */
19500a96aa3bSJed Brown for (i = 0; i < size; i++) {
19510a96aa3bSJed Brown PetscInt sParent;
19520a96aa3bSJed Brown
19530a96aa3bSJed Brown sA = supp[i];
19540a96aa3bSJed Brown if (sA == parent) continue;
19559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, sA, &sParent, NULL));
19560a96aa3bSJed Brown if (sParent == parent) break;
19570a96aa3bSJed Brown }
195808401ef6SPierre Jolivet PetscCheck(i != size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "could not find support in children");
19590a96aa3bSJed Brown /* find out which point sB is in an equivalent position to sA under
19600a96aa3bSJed Brown * parentOrientB */
19619566063dSJacob Faibussowitsch PetscCall(DMReferenceTreeGetChildSymmetry_pforest(dm, parent, parentOrientA, 0, sA, parentOrientB, &sOrientB, &sB));
19629566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, sA, &sConeSize));
19639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sA, &coneA));
19649566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sB, &coneB));
19659566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sA, &oA));
19669566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sB, &oB));
19670a96aa3bSJed Brown /* step through the cone of sA in natural order */
19680a96aa3bSJed Brown for (i = 0; i < sConeSize; i++) {
19690a96aa3bSJed Brown if (coneA[i] == childA) {
19700a96aa3bSJed Brown /* if childA is at position i in coneA,
19710a96aa3bSJed Brown * then we want the point that is at sOrientB*i in coneB */
19720a96aa3bSJed Brown PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize - (sOrientB + 1) - i) % sConeSize);
19730a96aa3bSJed Brown if (childB) *childB = coneB[j];
19740a96aa3bSJed Brown if (childOrientB) {
19750a96aa3bSJed Brown DMPolytopeType ct;
19760a96aa3bSJed Brown PetscInt oBtrue;
19770a96aa3bSJed Brown
19789566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, childA, &coneSize));
19790a96aa3bSJed Brown /* compose sOrientB and oB[j] */
19801dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected a vertex or an edge");
19810a96aa3bSJed Brown ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT;
19820a96aa3bSJed Brown /* we may have to flip an edge */
19830a96aa3bSJed Brown oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientationInv(ct, -1, oB[j]);
19840a96aa3bSJed Brown oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue);
19850a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, DMPolytopeConvertNewOrientation_Internal(ct, oA[i]), oBtrue);
19860a96aa3bSJed Brown *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap);
19870a96aa3bSJed Brown }
19880a96aa3bSJed Brown break;
19890a96aa3bSJed Brown }
19900a96aa3bSJed Brown }
199108401ef6SPierre Jolivet PetscCheck(i != sConeSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "support cone mismatch");
19923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
19930a96aa3bSJed Brown }
19940a96aa3bSJed Brown /* get the cone size and symmetry swap */
19959566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize));
19960a96aa3bSJed Brown ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB);
19970a96aa3bSJed Brown if (dim == 2) {
19980a96aa3bSJed Brown /* orientations refer to cones: we want them to refer to vertices:
19990a96aa3bSJed Brown * if it's a rotation, they are the same, but if the order is reversed, a
20000a96aa3bSJed Brown * permutation that puts side i first does *not* put vertex i first */
20010a96aa3bSJed Brown oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1);
20020a96aa3bSJed Brown oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1);
20030a96aa3bSJed Brown ABswapVert = DihedralSwap(coneSize, oAvert, oBvert);
20040a96aa3bSJed Brown } else {
20050a96aa3bSJed Brown oAvert = parentOrientA;
20060a96aa3bSJed Brown oBvert = parentOrientB;
20070a96aa3bSJed Brown ABswapVert = ABswap;
20080a96aa3bSJed Brown }
20090a96aa3bSJed Brown if (childB) {
20100a96aa3bSJed Brown /* assume that each child corresponds to a vertex, in the same order */
20110a96aa3bSJed Brown PetscInt p, posA = -1, numChildren, i;
20120a96aa3bSJed Brown const PetscInt *children;
20130a96aa3bSJed Brown
20140a96aa3bSJed Brown /* count which position the child is in */
20159566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, parent, &numChildren, &children));
20160a96aa3bSJed Brown for (i = 0; i < numChildren; i++) {
20170a96aa3bSJed Brown p = children[i];
20180a96aa3bSJed Brown if (p == childA) {
20190a96aa3bSJed Brown if (dim == 1) {
20200a96aa3bSJed Brown posA = i;
20210a96aa3bSJed Brown } else { /* 2D Morton to rotation */
20220a96aa3bSJed Brown posA = (i & 2) ? (i ^ 1) : i;
20230a96aa3bSJed Brown }
20240a96aa3bSJed Brown break;
20250a96aa3bSJed Brown }
20260a96aa3bSJed Brown }
20270a96aa3bSJed Brown if (posA >= coneSize) {
20280a96aa3bSJed Brown SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find childA in children of parent");
20290a96aa3bSJed Brown } else {
20300a96aa3bSJed Brown /* figure out position B by applying ABswapVert */
20310a96aa3bSJed Brown PetscInt posB, childIdB;
20320a96aa3bSJed Brown
20330a96aa3bSJed Brown posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize - (ABswapVert + 1) - posA) % coneSize);
20340a96aa3bSJed Brown if (dim == 1) {
20350a96aa3bSJed Brown childIdB = posB;
20360a96aa3bSJed Brown } else { /* 2D rotation to Morton */
20370a96aa3bSJed Brown childIdB = (posB & 2) ? (posB ^ 1) : posB;
20380a96aa3bSJed Brown }
20390a96aa3bSJed Brown if (childB) *childB = children[childIdB];
20400a96aa3bSJed Brown }
20410a96aa3bSJed Brown }
20420a96aa3bSJed Brown if (childOrientB) *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap);
20433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
20440a96aa3bSJed Brown }
20450a96aa3bSJed Brown
20460a96aa3bSJed Brown #define DMCreateReferenceTree_pforest _append_pforest(DMCreateReferenceTree)
DMCreateReferenceTree_pforest(MPI_Comm comm,DM * dm)2047d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateReferenceTree_pforest(MPI_Comm comm, DM *dm)
2048d71ae5a4SJacob Faibussowitsch {
20490a96aa3bSJed Brown p4est_connectivity_t *refcube;
20500a96aa3bSJed Brown p4est_t *root, *refined;
20510a96aa3bSJed Brown DM dmRoot, dmRefined;
20520a96aa3bSJed Brown DM_Plex *mesh;
20530a96aa3bSJed Brown PetscMPIInt rank;
205466c0a4b5SToby Isaac #if defined(PETSC_HAVE_MPIUNI)
205566c0a4b5SToby Isaac sc_MPI_Comm comm_self = sc_MPI_COMM_SELF;
205666c0a4b5SToby Isaac #else
205766c0a4b5SToby Isaac MPI_Comm comm_self = PETSC_COMM_SELF;
205866c0a4b5SToby Isaac #endif
20590a96aa3bSJed Brown
20600a96aa3bSJed Brown PetscFunctionBegin;
2061792fecdfSBarry Smith PetscCallP4estReturn(refcube, p4est_connectivity_new_byname, ("unit"));
20620a96aa3bSJed Brown { /* [-1,1]^d geometry */
20630a96aa3bSJed Brown PetscInt i, j;
20640a96aa3bSJed Brown
20650a96aa3bSJed Brown for (i = 0; i < P4EST_CHILDREN; i++) {
20660a96aa3bSJed Brown for (j = 0; j < 3; j++) {
20670a96aa3bSJed Brown refcube->vertices[3 * i + j] *= 2.;
20680a96aa3bSJed Brown refcube->vertices[3 * i + j] -= 1.;
20690a96aa3bSJed Brown }
20700a96aa3bSJed Brown }
20710a96aa3bSJed Brown }
2072792fecdfSBarry Smith PetscCallP4estReturn(root, p4est_new, (comm_self, refcube, 0, NULL, NULL));
2073792fecdfSBarry Smith PetscCallP4estReturn(refined, p4est_new_ext, (comm_self, refcube, 0, 1, 1, 0, NULL, NULL));
20749566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(root, &dmRoot));
20759566063dSJacob Faibussowitsch PetscCall(P4estToPlex_Local(refined, &dmRefined));
20760a96aa3bSJed Brown {
20770a96aa3bSJed Brown #if !defined(P4_TO_P8)
20780a96aa3bSJed Brown PetscInt nPoints = 25;
20799371c9d4SSatish Balay PetscInt perm[25] = {0, 1, 2, 3, 4, 12, 8, 14, 6, 9, 15, 5, 13, 10, 7, 11, 16, 22, 20, 24, 17, 21, 18, 23, 19};
20809371c9d4SSatish Balay PetscInt ident[25] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 0, 5, 6, 7, 8, 1, 2, 3, 4, 0};
20810a96aa3bSJed Brown #else
20820a96aa3bSJed Brown PetscInt nPoints = 125;
20839371c9d4SSatish Balay PetscInt perm[125] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 32, 16, 36, 24, 40, 12, 17, 37, 25, 41, 9, 33, 20, 26, 42, 13, 21, 27, 43, 10, 34, 18, 38, 28, 14, 19, 39, 29, 11, 35, 22, 30, 15,
20849371c9d4SSatish Balay 23, 31, 44, 84, 76, 92, 52, 86, 68, 94, 60, 78, 70, 96, 45, 85, 77, 93, 54, 72, 62, 74, 46, 80, 53, 87, 69, 95, 64, 82, 47, 81, 55, 73, 66, 48, 88, 56, 90, 61, 79, 71,
20859371c9d4SSatish Balay 97, 49, 89, 58, 63, 75, 50, 57, 91, 65, 83, 51, 59, 67, 98, 106, 110, 122, 114, 120, 118, 124, 99, 111, 115, 119, 100, 107, 116, 121, 101, 117, 102, 108, 112, 123, 103, 113, 104, 109, 105};
20869371c9d4SSatish Balay PetscInt ident[125] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,
20879371c9d4SSatish Balay 16, 17, 17, 18, 18, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 19, 20, 21, 22, 23, 24, 25, 26, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1, 2, 3, 4, 5, 6, 0};
20880a96aa3bSJed Brown
20890a96aa3bSJed Brown #endif
20900a96aa3bSJed Brown IS permIS;
20910a96aa3bSJed Brown DM dmPerm;
20920a96aa3bSJed Brown
20939566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nPoints, perm, PETSC_USE_POINTER, &permIS));
20949566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dmRefined, permIS, &dmPerm));
20950a96aa3bSJed Brown if (dmPerm) {
20969566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined));
20970a96aa3bSJed Brown dmRefined = dmPerm;
20980a96aa3bSJed Brown }
20999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&permIS));
21000a96aa3bSJed Brown {
21010a96aa3bSJed Brown PetscInt p;
21029566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRoot, "identity"));
21039566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmRefined, "identity"));
210448a46eb9SPierre Jolivet for (p = 0; p < P4EST_INSUL; p++) PetscCall(DMSetLabelValue(dmRoot, "identity", p, p));
210548a46eb9SPierre Jolivet for (p = 0; p < nPoints; p++) PetscCall(DMSetLabelValue(dmRefined, "identity", p, ident[p]));
21060a96aa3bSJed Brown }
21070a96aa3bSJed Brown }
21089566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(dmRoot, dmRefined, "identity", dm));
21090a96aa3bSJed Brown mesh = (DM_Plex *)(*dm)->data;
21100a96aa3bSJed Brown mesh->getchildsymmetry = DMReferenceTreeGetChildSymmetry_pforest;
21119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
21120a96aa3bSJed Brown if (rank == 0) {
21139566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRoot, NULL, "-dm_p4est_ref_root_view"));
21149566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined, NULL, "-dm_p4est_ref_refined_view"));
21159566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmRefined, NULL, "-dm_p4est_ref_tree_view"));
21160a96aa3bSJed Brown }
21179566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRefined));
21189566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmRoot));
2119792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (refined));
2120792fecdfSBarry Smith PetscCallP4est(p4est_destroy, (root));
2121792fecdfSBarry Smith PetscCallP4est(p4est_connectivity_destroy, (refcube));
21223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
21230a96aa3bSJed Brown }
21240a96aa3bSJed Brown
DMShareDiscretization(DM dmA,DM dmB)2125d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMShareDiscretization(DM dmA, DM dmB)
2126d71ae5a4SJacob Faibussowitsch {
21270a96aa3bSJed Brown void *ctx;
21280a96aa3bSJed Brown PetscInt num;
21290a96aa3bSJed Brown PetscReal val;
21300a96aa3bSJed Brown
21310a96aa3bSJed Brown PetscFunctionBegin;
21329566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmA, &ctx));
21339566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(dmB, ctx));
21349566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmA, dmB));
21359566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dmA, &num, &val));
21369566063dSJacob Faibussowitsch PetscCall(DMSetOutputSequenceNumber(dmB, num, val));
21370a96aa3bSJed Brown if (dmB->localSection != dmA->localSection || dmB->globalSection != dmA->globalSection) {
21389566063dSJacob Faibussowitsch PetscCall(DMClearLocalVectors(dmB));
21399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->localSection));
2140f4f49eeaSPierre Jolivet PetscCall(PetscSectionDestroy(&dmB->localSection));
21410a96aa3bSJed Brown dmB->localSection = dmA->localSection;
21429566063dSJacob Faibussowitsch PetscCall(DMClearGlobalVectors(dmB));
21439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->globalSection));
2144f4f49eeaSPierre Jolivet PetscCall(PetscSectionDestroy(&dmB->globalSection));
21450a96aa3bSJed Brown dmB->globalSection = dmA->globalSection;
21469566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.section));
2147f4f49eeaSPierre Jolivet PetscCall(PetscSectionDestroy(&dmB->defaultConstraint.section));
21483b8ba7d1SJed Brown dmB->defaultConstraint.section = dmA->defaultConstraint.section;
21499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->defaultConstraint.mat));
2150f4f49eeaSPierre Jolivet PetscCall(MatDestroy(&dmB->defaultConstraint.mat));
21513b8ba7d1SJed Brown dmB->defaultConstraint.mat = dmA->defaultConstraint.mat;
21529566063dSJacob Faibussowitsch if (dmA->map) PetscCall(PetscLayoutReference(dmA->map, &dmB->map));
21530a96aa3bSJed Brown }
21540a96aa3bSJed Brown if (dmB->sectionSF != dmA->sectionSF) {
21559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dmA->sectionSF));
21569566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&dmB->sectionSF));
21570a96aa3bSJed Brown dmB->sectionSF = dmA->sectionSF;
21580a96aa3bSJed Brown }
21593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
21600a96aa3bSJed Brown }
21610a96aa3bSJed Brown
21620a96aa3bSJed Brown /* Get an SF that broadcasts a coarse-cell covering of the local fine cells */
DMPforestGetCellCoveringSF(MPI_Comm comm,p4est_t * p4estC,p4est_t * p4estF,PetscInt cStart,PetscInt cEnd,PetscSF * coveringSF)2163d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetCellCoveringSF(MPI_Comm comm, p4est_t *p4estC, p4est_t *p4estF, PetscInt cStart, PetscInt cEnd, PetscSF *coveringSF)
2164d71ae5a4SJacob Faibussowitsch {
21650a96aa3bSJed Brown PetscInt startF, endF, startC, endC, p, nLeaves;
21660a96aa3bSJed Brown PetscSFNode *leaves;
21670a96aa3bSJed Brown PetscSF sf;
21680a96aa3bSJed Brown PetscInt *recv, *send;
21690a96aa3bSJed Brown PetscMPIInt tag;
21700a96aa3bSJed Brown MPI_Request *recvReqs, *sendReqs;
21710a96aa3bSJed Brown PetscSection section;
21720a96aa3bSJed Brown
21730a96aa3bSJed Brown PetscFunctionBegin;
21749566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize, p4estC->mpirank, p4estF, p4estC, &startC, &endC));
21759566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2 * (endC - startC), &recv, endC - startC, &recvReqs));
21769566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(comm, &tag));
21770a96aa3bSJed Brown for (p = startC; p < endC; p++) {
21780a96aa3bSJed Brown recvReqs[p - startC] = MPI_REQUEST_NULL; /* just in case we don't initiate a receive */
21790a96aa3bSJed Brown if (p4estC->global_first_quadrant[p] == p4estC->global_first_quadrant[p + 1]) { /* empty coarse partition */
21800a96aa3bSJed Brown recv[2 * (p - startC)] = 0;
21810a96aa3bSJed Brown recv[2 * (p - startC) + 1] = 0;
21820a96aa3bSJed Brown continue;
21830a96aa3bSJed Brown }
21840a96aa3bSJed Brown
21856497c311SBarry Smith PetscCallMPI(MPIU_Irecv(&recv[2 * (p - startC)], 2, MPIU_INT, p, tag, comm, &recvReqs[p - startC]));
21860a96aa3bSJed Brown }
21879566063dSJacob Faibussowitsch PetscCall(DMPforestComputeOverlappingRanks(p4estC->mpisize, p4estC->mpirank, p4estC, p4estF, &startF, &endF));
21889566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(2 * (endF - startF), &send, endF - startF, &sendReqs));
21890a96aa3bSJed Brown /* count the quadrants rank will send to each of [startF,endF) */
21900a96aa3bSJed Brown for (p = startF; p < endF; p++) {
21910a96aa3bSJed Brown p4est_quadrant_t *myFineStart = &p4estF->global_first_position[p];
21920a96aa3bSJed Brown p4est_quadrant_t *myFineEnd = &p4estF->global_first_position[p + 1];
21930a96aa3bSJed Brown PetscInt tStart = (PetscInt)myFineStart->p.which_tree;
21940a96aa3bSJed Brown PetscInt tEnd = (PetscInt)myFineEnd->p.which_tree;
21950a96aa3bSJed Brown PetscInt firstCell = -1, lastCell = -1;
21960a96aa3bSJed Brown p4est_tree_t *treeStart = &(((p4est_tree_t *)p4estC->trees->array)[tStart]);
21970a96aa3bSJed Brown p4est_tree_t *treeEnd = (size_t)tEnd < p4estC->trees->elem_count ? &(((p4est_tree_t *)p4estC->trees->array)[tEnd]) : NULL;
21980a96aa3bSJed Brown ssize_t overlapIndex;
21990a96aa3bSJed Brown
22000a96aa3bSJed Brown sendReqs[p - startF] = MPI_REQUEST_NULL; /* just in case we don't initiate a send */
22010a96aa3bSJed Brown if (p4estF->global_first_quadrant[p] == p4estF->global_first_quadrant[p + 1]) continue;
22020a96aa3bSJed Brown
22030a96aa3bSJed Brown /* locate myFineStart in (or before) a cell */
22040a96aa3bSJed Brown if (treeStart->quadrants.elem_count) {
2205f4f49eeaSPierre Jolivet PetscCallP4estReturn(overlapIndex, sc_array_bsearch, (&treeStart->quadrants, myFineStart, p4est_quadrant_disjoint));
22060a96aa3bSJed Brown if (overlapIndex < 0) {
22070a96aa3bSJed Brown firstCell = 0;
22080a96aa3bSJed Brown } else {
22096497c311SBarry Smith firstCell = (PetscInt)(treeStart->quadrants_offset + overlapIndex);
22100a96aa3bSJed Brown }
22110a96aa3bSJed Brown } else {
22120a96aa3bSJed Brown firstCell = 0;
22130a96aa3bSJed Brown }
22140a96aa3bSJed Brown if (treeEnd && treeEnd->quadrants.elem_count) {
2215f4f49eeaSPierre Jolivet PetscCallP4estReturn(overlapIndex, sc_array_bsearch, (&treeEnd->quadrants, myFineEnd, p4est_quadrant_disjoint));
22160a96aa3bSJed Brown if (overlapIndex < 0) { /* all of this local section is overlapped */
22170a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants;
22180a96aa3bSJed Brown } else {
22190a96aa3bSJed Brown p4est_quadrant_t *container = &(((p4est_quadrant_t *)treeEnd->quadrants.array)[overlapIndex]);
22200a96aa3bSJed Brown p4est_quadrant_t first_desc;
22210a96aa3bSJed Brown int equal;
22220a96aa3bSJed Brown
2223792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_first_descendant, (container, &first_desc, P4EST_QMAXLEVEL));
2224792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal, (myFineEnd, &first_desc));
22250a96aa3bSJed Brown if (equal) {
22266497c311SBarry Smith lastCell = (PetscInt)(treeEnd->quadrants_offset + overlapIndex);
22270a96aa3bSJed Brown } else {
22286497c311SBarry Smith lastCell = (PetscInt)(treeEnd->quadrants_offset + overlapIndex + 1);
22290a96aa3bSJed Brown }
22300a96aa3bSJed Brown }
22310a96aa3bSJed Brown } else {
22320a96aa3bSJed Brown lastCell = p4estC->local_num_quadrants;
22330a96aa3bSJed Brown }
22340a96aa3bSJed Brown send[2 * (p - startF)] = firstCell;
22350a96aa3bSJed Brown send[2 * (p - startF) + 1] = lastCell - firstCell;
22366497c311SBarry Smith PetscCallMPI(MPIU_Isend(&send[2 * (p - startF)], 2, MPIU_INT, p, tag, comm, &sendReqs[p - startF]));
22370a96aa3bSJed Brown }
22389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endC - startC), recvReqs, MPI_STATUSES_IGNORE));
22399566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion));
22409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, startC, endC));
22410a96aa3bSJed Brown for (p = startC; p < endC; p++) {
22420a96aa3bSJed Brown PetscInt numCells = recv[2 * (p - startC) + 1];
22439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(section, p, numCells));
22440a96aa3bSJed Brown }
22459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section));
22469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &nLeaves));
22479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &leaves));
22480a96aa3bSJed Brown for (p = startC; p < endC; p++) {
22490a96aa3bSJed Brown PetscInt firstCell = recv[2 * (p - startC)];
22500a96aa3bSJed Brown PetscInt numCells = recv[2 * (p - startC) + 1];
22510a96aa3bSJed Brown PetscInt off, i;
22520a96aa3bSJed Brown
22539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off));
22540a96aa3bSJed Brown for (i = 0; i < numCells; i++) {
22550a96aa3bSJed Brown leaves[off + i].rank = p;
22560a96aa3bSJed Brown leaves[off + i].index = firstCell + i;
22570a96aa3bSJed Brown }
22580a96aa3bSJed Brown }
22599566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sf));
22609566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, cEnd - cStart, nLeaves, NULL, PETSC_OWN_POINTER, leaves, PETSC_OWN_POINTER));
22619566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion));
22629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall((PetscMPIInt)(endF - startF), sendReqs, MPI_STATUSES_IGNORE));
22639566063dSJacob Faibussowitsch PetscCall(PetscFree2(send, sendReqs));
22649566063dSJacob Faibussowitsch PetscCall(PetscFree2(recv, recvReqs));
22650a96aa3bSJed Brown *coveringSF = sf;
22663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
22670a96aa3bSJed Brown }
22680a96aa3bSJed Brown
22690a96aa3bSJed Brown /* closure points for locally-owned cells */
DMPforestGetCellSFNodes(DM dm,PetscInt numClosureIndices,PetscInt * numClosurePoints,PetscSFNode ** closurePoints,PetscBool redirect)2270d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetCellSFNodes(DM dm, PetscInt numClosureIndices, PetscInt *numClosurePoints, PetscSFNode **closurePoints, PetscBool redirect)
2271d71ae5a4SJacob Faibussowitsch {
22720a96aa3bSJed Brown PetscInt cStart, cEnd;
22730a96aa3bSJed Brown PetscInt count, c;
22740a96aa3bSJed Brown PetscMPIInt rank;
22750a96aa3bSJed Brown PetscInt closureSize = -1;
22760a96aa3bSJed Brown PetscInt *closure = NULL;
22770a96aa3bSJed Brown PetscSF pointSF;
22780a96aa3bSJed Brown PetscInt nleaves, nroots;
22790a96aa3bSJed Brown const PetscInt *ilocal;
22800a96aa3bSJed Brown const PetscSFNode *iremote;
22810a96aa3bSJed Brown DM plex;
22820a96aa3bSJed Brown DM_Forest *forest;
22830a96aa3bSJed Brown DM_Forest_pforest *pforest;
22840a96aa3bSJed Brown
22850a96aa3bSJed Brown PetscFunctionBegin;
22860a96aa3bSJed Brown forest = (DM_Forest *)dm->data;
22870a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data;
22880a96aa3bSJed Brown cStart = pforest->cLocalStart;
22890a96aa3bSJed Brown cEnd = pforest->cLocalEnd;
22909566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
22919566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &pointSF));
22929566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &ilocal, &iremote));
22930a96aa3bSJed Brown nleaves = PetscMax(0, nleaves);
22940a96aa3bSJed Brown nroots = PetscMax(0, nroots);
22950a96aa3bSJed Brown *numClosurePoints = numClosureIndices * (cEnd - cStart);
22969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numClosurePoints, closurePoints));
22979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
22980a96aa3bSJed Brown for (c = cStart, count = 0; c < cEnd; c++) {
22990a96aa3bSJed Brown PetscInt i;
23009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, c, PETSC_TRUE, &closureSize, &closure));
23010a96aa3bSJed Brown
23020a96aa3bSJed Brown for (i = 0; i < numClosureIndices; i++, count++) {
23030a96aa3bSJed Brown PetscInt p = closure[2 * i];
23040a96aa3bSJed Brown PetscInt loc = -1;
23050a96aa3bSJed Brown
23069566063dSJacob Faibussowitsch PetscCall(PetscFindInt(p, nleaves, ilocal, &loc));
23070a96aa3bSJed Brown if (redirect && loc >= 0) {
23080a96aa3bSJed Brown (*closurePoints)[count].rank = iremote[loc].rank;
23090a96aa3bSJed Brown (*closurePoints)[count].index = iremote[loc].index;
23100a96aa3bSJed Brown } else {
23110a96aa3bSJed Brown (*closurePoints)[count].rank = rank;
23120a96aa3bSJed Brown (*closurePoints)[count].index = p;
23130a96aa3bSJed Brown }
23140a96aa3bSJed Brown }
23159566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, c, PETSC_TRUE, &closureSize, &closure));
23160a96aa3bSJed Brown }
23173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
23180a96aa3bSJed Brown }
23190a96aa3bSJed Brown
DMPforestMaxSFNode(void * a,void * b,PetscMPIInt * len,MPI_Datatype * type)2320d71ae5a4SJacob Faibussowitsch static void MPIAPI DMPforestMaxSFNode(void *a, void *b, PetscMPIInt *len, MPI_Datatype *type)
2321d71ae5a4SJacob Faibussowitsch {
23220a96aa3bSJed Brown PetscMPIInt i;
23230a96aa3bSJed Brown
23240a96aa3bSJed Brown for (i = 0; i < *len; i++) {
23250a96aa3bSJed Brown PetscSFNode *A = (PetscSFNode *)a;
23260a96aa3bSJed Brown PetscSFNode *B = (PetscSFNode *)b;
23270a96aa3bSJed Brown
23280a96aa3bSJed Brown if (B->rank < 0) *B = *A;
23290a96aa3bSJed Brown }
23300a96aa3bSJed Brown }
23310a96aa3bSJed Brown
DMPforestGetTransferSF_Point(DM coarse,DM fine,PetscSF * sf,PetscBool transferIdent,PetscInt * childIds[])2332d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetTransferSF_Point(DM coarse, DM fine, PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[])
2333d71ae5a4SJacob Faibussowitsch {
23340a96aa3bSJed Brown MPI_Comm comm;
23350a96aa3bSJed Brown PetscMPIInt rank, size;
23360a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF;
23370a96aa3bSJed Brown p4est_t *p4estC, *p4estF;
23380a96aa3bSJed Brown PetscInt numClosureIndices;
23390a96aa3bSJed Brown PetscInt numClosurePointsC, numClosurePointsF;
23400a96aa3bSJed Brown PetscSFNode *closurePointsC, *closurePointsF;
23410a96aa3bSJed Brown p4est_quadrant_t *coverQuads = NULL;
23420a96aa3bSJed Brown p4est_quadrant_t **treeQuads;
23430a96aa3bSJed Brown PetscInt *treeQuadCounts;
23440a96aa3bSJed Brown MPI_Datatype nodeType;
23450a96aa3bSJed Brown MPI_Datatype nodeClosureType;
23460a96aa3bSJed Brown MPI_Op sfNodeReduce;
23470a96aa3bSJed Brown p4est_topidx_t fltF, lltF, t;
23480a96aa3bSJed Brown DM plexC, plexF;
23490a96aa3bSJed Brown PetscInt pStartF, pEndF, pStartC, pEndC;
23500a96aa3bSJed Brown PetscBool saveInCoarse = PETSC_FALSE;
23510a96aa3bSJed Brown PetscBool saveInFine = PETSC_FALSE;
23520a96aa3bSJed Brown PetscBool formCids = (childIds != NULL) ? PETSC_TRUE : PETSC_FALSE;
23530a96aa3bSJed Brown PetscInt *cids = NULL;
23540a96aa3bSJed Brown
23550a96aa3bSJed Brown PetscFunctionBegin;
23560a96aa3bSJed Brown pforestC = (DM_Forest_pforest *)((DM_Forest *)coarse->data)->data;
23570a96aa3bSJed Brown pforestF = (DM_Forest_pforest *)((DM_Forest *)fine->data)->data;
23580a96aa3bSJed Brown p4estC = pforestC->forest;
23590a96aa3bSJed Brown p4estF = pforestF->forest;
236008401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo, PetscObjectComm((PetscObject)coarse), PETSC_ERR_ARG_INCOMP, "DM's must have the same base DM");
23610a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse);
23629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
23639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
23649566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine, &plexF));
23659566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF, &pStartF, &pEndF));
23669566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse, &plexC));
23679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC, &pStartC, &pEndC));
23680a96aa3bSJed Brown { /* check if the results have been cached */
23690a96aa3bSJed Brown DM adaptCoarse, adaptFine;
23700a96aa3bSJed Brown
23719566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(coarse, &adaptCoarse));
23729566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(fine, &adaptFine));
23730a96aa3bSJed Brown if (adaptCoarse && adaptCoarse->data == fine->data) { /* coarse is adapted from fine */
23740a96aa3bSJed Brown if (pforestC->pointSelfToAdaptSF) {
2375f4f49eeaSPierre Jolivet PetscCall(PetscObjectReference((PetscObject)pforestC->pointSelfToAdaptSF));
23760a96aa3bSJed Brown *sf = pforestC->pointSelfToAdaptSF;
23770a96aa3bSJed Brown if (childIds) {
23789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids));
23799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids, pforestC->pointSelfToAdaptCids, pEndF - pStartF));
23800a96aa3bSJed Brown *childIds = cids;
23810a96aa3bSJed Brown }
23823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
23830a96aa3bSJed Brown } else {
23840a96aa3bSJed Brown saveInCoarse = PETSC_TRUE;
23850a96aa3bSJed Brown formCids = PETSC_TRUE;
23860a96aa3bSJed Brown }
23870a96aa3bSJed Brown } else if (adaptFine && adaptFine->data == coarse->data) { /* fine is adapted from coarse */
23880a96aa3bSJed Brown if (pforestF->pointAdaptToSelfSF) {
2389f4f49eeaSPierre Jolivet PetscCall(PetscObjectReference((PetscObject)pforestF->pointAdaptToSelfSF));
23900a96aa3bSJed Brown *sf = pforestF->pointAdaptToSelfSF;
23910a96aa3bSJed Brown if (childIds) {
23929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids));
23939566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(cids, pforestF->pointAdaptToSelfCids, pEndF - pStartF));
23940a96aa3bSJed Brown *childIds = cids;
23950a96aa3bSJed Brown }
23963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
23970a96aa3bSJed Brown } else {
23980a96aa3bSJed Brown saveInFine = PETSC_TRUE;
23990a96aa3bSJed Brown formCids = PETSC_TRUE;
24000a96aa3bSJed Brown }
24010a96aa3bSJed Brown }
24020a96aa3bSJed Brown }
24030a96aa3bSJed Brown
24040a96aa3bSJed Brown /* count the number of closure points that have dofs and create a list */
24050a96aa3bSJed Brown numClosureIndices = P4EST_INSUL;
24060a96aa3bSJed Brown /* create the datatype */
24079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(2, MPIU_INT, &nodeType));
24089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType));
24099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(DMPforestMaxSFNode, PETSC_FALSE, &sfNodeReduce));
24109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(numClosureIndices * 2, MPIU_INT, &nodeClosureType));
24119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeClosureType));
24120a96aa3bSJed Brown /* everything has to go through cells: for each cell, create a list of the sfnodes in its closure */
24130a96aa3bSJed Brown /* get lists of closure point SF nodes for every cell */
24149566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(coarse, numClosureIndices, &numClosurePointsC, &closurePointsC, PETSC_TRUE));
24159566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellSFNodes(fine, numClosureIndices, &numClosurePointsF, &closurePointsF, PETSC_FALSE));
24160a96aa3bSJed Brown /* create pointers for tree lists */
24170a96aa3bSJed Brown fltF = p4estF->first_local_tree;
24180a96aa3bSJed Brown lltF = p4estF->last_local_tree;
24199566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(lltF + 1 - fltF, &treeQuads, lltF + 1 - fltF, &treeQuadCounts));
24200a96aa3bSJed Brown /* if the partitions don't match, ship the coarse to cover the fine */
24210a96aa3bSJed Brown if (size > 1) {
24220a96aa3bSJed Brown PetscInt p;
24230a96aa3bSJed Brown
24240a96aa3bSJed Brown for (p = 0; p < size; p++) {
24250a96aa3bSJed Brown int equal;
24260a96aa3bSJed Brown
2427792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal_piggy, (&p4estC->global_first_position[p], &p4estF->global_first_position[p]));
24280a96aa3bSJed Brown if (!equal) break;
24290a96aa3bSJed Brown }
24300a96aa3bSJed Brown if (p < size) { /* non-matching distribution: send the coarse to cover the fine */
24310a96aa3bSJed Brown PetscInt cStartC, cEndC;
24320a96aa3bSJed Brown PetscSF coveringSF;
24330a96aa3bSJed Brown PetscInt nleaves;
24340a96aa3bSJed Brown PetscInt count;
24350a96aa3bSJed Brown PetscSFNode *newClosurePointsC;
24360a96aa3bSJed Brown p4est_quadrant_t *coverQuadsSend;
24370a96aa3bSJed Brown p4est_topidx_t fltC = p4estC->first_local_tree;
24380a96aa3bSJed Brown p4est_topidx_t lltC = p4estC->last_local_tree;
24390a96aa3bSJed Brown p4est_topidx_t t;
24400a96aa3bSJed Brown PetscMPIInt blockSizes[4] = {P4EST_DIM, 2, 1, 1};
24419371c9d4SSatish Balay MPI_Aint blockOffsets[4] = {offsetof(p4est_quadrant_t, x), offsetof(p4est_quadrant_t, level), offsetof(p4est_quadrant_t, pad16), offsetof(p4est_quadrant_t, p)};
24420a96aa3bSJed Brown MPI_Datatype blockTypes[4] = {MPI_INT32_T, MPI_INT8_T, MPI_INT16_T, MPI_INT32_T /* p.which_tree */};
24430a96aa3bSJed Brown MPI_Datatype quadStruct, quadType;
24440a96aa3bSJed Brown
24459566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC, 0, &cStartC, &cEndC));
24469566063dSJacob Faibussowitsch PetscCall(DMPforestGetCellCoveringSF(comm, p4estC, p4estF, pforestC->cLocalStart, pforestC->cLocalEnd, &coveringSF));
24479566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coveringSF, NULL, &nleaves, NULL, NULL));
24489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numClosureIndices * nleaves, &newClosurePointsC));
24499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &coverQuads));
24509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEndC - cStartC, &coverQuadsSend));
24510a96aa3bSJed Brown count = 0;
24520a96aa3bSJed Brown for (t = fltC; t <= lltC; t++) { /* unfortunately, we need to pack a send array, since quads are not stored packed in p4est */
24530a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estC->trees->array)[t]);
24540a96aa3bSJed Brown PetscInt q;
24550a96aa3bSJed Brown
24569566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&coverQuadsSend[count], tree->quadrants.array, tree->quadrants.elem_count * sizeof(p4est_quadrant_t)));
24570a96aa3bSJed Brown for (q = 0; (size_t)q < tree->quadrants.elem_count; q++) coverQuadsSend[count + q].p.which_tree = t;
24580a96aa3bSJed Brown count += tree->quadrants.elem_count;
24590a96aa3bSJed Brown }
24600a96aa3bSJed Brown /* p is of a union type p4est_quadrant_data, but only the p.which_tree field is active at this time. So, we
24610a96aa3bSJed Brown have a simple blockTypes[] to use. Note that quadStruct does not count potential padding in array of
24620a96aa3bSJed Brown p4est_quadrant_t. We have to call MPI_Type_create_resized() to change upper-bound of quadStruct.
24630a96aa3bSJed Brown */
24649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(4, blockSizes, blockOffsets, blockTypes, &quadStruct));
24659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_resized(quadStruct, 0, sizeof(p4est_quadrant_t), &quadType));
24669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&quadType));
24679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF, nodeClosureType, closurePointsC, newClosurePointsC, MPI_REPLACE));
24689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coveringSF, quadType, coverQuadsSend, coverQuads, MPI_REPLACE));
24699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF, nodeClosureType, closurePointsC, newClosurePointsC, MPI_REPLACE));
24709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coveringSF, quadType, coverQuadsSend, coverQuads, MPI_REPLACE));
24719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadStruct));
24729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&quadType));
24739566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuadsSend));
24749566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC));
24759566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coveringSF));
24760a96aa3bSJed Brown closurePointsC = newClosurePointsC;
24770a96aa3bSJed Brown
24780a96aa3bSJed Brown /* assign tree quads based on locations in coverQuads */
24790a96aa3bSJed Brown {
24800a96aa3bSJed Brown PetscInt q;
24810a96aa3bSJed Brown for (q = 0; q < nleaves; q++) {
24820a96aa3bSJed Brown p4est_locidx_t t = coverQuads[q].p.which_tree;
24830a96aa3bSJed Brown if (!treeQuadCounts[t - fltF]++) treeQuads[t - fltF] = &coverQuads[q];
24840a96aa3bSJed Brown }
24850a96aa3bSJed Brown }
24860a96aa3bSJed Brown }
24870a96aa3bSJed Brown }
24880a96aa3bSJed Brown if (!coverQuads) { /* matching partitions: assign tree quads based on locations in p4est native arrays */
24890a96aa3bSJed Brown for (t = fltF; t <= lltF; t++) {
24900a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estC->trees->array)[t]);
24910a96aa3bSJed Brown
24926497c311SBarry Smith treeQuadCounts[t - fltF] = (PetscInt)tree->quadrants.elem_count;
24930a96aa3bSJed Brown treeQuads[t - fltF] = (p4est_quadrant_t *)tree->quadrants.array;
24940a96aa3bSJed Brown }
24950a96aa3bSJed Brown }
24960a96aa3bSJed Brown
24970a96aa3bSJed Brown {
24980a96aa3bSJed Brown PetscInt p;
24990a96aa3bSJed Brown PetscInt cLocalStartF;
25000a96aa3bSJed Brown PetscSF pointSF;
25010a96aa3bSJed Brown PetscSFNode *roots;
25020a96aa3bSJed Brown PetscInt *rootType;
25030a96aa3bSJed Brown DM refTree = NULL;
25040a96aa3bSJed Brown DMLabel canonical;
25050a96aa3bSJed Brown PetscInt *childClosures[P4EST_CHILDREN] = {NULL};
25060a96aa3bSJed Brown PetscInt *rootClosure = NULL;
25070a96aa3bSJed Brown PetscInt coarseOffset;
25080a96aa3bSJed Brown PetscInt numCoarseQuads;
25090a96aa3bSJed Brown
25109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &roots));
25119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &rootType));
25129566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(fine, &pointSF));
25130a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) {
25140a96aa3bSJed Brown roots[p - pStartF].rank = -1;
25150a96aa3bSJed Brown roots[p - pStartF].index = -1;
25160a96aa3bSJed Brown rootType[p - pStartF] = -1;
25170a96aa3bSJed Brown }
25180a96aa3bSJed Brown if (formCids) {
25190a96aa3bSJed Brown PetscInt child;
25200a96aa3bSJed Brown
25219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &cids));
25220a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) cids[p - pStartF] = -2;
25239566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF, &refTree));
25249566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, 0, PETSC_TRUE, NULL, &rootClosure));
25250a96aa3bSJed Brown for (child = 0; child < P4EST_CHILDREN; child++) { /* get the closures of the child cells in the reference tree */
25269566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child + 1, PETSC_TRUE, NULL, &childClosures[child]));
25270a96aa3bSJed Brown }
25289566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical));
25290a96aa3bSJed Brown }
25300a96aa3bSJed Brown cLocalStartF = pforestF->cLocalStart;
25310a96aa3bSJed Brown for (t = fltF, coarseOffset = 0, numCoarseQuads = 0; t <= lltF; t++, coarseOffset += numCoarseQuads) {
25320a96aa3bSJed Brown p4est_tree_t *tree = &(((p4est_tree_t *)p4estF->trees->array)[t]);
25336497c311SBarry Smith PetscInt numFineQuads = (PetscInt)tree->quadrants.elem_count;
25340a96aa3bSJed Brown p4est_quadrant_t *coarseQuads = treeQuads[t - fltF];
25350a96aa3bSJed Brown p4est_quadrant_t *fineQuads = (p4est_quadrant_t *)tree->quadrants.array;
25360a96aa3bSJed Brown PetscInt i, coarseCount = 0;
25370a96aa3bSJed Brown PetscInt offset = tree->quadrants_offset;
25380a96aa3bSJed Brown sc_array_t coarseQuadsArray;
25390a96aa3bSJed Brown
25400a96aa3bSJed Brown numCoarseQuads = treeQuadCounts[t - fltF];
2541792fecdfSBarry Smith PetscCallP4est(sc_array_init_data, (&coarseQuadsArray, coarseQuads, sizeof(p4est_quadrant_t), (size_t)numCoarseQuads));
25420a96aa3bSJed Brown for (i = 0; i < numFineQuads; i++) {
25430a96aa3bSJed Brown PetscInt c = i + offset;
25440a96aa3bSJed Brown p4est_quadrant_t *quad = &fineQuads[i];
25450a96aa3bSJed Brown p4est_quadrant_t *quadCoarse = NULL;
25460a96aa3bSJed Brown ssize_t disjoint = -1;
25470a96aa3bSJed Brown
25480a96aa3bSJed Brown while (disjoint < 0 && coarseCount < numCoarseQuads) {
25490a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount];
2550792fecdfSBarry Smith PetscCallP4estReturn(disjoint, p4est_quadrant_disjoint, (quadCoarse, quad));
25510a96aa3bSJed Brown if (disjoint < 0) coarseCount++;
25520a96aa3bSJed Brown }
255308401ef6SPierre Jolivet PetscCheck(disjoint == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "did not find overlapping coarse quad");
25540a96aa3bSJed Brown if (quadCoarse->level > quad->level || (quadCoarse->level == quad->level && !transferIdent)) { /* the "coarse" mesh is finer than the fine mesh at the point: continue */
25550a96aa3bSJed Brown if (transferIdent) { /* find corners */
25560a96aa3bSJed Brown PetscInt j = 0;
25570a96aa3bSJed Brown
25580a96aa3bSJed Brown do {
25590a96aa3bSJed Brown if (j < P4EST_CHILDREN) {
25600a96aa3bSJed Brown p4est_quadrant_t cornerQuad;
25610a96aa3bSJed Brown int equal;
25620a96aa3bSJed Brown
2563792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_descendant, (quad, &cornerQuad, j, quadCoarse->level));
2564792fecdfSBarry Smith PetscCallP4estReturn(equal, p4est_quadrant_is_equal, (&cornerQuad, quadCoarse));
25650a96aa3bSJed Brown if (equal) {
25660a96aa3bSJed Brown PetscInt petscJ = P4estVertToPetscVert[j];
25670a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + (P4EST_INSUL - P4EST_CHILDREN) + petscJ].index;
25680a96aa3bSJed Brown PetscSFNode q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + (P4EST_INSUL - P4EST_CHILDREN) + petscJ];
25690a96aa3bSJed Brown
25700a96aa3bSJed Brown roots[p - pStartF] = q;
25711690c2aeSBarry Smith rootType[p - pStartF] = PETSC_INT_MAX;
25720a96aa3bSJed Brown cids[p - pStartF] = -1;
25730a96aa3bSJed Brown j++;
25740a96aa3bSJed Brown }
25750a96aa3bSJed Brown }
25760a96aa3bSJed Brown coarseCount++;
25770a96aa3bSJed Brown disjoint = 1;
25780a96aa3bSJed Brown if (coarseCount < numCoarseQuads) {
25790a96aa3bSJed Brown quadCoarse = &coarseQuads[coarseCount];
2580792fecdfSBarry Smith PetscCallP4estReturn(disjoint, p4est_quadrant_disjoint, (quadCoarse, quad));
25810a96aa3bSJed Brown }
25820a96aa3bSJed Brown } while (!disjoint);
25830a96aa3bSJed Brown }
25840a96aa3bSJed Brown continue;
25850a96aa3bSJed Brown }
25860a96aa3bSJed Brown if (quadCoarse->level == quad->level) { /* same quad present in coarse and fine mesh */
25870a96aa3bSJed Brown PetscInt j;
25880a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) {
25890a96aa3bSJed Brown PetscInt p = closurePointsF[numClosureIndices * c + j].index;
25900a96aa3bSJed Brown
25910a96aa3bSJed Brown roots[p - pStartF] = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + j];
25921690c2aeSBarry Smith rootType[p - pStartF] = PETSC_INT_MAX; /* unconditionally accept */
25930a96aa3bSJed Brown cids[p - pStartF] = -1;
25940a96aa3bSJed Brown }
25950a96aa3bSJed Brown } else {
25960a96aa3bSJed Brown PetscInt levelDiff = quad->level - quadCoarse->level;
25970a96aa3bSJed Brown PetscInt proposedCids[P4EST_INSUL] = {0};
25980a96aa3bSJed Brown
25990a96aa3bSJed Brown if (formCids) {
26000a96aa3bSJed Brown PetscInt cl;
26010a96aa3bSJed Brown PetscInt *pointClosure = NULL;
26020a96aa3bSJed Brown int cid;
26030a96aa3bSJed Brown
260408401ef6SPierre Jolivet PetscCheck(levelDiff <= 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Recursive child ids not implemented");
2605792fecdfSBarry Smith PetscCallP4estReturn(cid, p4est_quadrant_child_id, (quad));
26069566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plexF, c + cLocalStartF, PETSC_TRUE, NULL, &pointClosure));
26070a96aa3bSJed Brown for (cl = 0; cl < P4EST_INSUL; cl++) {
26080a96aa3bSJed Brown PetscInt p = pointClosure[2 * cl];
26090a96aa3bSJed Brown PetscInt point = childClosures[cid][2 * cl];
26100a96aa3bSJed Brown PetscInt ornt = childClosures[cid][2 * cl + 1];
26110a96aa3bSJed Brown PetscInt newcid = -1;
26120a96aa3bSJed Brown DMPolytopeType ct;
26130a96aa3bSJed Brown
26141690c2aeSBarry Smith if (rootType[p - pStartF] == PETSC_INT_MAX) continue;
26159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, point, &ct));
26160a96aa3bSJed Brown ornt = DMPolytopeConvertNewOrientation_Internal(ct, ornt);
26170a96aa3bSJed Brown if (!cl) {
26180a96aa3bSJed Brown newcid = cid + 1;
26190a96aa3bSJed Brown } else {
26200a96aa3bSJed Brown PetscInt rcl, parent, parentOrnt = 0;
26210a96aa3bSJed Brown
26229566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, point, &parent, NULL));
26230a96aa3bSJed Brown if (parent == point) {
26240a96aa3bSJed Brown newcid = -1;
26250a96aa3bSJed Brown } else if (!parent) { /* in the root */
26260a96aa3bSJed Brown newcid = point;
26270a96aa3bSJed Brown } else {
26280a96aa3bSJed Brown DMPolytopeType rct = DM_POLYTOPE_UNKNOWN;
26290a96aa3bSJed Brown
26300a96aa3bSJed Brown for (rcl = 1; rcl < P4EST_INSUL; rcl++) {
26310a96aa3bSJed Brown if (rootClosure[2 * rcl] == parent) {
26329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(refTree, parent, &rct));
26330a96aa3bSJed Brown parentOrnt = DMPolytopeConvertNewOrientation_Internal(rct, rootClosure[2 * rcl + 1]);
26340a96aa3bSJed Brown break;
26350a96aa3bSJed Brown }
26360a96aa3bSJed Brown }
263708401ef6SPierre Jolivet PetscCheck(rcl < P4EST_INSUL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Couldn't find parent in root closure");
26389566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(refTree, parent, parentOrnt, ornt, point, DMPolytopeConvertNewOrientation_Internal(rct, pointClosure[2 * rcl + 1]), NULL, &newcid));
26390a96aa3bSJed Brown }
26400a96aa3bSJed Brown }
26410a96aa3bSJed Brown if (newcid >= 0) {
264248a46eb9SPierre Jolivet if (canonical) PetscCall(DMLabelGetValue(canonical, newcid, &newcid));
26430a96aa3bSJed Brown proposedCids[cl] = newcid;
26440a96aa3bSJed Brown }
26450a96aa3bSJed Brown }
26469566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plexF, c + cLocalStartF, PETSC_TRUE, NULL, &pointClosure));
26470a96aa3bSJed Brown }
26489371c9d4SSatish Balay p4est_qcoord_t coarseBound[2][P4EST_DIM] = {
26499371c9d4SSatish Balay {quadCoarse->x, quadCoarse->y,
26500a96aa3bSJed Brown #if defined(P4_TO_P8)
26510a96aa3bSJed Brown quadCoarse->z
26520a96aa3bSJed Brown #endif
26539371c9d4SSatish Balay },
26549371c9d4SSatish Balay {0}
26559371c9d4SSatish Balay };
26569371c9d4SSatish Balay p4est_qcoord_t fineBound[2][P4EST_DIM] = {
26579371c9d4SSatish Balay {quad->x, quad->y,
26580a96aa3bSJed Brown #if defined(P4_TO_P8)
26590a96aa3bSJed Brown quad->z
26600a96aa3bSJed Brown #endif
26619371c9d4SSatish Balay },
26629371c9d4SSatish Balay {0}
26639371c9d4SSatish Balay };
26640a96aa3bSJed Brown PetscInt j;
26650a96aa3bSJed Brown for (j = 0; j < P4EST_DIM; j++) { /* get the coordinates of cell boundaries in each direction */
26660a96aa3bSJed Brown coarseBound[1][j] = coarseBound[0][j] + P4EST_QUADRANT_LEN(quadCoarse->level);
26670a96aa3bSJed Brown fineBound[1][j] = fineBound[0][j] + P4EST_QUADRANT_LEN(quad->level);
26680a96aa3bSJed Brown }
26690a96aa3bSJed Brown for (j = 0; j < numClosureIndices; j++) {
26700a96aa3bSJed Brown PetscInt l, p;
26710a96aa3bSJed Brown PetscSFNode q;
26720a96aa3bSJed Brown
26730a96aa3bSJed Brown p = closurePointsF[numClosureIndices * c + j].index;
26741690c2aeSBarry Smith if (rootType[p - pStartF] == PETSC_INT_MAX) continue;
26750a96aa3bSJed Brown if (j == 0) { /* volume: ancestor is volume */
26760a96aa3bSJed Brown l = 0;
26770a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES) { /* facet */
26780a96aa3bSJed Brown PetscInt face = PetscFaceToP4estFace[j - 1];
26790a96aa3bSJed Brown PetscInt direction = face / 2;
26800a96aa3bSJed Brown PetscInt coarseFace = -1;
26810a96aa3bSJed Brown
26820a96aa3bSJed Brown if (coarseBound[face % 2][direction] == fineBound[face % 2][direction]) {
26830a96aa3bSJed Brown coarseFace = face;
26840a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace];
26850a96aa3bSJed Brown } else {
26860a96aa3bSJed Brown l = 0;
26870a96aa3bSJed Brown }
26880a96aa3bSJed Brown #if defined(P4_TO_P8)
26890a96aa3bSJed Brown } else if (j < 1 + P4EST_FACES + P8EST_EDGES) {
26900a96aa3bSJed Brown PetscInt edge = PetscEdgeToP4estEdge[j - (1 + P4EST_FACES)];
26910a96aa3bSJed Brown PetscInt direction = edge / 4;
26920a96aa3bSJed Brown PetscInt mod = edge % 4;
26930a96aa3bSJed Brown PetscInt coarseEdge = -1, coarseFace = -1;
26940a96aa3bSJed Brown PetscInt minDir = PetscMin((direction + 1) % 3, (direction + 2) % 3);
26950a96aa3bSJed Brown PetscInt maxDir = PetscMax((direction + 1) % 3, (direction + 2) % 3);
26960a96aa3bSJed Brown PetscBool dirTest[2];
26970a96aa3bSJed Brown
26980a96aa3bSJed Brown dirTest[0] = (PetscBool)(coarseBound[mod % 2][minDir] == fineBound[mod % 2][minDir]);
26990a96aa3bSJed Brown dirTest[1] = (PetscBool)(coarseBound[mod / 2][maxDir] == fineBound[mod / 2][maxDir]);
27000a96aa3bSJed Brown
27010a96aa3bSJed Brown if (dirTest[0] && dirTest[1]) { /* fine edge falls on coarse edge */
27020a96aa3bSJed Brown coarseEdge = edge;
27030a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge];
27040a96aa3bSJed Brown } else if (dirTest[0]) { /* fine edge falls on a coarse face in the minDir direction */
27050a96aa3bSJed Brown coarseFace = 2 * minDir + (mod % 2);
27060a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace];
27070a96aa3bSJed Brown } else if (dirTest[1]) { /* fine edge falls on a coarse face in the maxDir direction */
27080a96aa3bSJed Brown coarseFace = 2 * maxDir + (mod / 2);
27090a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace];
27100a96aa3bSJed Brown } else {
27110a96aa3bSJed Brown l = 0;
27120a96aa3bSJed Brown }
27130a96aa3bSJed Brown #endif
27140a96aa3bSJed Brown } else {
27150a96aa3bSJed Brown PetscInt vertex = PetscVertToP4estVert[P4EST_CHILDREN - (P4EST_INSUL - j)];
27160a96aa3bSJed Brown PetscBool dirTest[P4EST_DIM];
27170a96aa3bSJed Brown PetscInt m;
27180a96aa3bSJed Brown PetscInt numMatch = 0;
27190a96aa3bSJed Brown PetscInt coarseVertex = -1, coarseFace = -1;
27200a96aa3bSJed Brown #if defined(P4_TO_P8)
27210a96aa3bSJed Brown PetscInt coarseEdge = -1;
27220a96aa3bSJed Brown #endif
27230a96aa3bSJed Brown
27240a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) {
27250a96aa3bSJed Brown dirTest[m] = (PetscBool)(coarseBound[(vertex >> m) & 1][m] == fineBound[(vertex >> m) & 1][m]);
27260a96aa3bSJed Brown if (dirTest[m]) numMatch++;
27270a96aa3bSJed Brown }
27280a96aa3bSJed Brown if (numMatch == P4EST_DIM) { /* vertex on vertex */
27290a96aa3bSJed Brown coarseVertex = vertex;
27300a96aa3bSJed Brown l = P4EST_INSUL - (P4EST_CHILDREN - P4estVertToPetscVert[coarseVertex]);
27310a96aa3bSJed Brown } else if (numMatch == 1) { /* vertex on face */
27320a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) {
27330a96aa3bSJed Brown if (dirTest[m]) {
27340a96aa3bSJed Brown coarseFace = 2 * m + ((vertex >> m) & 1);
27350a96aa3bSJed Brown break;
27360a96aa3bSJed Brown }
27370a96aa3bSJed Brown }
27380a96aa3bSJed Brown l = 1 + P4estFaceToPetscFace[coarseFace];
27390a96aa3bSJed Brown #if defined(P4_TO_P8)
27400a96aa3bSJed Brown } else if (numMatch == 2) { /* vertex on edge */
27410a96aa3bSJed Brown for (m = 0; m < P4EST_DIM; m++) {
27420a96aa3bSJed Brown if (!dirTest[m]) {
27430a96aa3bSJed Brown PetscInt otherDir1 = (m + 1) % 3;
27440a96aa3bSJed Brown PetscInt otherDir2 = (m + 2) % 3;
27450a96aa3bSJed Brown PetscInt minDir = PetscMin(otherDir1, otherDir2);
27460a96aa3bSJed Brown PetscInt maxDir = PetscMax(otherDir1, otherDir2);
27470a96aa3bSJed Brown
27480a96aa3bSJed Brown coarseEdge = m * 4 + 2 * ((vertex >> maxDir) & 1) + ((vertex >> minDir) & 1);
27490a96aa3bSJed Brown break;
27500a96aa3bSJed Brown }
27510a96aa3bSJed Brown }
27520a96aa3bSJed Brown l = 1 + P4EST_FACES + P4estEdgeToPetscEdge[coarseEdge];
27530a96aa3bSJed Brown #endif
27540a96aa3bSJed Brown } else { /* volume */
27550a96aa3bSJed Brown l = 0;
27560a96aa3bSJed Brown }
27570a96aa3bSJed Brown }
27580a96aa3bSJed Brown q = closurePointsC[numClosureIndices * (coarseCount + coarseOffset) + l];
27590a96aa3bSJed Brown if (l > rootType[p - pStartF]) {
27600a96aa3bSJed Brown if (l >= P4EST_INSUL - P4EST_CHILDREN) { /* vertex on vertex: unconditional acceptance */
27610a96aa3bSJed Brown if (transferIdent) {
27620a96aa3bSJed Brown roots[p - pStartF] = q;
27631690c2aeSBarry Smith rootType[p - pStartF] = PETSC_INT_MAX;
27640a96aa3bSJed Brown if (formCids) cids[p - pStartF] = -1;
27650a96aa3bSJed Brown }
27660a96aa3bSJed Brown } else {
27670a96aa3bSJed Brown PetscInt k, thisp = p, limit;
27680a96aa3bSJed Brown
27690a96aa3bSJed Brown roots[p - pStartF] = q;
27700a96aa3bSJed Brown rootType[p - pStartF] = l;
27710a96aa3bSJed Brown if (formCids) cids[p - pStartF] = proposedCids[j];
27720a96aa3bSJed Brown limit = transferIdent ? levelDiff : (levelDiff - 1);
27730a96aa3bSJed Brown for (k = 0; k < limit; k++) {
27740a96aa3bSJed Brown PetscInt parent;
27750a96aa3bSJed Brown
27769566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plexF, thisp, &parent, NULL));
27770a96aa3bSJed Brown if (parent == thisp) break;
27780a96aa3bSJed Brown
27790a96aa3bSJed Brown roots[parent - pStartF] = q;
27801690c2aeSBarry Smith rootType[parent - pStartF] = PETSC_INT_MAX;
27810a96aa3bSJed Brown if (formCids) cids[parent - pStartF] = -1;
27820a96aa3bSJed Brown thisp = parent;
27830a96aa3bSJed Brown }
27840a96aa3bSJed Brown }
27850a96aa3bSJed Brown }
27860a96aa3bSJed Brown }
27870a96aa3bSJed Brown }
27880a96aa3bSJed Brown }
27890a96aa3bSJed Brown }
27900a96aa3bSJed Brown
27910a96aa3bSJed 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 */
27920a96aa3bSJed Brown if (size > 1) {
27930a96aa3bSJed Brown PetscInt *rootTypeCopy, p;
27940a96aa3bSJed Brown
27959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &rootTypeCopy));
27969566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(rootTypeCopy, rootType, pEndF - pStartF));
279757168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_MAX));
279857168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_MAX));
27999566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_REPLACE));
28009566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, rootTypeCopy, rootTypeCopy, MPI_REPLACE));
28010a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) {
28020a96aa3bSJed 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 */
28030a96aa3bSJed Brown roots[p - pStartF].rank = -1;
28040a96aa3bSJed Brown roots[p - pStartF].index = -1;
28050a96aa3bSJed Brown }
2806ac530a7eSPierre Jolivet if (formCids && rootTypeCopy[p - pStartF] == PETSC_INT_MAX) cids[p - pStartF] = -1; /* we have found an antecedent that is the same: no child id */
28070a96aa3bSJed Brown }
28089566063dSJacob Faibussowitsch PetscCall(PetscFree(rootTypeCopy));
28099566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pointSF, nodeType, roots, roots, sfNodeReduce));
28109566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pointSF, nodeType, roots, roots, sfNodeReduce));
28119566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, nodeType, roots, roots, MPI_REPLACE));
28129566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, nodeType, roots, roots, MPI_REPLACE));
28130a96aa3bSJed Brown }
28149566063dSJacob Faibussowitsch PetscCall(PetscFree(rootType));
28150a96aa3bSJed Brown
28160a96aa3bSJed Brown {
28170a96aa3bSJed Brown PetscInt numRoots;
28180a96aa3bSJed Brown PetscInt numLeaves;
28190a96aa3bSJed Brown PetscInt *leaves;
28200a96aa3bSJed Brown PetscSFNode *iremote;
28210a96aa3bSJed Brown /* count leaves */
28220a96aa3bSJed Brown
28230a96aa3bSJed Brown numRoots = pEndC - pStartC;
28240a96aa3bSJed Brown
28250a96aa3bSJed Brown numLeaves = 0;
28260a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) {
28270a96aa3bSJed Brown if (roots[p - pStartF].index >= 0) numLeaves++;
28280a96aa3bSJed Brown }
28299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &leaves));
28309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &iremote));
28310a96aa3bSJed Brown numLeaves = 0;
28320a96aa3bSJed Brown for (p = pStartF; p < pEndF; p++) {
28330a96aa3bSJed Brown if (roots[p - pStartF].index >= 0) {
28340a96aa3bSJed Brown leaves[numLeaves] = p - pStartF;
28350a96aa3bSJed Brown iremote[numLeaves] = roots[p - pStartF];
28360a96aa3bSJed Brown numLeaves++;
28370a96aa3bSJed Brown }
28380a96aa3bSJed Brown }
28399566063dSJacob Faibussowitsch PetscCall(PetscFree(roots));
28409566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sf));
28410a96aa3bSJed Brown if (numLeaves == (pEndF - pStartF)) {
28429566063dSJacob Faibussowitsch PetscCall(PetscFree(leaves));
28439566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, numRoots, numLeaves, NULL, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
28440a96aa3bSJed Brown } else {
28459566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, numRoots, numLeaves, leaves, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
28460a96aa3bSJed Brown }
28470a96aa3bSJed Brown }
28480a96aa3bSJed Brown if (formCids) {
28490a96aa3bSJed Brown PetscSF pointSF;
28500a96aa3bSJed Brown PetscInt child;
28510a96aa3bSJed Brown
28529566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(plexF, &refTree));
28539566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plexF, &pointSF));
285457168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, cids, cids, MPI_MAX));
285557168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, cids, cids, MPI_MAX));
28560a96aa3bSJed Brown if (childIds) *childIds = cids;
285748a46eb9SPierre Jolivet for (child = 0; child < P4EST_CHILDREN; child++) PetscCall(DMPlexRestoreTransitiveClosure(refTree, child + 1, PETSC_TRUE, NULL, &childClosures[child]));
28589566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, 0, PETSC_TRUE, NULL, &rootClosure));
28590a96aa3bSJed Brown }
28600a96aa3bSJed Brown }
28610a96aa3bSJed Brown if (saveInCoarse) { /* cache results */
28629566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf));
28630a96aa3bSJed Brown pforestC->pointSelfToAdaptSF = *sf;
28640a96aa3bSJed Brown if (!childIds) {
28650a96aa3bSJed Brown pforestC->pointSelfToAdaptCids = cids;
28660a96aa3bSJed Brown } else {
28679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &pforestC->pointSelfToAdaptCids));
28689566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestC->pointSelfToAdaptCids, cids, pEndF - pStartF));
28690a96aa3bSJed Brown }
28700a96aa3bSJed Brown } else if (saveInFine) {
28719566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*sf));
28720a96aa3bSJed Brown pforestF->pointAdaptToSelfSF = *sf;
28730a96aa3bSJed Brown if (!childIds) {
28740a96aa3bSJed Brown pforestF->pointAdaptToSelfCids = cids;
28750a96aa3bSJed Brown } else {
28769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &pforestF->pointAdaptToSelfCids));
28779566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pforestF->pointAdaptToSelfCids, cids, pEndF - pStartF));
28780a96aa3bSJed Brown }
28790a96aa3bSJed Brown }
28809566063dSJacob Faibussowitsch PetscCall(PetscFree2(treeQuads, treeQuadCounts));
28819566063dSJacob Faibussowitsch PetscCall(PetscFree(coverQuads));
28829566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsC));
28839566063dSJacob Faibussowitsch PetscCall(PetscFree(closurePointsF));
28849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeClosureType));
28859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&sfNodeReduce));
28869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType));
28873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
28880a96aa3bSJed Brown }
28890a96aa3bSJed Brown
28900a96aa3bSJed Brown /* children are sf leaves of parents */
DMPforestGetTransferSF_Internal(DM coarse,DM fine,const PetscInt dofPerDim[],PetscSF * sf,PetscBool transferIdent,PetscInt * childIds[])2891d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetTransferSF_Internal(DM coarse, DM fine, const PetscInt dofPerDim[], PetscSF *sf, PetscBool transferIdent, PetscInt *childIds[])
2892d71ae5a4SJacob Faibussowitsch {
28930a96aa3bSJed Brown MPI_Comm comm;
2894d70f29a3SPierre Jolivet PetscMPIInt rank;
28950a96aa3bSJed Brown DM_Forest_pforest *pforestC, *pforestF;
28960a96aa3bSJed Brown DM plexC, plexF;
28970a96aa3bSJed Brown PetscInt pStartC, pEndC, pStartF, pEndF;
28980a96aa3bSJed Brown PetscSF pointTransferSF;
28990a96aa3bSJed Brown PetscBool allOnes = PETSC_TRUE;
29000a96aa3bSJed Brown
29010a96aa3bSJed Brown PetscFunctionBegin;
29020a96aa3bSJed Brown pforestC = (DM_Forest_pforest *)((DM_Forest *)coarse->data)->data;
29030a96aa3bSJed Brown pforestF = (DM_Forest_pforest *)((DM_Forest *)fine->data)->data;
290408401ef6SPierre Jolivet PetscCheck(pforestC->topo == pforestF->topo, PetscObjectComm((PetscObject)coarse), PETSC_ERR_ARG_INCOMP, "DM's must have the same base DM");
29050a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)coarse);
29069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
29070a96aa3bSJed Brown
29080a96aa3bSJed Brown {
29090a96aa3bSJed Brown PetscInt i;
29100a96aa3bSJed Brown for (i = 0; i <= P4EST_DIM; i++) {
29110a96aa3bSJed Brown if (dofPerDim[i] != 1) {
29120a96aa3bSJed Brown allOnes = PETSC_FALSE;
29130a96aa3bSJed Brown break;
29140a96aa3bSJed Brown }
29150a96aa3bSJed Brown }
29160a96aa3bSJed Brown }
29179566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Point(coarse, fine, &pointTransferSF, transferIdent, childIds));
29180a96aa3bSJed Brown if (allOnes) {
29190a96aa3bSJed Brown *sf = pointTransferSF;
29203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
29210a96aa3bSJed Brown }
29220a96aa3bSJed Brown
29239566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(fine, &plexF));
29249566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexF, &pStartF, &pEndF));
29259566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(coarse, &plexC));
29269566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexC, &pStartC, &pEndC));
29270a96aa3bSJed Brown {
29280a96aa3bSJed Brown PetscInt numRoots;
29290a96aa3bSJed Brown PetscInt numLeaves;
29300a96aa3bSJed Brown const PetscInt *leaves;
29310a96aa3bSJed Brown const PetscSFNode *iremote;
29320a96aa3bSJed Brown PetscInt d;
29330a96aa3bSJed Brown PetscSection leafSection, rootSection;
29340a96aa3bSJed Brown
2935217f96c1SStefano Zampini /* count leaves */
29369566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointTransferSF, &numRoots, &numLeaves, &leaves, &iremote));
29379566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &rootSection));
29389566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &leafSection));
29399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootSection, pStartC, pEndC));
29409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafSection, pStartF, pEndF));
29410a96aa3bSJed Brown
29420a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) {
29430a96aa3bSJed Brown PetscInt startC, endC, e;
29440a96aa3bSJed Brown
29459566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexC, P4EST_DIM - d, &startC, &endC));
294648a46eb9SPierre Jolivet for (e = startC; e < endC; e++) PetscCall(PetscSectionSetDof(rootSection, e, dofPerDim[d]));
29470a96aa3bSJed Brown }
29480a96aa3bSJed Brown
29490a96aa3bSJed Brown for (d = 0; d <= P4EST_DIM; d++) {
29500a96aa3bSJed Brown PetscInt startF, endF, e;
29510a96aa3bSJed Brown
29529566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plexF, P4EST_DIM - d, &startF, &endF));
295348a46eb9SPierre Jolivet for (e = startF; e < endF; e++) PetscCall(PetscSectionSetDof(leafSection, e, dofPerDim[d]));
29540a96aa3bSJed Brown }
29550a96aa3bSJed Brown
29569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootSection));
29579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafSection));
29580a96aa3bSJed Brown {
29590a96aa3bSJed Brown PetscInt nroots, nleaves;
29600a96aa3bSJed Brown PetscInt *mine, i, p;
29610a96aa3bSJed Brown PetscInt *offsets, *offsetsRoot;
29620a96aa3bSJed Brown PetscSFNode *remote;
29630a96aa3bSJed Brown
29649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndF - pStartF, &offsets));
29659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &offsetsRoot));
296648a46eb9SPierre Jolivet for (p = pStartC; p < pEndC; p++) PetscCall(PetscSectionGetOffset(rootSection, p, &offsetsRoot[p - pStartC]));
29679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointTransferSF, MPIU_INT, offsetsRoot, offsets, MPI_REPLACE));
29689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointTransferSF, MPIU_INT, offsetsRoot, offsets, MPI_REPLACE));
29699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootSection, &nroots));
29700a96aa3bSJed Brown nleaves = 0;
29710a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) {
29720a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i;
29730a96aa3bSJed Brown PetscInt dof;
29740a96aa3bSJed Brown
29759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, leaf, &dof));
29760a96aa3bSJed Brown nleaves += dof;
29770a96aa3bSJed Brown }
29789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &mine));
29799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remote));
29800a96aa3bSJed Brown nleaves = 0;
29810a96aa3bSJed Brown for (i = 0; i < numLeaves; i++) {
29820a96aa3bSJed Brown PetscInt leaf = leaves ? leaves[i] : i;
29830a96aa3bSJed Brown PetscInt dof;
29840a96aa3bSJed Brown PetscInt off, j;
29850a96aa3bSJed Brown
29869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafSection, leaf, &dof));
29879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafSection, leaf, &off));
29880a96aa3bSJed Brown for (j = 0; j < dof; j++) {
29890a96aa3bSJed Brown remote[nleaves].rank = iremote[i].rank;
29900a96aa3bSJed Brown remote[nleaves].index = offsets[leaf] + j;
29910a96aa3bSJed Brown mine[nleaves++] = off + j;
29920a96aa3bSJed Brown }
29930a96aa3bSJed Brown }
29949566063dSJacob Faibussowitsch PetscCall(PetscFree(offsetsRoot));
29959566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets));
29969566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, sf));
29979566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(*sf, nroots, nleaves, mine, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER));
29980a96aa3bSJed Brown }
29999566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafSection));
30009566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootSection));
30019566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointTransferSF));
30020a96aa3bSJed Brown }
30033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
30040a96aa3bSJed Brown }
30050a96aa3bSJed Brown
DMPforestGetTransferSF(DM dmA,DM dmB,const PetscInt dofPerDim[],PetscSF * sfAtoB,PetscSF * sfBtoA)3006d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetTransferSF(DM dmA, DM dmB, const PetscInt dofPerDim[], PetscSF *sfAtoB, PetscSF *sfBtoA)
3007d71ae5a4SJacob Faibussowitsch {
30080a96aa3bSJed Brown DM adaptA, adaptB;
30090a96aa3bSJed Brown DMAdaptFlag purpose;
30100a96aa3bSJed Brown
30110a96aa3bSJed Brown PetscFunctionBegin;
30129566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmA, &adaptA));
30139566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmB, &adaptB));
30140a96aa3bSJed Brown /* it is more efficient when the coarser mesh is the first argument: reorder if we know one is coarser than the other */
30150a96aa3bSJed Brown if (adaptA && adaptA->data == dmB->data) { /* dmA was adapted from dmB */
30169566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmA, &purpose));
30170a96aa3bSJed Brown if (purpose == DM_ADAPT_REFINE) {
30189566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB));
30193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
30200a96aa3bSJed Brown }
30210a96aa3bSJed Brown } else if (adaptB && adaptB->data == dmA->data) { /* dmB was adapted from dmA */
30229566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmB, &purpose));
30230a96aa3bSJed Brown if (purpose == DM_ADAPT_COARSEN) {
30249566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(dmB, dmA, dofPerDim, sfBtoA, sfAtoB));
30253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
30260a96aa3bSJed Brown }
30270a96aa3bSJed Brown }
30281baa6e33SBarry Smith if (sfAtoB) PetscCall(DMPforestGetTransferSF_Internal(dmA, dmB, dofPerDim, sfAtoB, PETSC_TRUE, NULL));
30291baa6e33SBarry Smith if (sfBtoA) PetscCall(DMPforestGetTransferSF_Internal(dmB, dmA, dofPerDim, sfBtoA, (PetscBool)(sfAtoB == NULL), NULL));
30303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
30310a96aa3bSJed Brown }
30320a96aa3bSJed Brown
DMPforestLabelsInitialize(DM dm,DM plex)3033d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestLabelsInitialize(DM dm, DM plex)
3034d71ae5a4SJacob Faibussowitsch {
30350a96aa3bSJed Brown DM_Forest *forest = (DM_Forest *)dm->data;
30360a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)forest->data;
30370a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, cStart, cEnd, fStart, fEnd, eStart, eEnd, vStart, vEnd;
30380a96aa3bSJed Brown PetscInt cStartBase, cEndBase, fStartBase, fEndBase, vStartBase, vEndBase, eStartBase, eEndBase;
30390a96aa3bSJed Brown PetscInt pStart, pEnd, pStartBase, pEndBase, p;
30400a96aa3bSJed Brown DM base;
30410a96aa3bSJed Brown PetscInt *star = NULL, starSize;
30420a96aa3bSJed Brown DMLabelLink next = dm->labels;
30430a96aa3bSJed Brown PetscInt guess = 0;
30440a96aa3bSJed Brown p4est_topidx_t num_trees = pforest->topo->conn->num_trees;
30450a96aa3bSJed Brown
30460a96aa3bSJed Brown PetscFunctionBegin;
30470a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE;
30480a96aa3bSJed Brown cLocalStart = pforest->cLocalStart;
30490a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd;
30509566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base));
30510a96aa3bSJed Brown if (!base) {
30520a96aa3bSJed Brown if (pforest->ghostName) { /* insert a label to make the boundaries, with stratum values denoting which face of the element touches the boundary */
30530a96aa3bSJed Brown p4est_connectivity_t *conn = pforest->topo->conn;
30540a96aa3bSJed Brown p4est_t *p4est = pforest->forest;
30550a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t *)p4est->trees->array;
30560a96aa3bSJed Brown p4est_topidx_t t, flt = p4est->first_local_tree;
30570a96aa3bSJed Brown p4est_topidx_t llt = pforest->forest->last_local_tree;
30580a96aa3bSJed Brown DMLabel ghostLabel;
30590a96aa3bSJed Brown PetscInt c;
30600a96aa3bSJed Brown
30619566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(plex, pforest->ghostName));
30629566063dSJacob Faibussowitsch PetscCall(DMGetLabel(plex, pforest->ghostName, &ghostLabel));
30630a96aa3bSJed Brown for (c = cLocalStart, t = flt; t <= llt; t++) {
30640a96aa3bSJed Brown p4est_tree_t *tree = &trees[t];
30650a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array;
30660a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count;
30670a96aa3bSJed Brown PetscInt q;
30680a96aa3bSJed Brown
30690a96aa3bSJed Brown for (q = 0; q < numQuads; q++, c++) {
30700a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[q];
30710a96aa3bSJed Brown PetscInt f;
30720a96aa3bSJed Brown
30730a96aa3bSJed Brown for (f = 0; f < P4EST_FACES; f++) {
30740a96aa3bSJed Brown p4est_quadrant_t neigh;
30750a96aa3bSJed Brown int isOutside;
30760a96aa3bSJed Brown
3077792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor, (quad, f, &neigh));
3078792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p4est_quadrant_is_outside_face, (&neigh));
30790a96aa3bSJed Brown if (isOutside) {
30800a96aa3bSJed Brown p4est_topidx_t nt;
30810a96aa3bSJed Brown PetscInt nf;
30820a96aa3bSJed Brown
30830a96aa3bSJed Brown nt = conn->tree_to_tree[t * P4EST_FACES + f];
30840a96aa3bSJed Brown nf = (PetscInt)conn->tree_to_face[t * P4EST_FACES + f];
30850a96aa3bSJed Brown nf = nf % P4EST_FACES;
30860a96aa3bSJed Brown if (nt == t && nf == f) {
30870a96aa3bSJed Brown PetscInt plexF = P4estFaceToPetscFace[f];
30880a96aa3bSJed Brown const PetscInt *cone;
30890a96aa3bSJed Brown
30909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(plex, c, &cone));
30919566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ghostLabel, cone[plexF], plexF + 1));
30920a96aa3bSJed Brown }
30930a96aa3bSJed Brown }
30940a96aa3bSJed Brown }
30950a96aa3bSJed Brown }
30960a96aa3bSJed Brown }
30970a96aa3bSJed Brown }
30983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
30990a96aa3bSJed Brown }
31009566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, 0, &cStartBase, &cEndBase));
31019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, 1, &fStartBase, &fEndBase));
31029566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(base, P4EST_DIM - 1, &eStartBase, &eEndBase));
31039566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(base, 0, &vStartBase, &vEndBase));
31040a96aa3bSJed Brown
31059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, 0, &cStart, &cEnd));
31069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, 1, &fStart, &fEnd));
31079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(plex, P4EST_DIM - 1, &eStart, &eEnd));
31089566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd));
31090a96aa3bSJed Brown
31109566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &pStart, &pEnd));
31119566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(base, &pStartBase, &pEndBase));
31120a96aa3bSJed Brown /* go through the mesh: use star to find a quadrant that borders a point. Use the closure to determine the
31130a96aa3bSJed Brown * orientation of the quadrant relative to that point. Use that to relate the point to the numbering in the base
31140a96aa3bSJed Brown * mesh, and extract a label value (since the base mesh is redundantly distributed, can be found locally). */
31150a96aa3bSJed Brown while (next) {
31160a96aa3bSJed Brown DMLabel baseLabel;
31170a96aa3bSJed Brown DMLabel label = next->label;
31180a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK, isSpmap;
31190a96aa3bSJed Brown const char *name;
31200a96aa3bSJed Brown
31219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)label, &name));
31229566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth));
31230a96aa3bSJed Brown if (isDepth) {
31240a96aa3bSJed Brown next = next->next;
31250a96aa3bSJed Brown continue;
31260a96aa3bSJed Brown }
31279566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType));
31280a96aa3bSJed Brown if (isCellType) {
31290a96aa3bSJed Brown next = next->next;
31300a96aa3bSJed Brown continue;
31310a96aa3bSJed Brown }
31329566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost));
31330a96aa3bSJed Brown if (isGhost) {
31340a96aa3bSJed Brown next = next->next;
31350a96aa3bSJed Brown continue;
31360a96aa3bSJed Brown }
31379566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK));
31380a96aa3bSJed Brown if (isVTK) {
31390a96aa3bSJed Brown next = next->next;
31400a96aa3bSJed Brown continue;
31410a96aa3bSJed Brown }
31429566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "_forest_base_subpoint_map", &isSpmap));
31430a96aa3bSJed Brown if (!isSpmap) {
31449566063dSJacob Faibussowitsch PetscCall(DMGetLabel(base, name, &baseLabel));
31450a96aa3bSJed Brown if (!baseLabel) {
31460a96aa3bSJed Brown next = next->next;
31470a96aa3bSJed Brown continue;
31480a96aa3bSJed Brown }
31499566063dSJacob Faibussowitsch PetscCall(DMLabelCreateIndex(baseLabel, pStartBase, pEndBase));
31500a96aa3bSJed Brown } else baseLabel = NULL;
31510a96aa3bSJed Brown
31520a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) {
31530a96aa3bSJed Brown PetscInt s, c = -1, l;
31540a96aa3bSJed Brown PetscInt *closure = NULL, closureSize;
31550a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array;
31560a96aa3bSJed Brown p4est_tree_t *trees = (p4est_tree_t *)pforest->forest->trees->array;
31570a96aa3bSJed Brown p4est_quadrant_t *q;
31580a96aa3bSJed Brown PetscInt t, val;
31590a96aa3bSJed Brown PetscBool zerosupportpoint = PETSC_FALSE;
31600a96aa3bSJed Brown
31619566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star));
31620a96aa3bSJed Brown for (s = 0; s < starSize; s++) {
31630a96aa3bSJed Brown PetscInt point = star[2 * s];
31640a96aa3bSJed Brown
31650a96aa3bSJed Brown if (cStart <= point && point < cEnd) {
31669566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, point, PETSC_TRUE, &closureSize, &closure));
31670a96aa3bSJed Brown for (l = 0; l < closureSize; l++) {
31680a96aa3bSJed Brown PetscInt qParent = closure[2 * l], q, pp = p, pParent = p;
31690a96aa3bSJed Brown do { /* check parents of q */
31700a96aa3bSJed Brown q = qParent;
31710a96aa3bSJed Brown if (q == p) {
31720a96aa3bSJed Brown c = point;
31730a96aa3bSJed Brown break;
31740a96aa3bSJed Brown }
31759566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &qParent, NULL));
31760a96aa3bSJed Brown } while (qParent != q);
31770a96aa3bSJed Brown if (c != -1) break;
31789566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, pp, &pParent, NULL));
31790a96aa3bSJed Brown q = closure[2 * l];
31800a96aa3bSJed Brown while (pParent != pp) { /* check parents of p */
31810a96aa3bSJed Brown pp = pParent;
31820a96aa3bSJed Brown if (pp == q) {
31830a96aa3bSJed Brown c = point;
31840a96aa3bSJed Brown break;
31850a96aa3bSJed Brown }
31869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, pp, &pParent, NULL));
31870a96aa3bSJed Brown }
31880a96aa3bSJed Brown if (c != -1) break;
31890a96aa3bSJed Brown }
31909566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, point, PETSC_TRUE, NULL, &closure));
31910a96aa3bSJed Brown if (l < closureSize) break;
31920a96aa3bSJed Brown } else {
31930a96aa3bSJed Brown PetscInt supportSize;
31940a96aa3bSJed Brown
31959566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(plex, point, &supportSize));
31960a96aa3bSJed Brown zerosupportpoint = (PetscBool)(zerosupportpoint || !supportSize);
31970a96aa3bSJed Brown }
31980a96aa3bSJed Brown }
31990a96aa3bSJed Brown if (c < 0) {
32000a96aa3bSJed Brown const char *prefix;
32010a96aa3bSJed Brown PetscBool print = PETSC_FALSE;
32020a96aa3bSJed Brown
32039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
32049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, prefix, "-dm_forest_print_label_error", &print, NULL));
32050a96aa3bSJed Brown if (print) {
32060a96aa3bSJed Brown PetscInt i;
32070a96aa3bSJed Brown
320863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Failed to find cell with point %" PetscInt_FMT " in its closure for label %s (starSize %" PetscInt_FMT ")\n", PetscGlobalRank, p, baseLabel ? ((PetscObject)baseLabel)->name : "_forest_base_subpoint_map", starSize));
320963a3b9bcSJacob Faibussowitsch for (i = 0; i < starSize; i++) PetscCall(PetscPrintf(PETSC_COMM_SELF, " star[%" PetscInt_FMT "] = %" PetscInt_FMT ",%" PetscInt_FMT "\n", i, star[2 * i], star[2 * i + 1]));
32100a96aa3bSJed Brown }
32119566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, NULL, &star));
32120a96aa3bSJed Brown if (zerosupportpoint) continue;
32139371c9d4SSatish Balay else
32149371c9d4SSatish Balay SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed to find cell with point %" PetscInt_FMT " in its closure for label %s. Rerun with -dm_forest_print_label_error for more information", p, baseLabel ? ((PetscObject)baseLabel)->name : "_forest_base_subpoint_map");
32150a96aa3bSJed Brown }
32169566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, NULL, &star));
32170a96aa3bSJed Brown
32180a96aa3bSJed Brown if (c < cLocalStart) {
32190a96aa3bSJed Brown /* get from the beginning of the ghost layer */
3220f4f49eeaSPierre Jolivet q = &ghosts[c];
32210a96aa3bSJed Brown t = (PetscInt)q->p.which_tree;
32220a96aa3bSJed Brown } else if (c < cLocalEnd) {
32230a96aa3bSJed Brown PetscInt lo = 0, hi = num_trees;
32240a96aa3bSJed Brown /* get from local quadrants: have to find the right tree */
32250a96aa3bSJed Brown
32260a96aa3bSJed Brown c -= cLocalStart;
32270a96aa3bSJed Brown
32280a96aa3bSJed Brown do {
32290a96aa3bSJed Brown p4est_tree_t *tree;
32300a96aa3bSJed Brown
32311dca8a05SBarry Smith PetscCheck(guess >= lo && guess < num_trees && lo < hi, PETSC_COMM_SELF, PETSC_ERR_PLIB, "failed binary search");
32320a96aa3bSJed Brown tree = &trees[guess];
32330a96aa3bSJed Brown if (c < tree->quadrants_offset) {
32340a96aa3bSJed Brown hi = guess;
32350a96aa3bSJed Brown } else if (c < tree->quadrants_offset + (PetscInt)tree->quadrants.elem_count) {
32360a96aa3bSJed Brown q = &((p4est_quadrant_t *)tree->quadrants.array)[c - (PetscInt)tree->quadrants_offset];
32370a96aa3bSJed Brown t = guess;
32380a96aa3bSJed Brown break;
32390a96aa3bSJed Brown } else {
32400a96aa3bSJed Brown lo = guess + 1;
32410a96aa3bSJed Brown }
32420a96aa3bSJed Brown guess = lo + (hi - lo) / 2;
32430a96aa3bSJed Brown } while (1);
32440a96aa3bSJed Brown } else {
32450a96aa3bSJed Brown /* get from the end of the ghost layer */
32460a96aa3bSJed Brown c -= (cLocalEnd - cLocalStart);
32470a96aa3bSJed Brown
3248f4f49eeaSPierre Jolivet q = &ghosts[c];
32490a96aa3bSJed Brown t = (PetscInt)q->p.which_tree;
32500a96aa3bSJed Brown }
32510a96aa3bSJed Brown
32520a96aa3bSJed Brown if (l == 0) { /* cell */
32530a96aa3bSJed Brown if (baseLabel) {
32549566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val));
32550a96aa3bSJed Brown } else {
32560a96aa3bSJed Brown val = t + cStartBase;
32570a96aa3bSJed Brown }
32589566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
32590a96aa3bSJed Brown } else if (l >= 1 && l < 1 + P4EST_FACES) { /* facet */
32600a96aa3bSJed Brown p4est_quadrant_t nq;
32610a96aa3bSJed Brown int isInside;
32620a96aa3bSJed Brown
32630a96aa3bSJed Brown l = PetscFaceToP4estFace[l - 1];
3264792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_face_neighbor, (q, l, &nq));
3265792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq));
32660a96aa3bSJed Brown if (isInside) {
32670a96aa3bSJed Brown /* this facet is in the interior of a tree, so it inherits the label of the tree */
32680a96aa3bSJed Brown if (baseLabel) {
32699566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val));
32700a96aa3bSJed Brown } else {
32710a96aa3bSJed Brown val = t + cStartBase;
32720a96aa3bSJed Brown }
32739566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
32740a96aa3bSJed Brown } else {
32750a96aa3bSJed Brown PetscInt f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + l];
32760a96aa3bSJed Brown
32770a96aa3bSJed Brown if (baseLabel) {
32789566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val));
32790a96aa3bSJed Brown } else {
32800a96aa3bSJed Brown val = f + fStartBase;
32810a96aa3bSJed Brown }
32829566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
32830a96aa3bSJed Brown }
32840a96aa3bSJed Brown #if defined(P4_TO_P8)
32850a96aa3bSJed Brown } else if (l >= 1 + P4EST_FACES && l < 1 + P4EST_FACES + P8EST_EDGES) { /* edge */
32860a96aa3bSJed Brown p4est_quadrant_t nq;
32870a96aa3bSJed Brown int isInside;
32880a96aa3bSJed Brown
32890a96aa3bSJed Brown l = PetscEdgeToP4estEdge[l - (1 + P4EST_FACES)];
3290792fecdfSBarry Smith PetscCallP4est(p8est_quadrant_edge_neighbor, (q, l, &nq));
3291792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq));
32920a96aa3bSJed Brown if (isInside) {
32930a96aa3bSJed Brown /* this edge is in the interior of a tree, so it inherits the label of the tree */
32940a96aa3bSJed Brown if (baseLabel) {
32959566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val));
32960a96aa3bSJed Brown } else {
32970a96aa3bSJed Brown val = t + cStartBase;
32980a96aa3bSJed Brown }
32999566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
33000a96aa3bSJed Brown } else {
33010a96aa3bSJed Brown int isOutsideFace;
33020a96aa3bSJed Brown
3303792fecdfSBarry Smith PetscCallP4estReturn(isOutsideFace, p4est_quadrant_is_outside_face, (&nq));
33040a96aa3bSJed Brown if (isOutsideFace) {
33050a96aa3bSJed Brown PetscInt f;
33060a96aa3bSJed Brown
33070a96aa3bSJed Brown if (nq.x < 0) {
33080a96aa3bSJed Brown f = 0;
33090a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) {
33100a96aa3bSJed Brown f = 1;
33110a96aa3bSJed Brown } else if (nq.y < 0) {
33120a96aa3bSJed Brown f = 2;
33130a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) {
33140a96aa3bSJed Brown f = 3;
33150a96aa3bSJed Brown } else if (nq.z < 0) {
33160a96aa3bSJed Brown f = 4;
33170a96aa3bSJed Brown } else {
33180a96aa3bSJed Brown f = 5;
33190a96aa3bSJed Brown }
33200a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f];
33210a96aa3bSJed Brown if (baseLabel) {
33229566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val));
33230a96aa3bSJed Brown } else {
33240a96aa3bSJed Brown val = f + fStartBase;
33250a96aa3bSJed Brown }
33269566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
33270a96aa3bSJed Brown } else { /* the quadrant edge corresponds to the tree edge */
33280a96aa3bSJed Brown PetscInt e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + l];
33290a96aa3bSJed Brown
33300a96aa3bSJed Brown if (baseLabel) {
33319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, e + eStartBase, &val));
33320a96aa3bSJed Brown } else {
33330a96aa3bSJed Brown val = e + eStartBase;
33340a96aa3bSJed Brown }
33359566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
33360a96aa3bSJed Brown }
33370a96aa3bSJed Brown }
33380a96aa3bSJed Brown #endif
33390a96aa3bSJed Brown } else { /* vertex */
33400a96aa3bSJed Brown p4est_quadrant_t nq;
33410a96aa3bSJed Brown int isInside;
33420a96aa3bSJed Brown
33430a96aa3bSJed Brown #if defined(P4_TO_P8)
33440a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES + P8EST_EDGES)];
33450a96aa3bSJed Brown #else
33460a96aa3bSJed Brown l = PetscVertToP4estVert[l - (1 + P4EST_FACES)];
33470a96aa3bSJed Brown #endif
3348792fecdfSBarry Smith PetscCallP4est(p4est_quadrant_corner_neighbor, (q, l, &nq));
3349792fecdfSBarry Smith PetscCallP4estReturn(isInside, p4est_quadrant_is_inside_root, (&nq));
33500a96aa3bSJed Brown if (isInside) {
33510a96aa3bSJed Brown if (baseLabel) {
33529566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, t + cStartBase, &val));
33530a96aa3bSJed Brown } else {
33540a96aa3bSJed Brown val = t + cStartBase;
33550a96aa3bSJed Brown }
33569566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
33570a96aa3bSJed Brown } else {
33580a96aa3bSJed Brown int isOutside;
33590a96aa3bSJed Brown
3360792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p4est_quadrant_is_outside_face, (&nq));
33610a96aa3bSJed Brown if (isOutside) {
33620a96aa3bSJed Brown PetscInt f = -1;
33630a96aa3bSJed Brown
33640a96aa3bSJed Brown if (nq.x < 0) {
33650a96aa3bSJed Brown f = 0;
33660a96aa3bSJed Brown } else if (nq.x >= P4EST_ROOT_LEN) {
33670a96aa3bSJed Brown f = 1;
33680a96aa3bSJed Brown } else if (nq.y < 0) {
33690a96aa3bSJed Brown f = 2;
33700a96aa3bSJed Brown } else if (nq.y >= P4EST_ROOT_LEN) {
33710a96aa3bSJed Brown f = 3;
33720a96aa3bSJed Brown #if defined(P4_TO_P8)
33730a96aa3bSJed Brown } else if (nq.z < 0) {
33740a96aa3bSJed Brown f = 4;
33750a96aa3bSJed Brown } else {
33760a96aa3bSJed Brown f = 5;
33770a96aa3bSJed Brown #endif
33780a96aa3bSJed Brown }
33790a96aa3bSJed Brown f = pforest->topo->tree_face_to_uniq[P4EST_FACES * t + f];
33800a96aa3bSJed Brown if (baseLabel) {
33819566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, f + fStartBase, &val));
33820a96aa3bSJed Brown } else {
33830a96aa3bSJed Brown val = f + fStartBase;
33840a96aa3bSJed Brown }
33859566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
33860a96aa3bSJed Brown continue;
33870a96aa3bSJed Brown }
33880a96aa3bSJed Brown #if defined(P4_TO_P8)
3389792fecdfSBarry Smith PetscCallP4estReturn(isOutside, p8est_quadrant_is_outside_edge, (&nq));
33900a96aa3bSJed Brown if (isOutside) {
33910a96aa3bSJed Brown /* outside edge */
33920a96aa3bSJed Brown PetscInt e = -1;
33930a96aa3bSJed Brown
33940a96aa3bSJed Brown if (nq.x >= 0 && nq.x < P4EST_ROOT_LEN) {
33950a96aa3bSJed Brown if (nq.z < 0) {
33960a96aa3bSJed Brown if (nq.y < 0) {
33970a96aa3bSJed Brown e = 0;
33980a96aa3bSJed Brown } else {
33990a96aa3bSJed Brown e = 1;
34000a96aa3bSJed Brown }
34010a96aa3bSJed Brown } else {
34020a96aa3bSJed Brown if (nq.y < 0) {
34030a96aa3bSJed Brown e = 2;
34040a96aa3bSJed Brown } else {
34050a96aa3bSJed Brown e = 3;
34060a96aa3bSJed Brown }
34070a96aa3bSJed Brown }
34080a96aa3bSJed Brown } else if (nq.y >= 0 && nq.y < P4EST_ROOT_LEN) {
34090a96aa3bSJed Brown if (nq.z < 0) {
34100a96aa3bSJed Brown if (nq.x < 0) {
34110a96aa3bSJed Brown e = 4;
34120a96aa3bSJed Brown } else {
34130a96aa3bSJed Brown e = 5;
34140a96aa3bSJed Brown }
34150a96aa3bSJed Brown } else {
34160a96aa3bSJed Brown if (nq.x < 0) {
34170a96aa3bSJed Brown e = 6;
34180a96aa3bSJed Brown } else {
34190a96aa3bSJed Brown e = 7;
34200a96aa3bSJed Brown }
34210a96aa3bSJed Brown }
34220a96aa3bSJed Brown } else {
34230a96aa3bSJed Brown if (nq.y < 0) {
34240a96aa3bSJed Brown if (nq.x < 0) {
34250a96aa3bSJed Brown e = 8;
34260a96aa3bSJed Brown } else {
34270a96aa3bSJed Brown e = 9;
34280a96aa3bSJed Brown }
34290a96aa3bSJed Brown } else {
34300a96aa3bSJed Brown if (nq.x < 0) {
34310a96aa3bSJed Brown e = 10;
34320a96aa3bSJed Brown } else {
34330a96aa3bSJed Brown e = 11;
34340a96aa3bSJed Brown }
34350a96aa3bSJed Brown }
34360a96aa3bSJed Brown }
34370a96aa3bSJed Brown
34380a96aa3bSJed Brown e = pforest->topo->conn->tree_to_edge[P8EST_EDGES * t + e];
34390a96aa3bSJed Brown if (baseLabel) {
34409566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, e + eStartBase, &val));
34410a96aa3bSJed Brown } else {
34420a96aa3bSJed Brown val = e + eStartBase;
34430a96aa3bSJed Brown }
34449566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
34450a96aa3bSJed Brown continue;
34460a96aa3bSJed Brown }
34470a96aa3bSJed Brown #endif
34480a96aa3bSJed Brown {
34490a96aa3bSJed Brown /* outside vertex: same corner as quadrant corner */
34500a96aa3bSJed Brown PetscInt v = pforest->topo->conn->tree_to_corner[P4EST_CHILDREN * t + l];
34510a96aa3bSJed Brown
34520a96aa3bSJed Brown if (baseLabel) {
34539566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(baseLabel, v + vStartBase, &val));
34540a96aa3bSJed Brown } else {
34550a96aa3bSJed Brown val = v + vStartBase;
34560a96aa3bSJed Brown }
34579566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, p, val));
34580a96aa3bSJed Brown }
34590a96aa3bSJed Brown }
34600a96aa3bSJed Brown }
34610a96aa3bSJed Brown }
34620a96aa3bSJed Brown next = next->next;
34630a96aa3bSJed Brown }
34643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
34650a96aa3bSJed Brown }
34660a96aa3bSJed Brown
DMPforestLabelsFinalize(DM dm,DM plex)3467d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestLabelsFinalize(DM dm, DM plex)
3468d71ae5a4SJacob Faibussowitsch {
34690a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data;
34700a96aa3bSJed Brown DM adapt;
34710a96aa3bSJed Brown
34720a96aa3bSJed Brown PetscFunctionBegin;
34733ba16761SJacob Faibussowitsch if (pforest->labelsFinalized) PetscFunctionReturn(PETSC_SUCCESS);
34740a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE;
34759566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dm, &adapt));
34760a96aa3bSJed Brown if (!adapt) {
34770a96aa3bSJed Brown /* Initialize labels from the base dm */
34789566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsInitialize(dm, plex));
34790a96aa3bSJed Brown } else {
34800a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1};
34810a96aa3bSJed Brown PetscSF transferForward, transferBackward, pointSF;
34820a96aa3bSJed Brown PetscInt pStart, pEnd, pStartA, pEndA;
34830a96aa3bSJed Brown PetscInt *values, *adaptValues;
34840a96aa3bSJed Brown DMLabelLink next = adapt->labels;
34850a96aa3bSJed Brown DMLabel adaptLabel;
34860a96aa3bSJed Brown DM adaptPlex;
34870a96aa3bSJed Brown
34889566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityLabel(dm, &adaptLabel));
34899566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(adapt, &adaptPlex));
34909566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF(adapt, dm, dofPerDim, &transferForward, &transferBackward));
34919566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &pStart, &pEnd));
34929566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(adaptPlex, &pStartA, &pEndA));
34939566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &values, pEndA - pStartA, &adaptValues));
34949566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(plex, &pointSF));
34950a96aa3bSJed Brown if (PetscDefined(USE_DEBUG)) {
34960a96aa3bSJed Brown PetscInt p;
34970a96aa3bSJed Brown for (p = pStartA; p < pEndA; p++) adaptValues[p - pStartA] = -1;
34980a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) values[p - pStart] = -2;
34990a96aa3bSJed Brown if (transferForward) {
35009566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE));
35019566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE));
35020a96aa3bSJed Brown }
35030a96aa3bSJed Brown if (transferBackward) {
350457168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX));
350557168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX));
35060a96aa3bSJed Brown }
35070a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) {
35080a96aa3bSJed Brown PetscInt q = p, parent;
35090a96aa3bSJed Brown
35109566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL));
35110a96aa3bSJed Brown while (parent != q) {
35120a96aa3bSJed Brown if (values[parent] == -2) values[parent] = values[q];
35130a96aa3bSJed Brown q = parent;
35149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL));
35150a96aa3bSJed Brown }
35160a96aa3bSJed Brown }
351757168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, values, values, MPI_MAX));
351857168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, values, values, MPI_MAX));
35199566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, values, values, MPI_REPLACE));
35209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, values, values, MPI_REPLACE));
3521ad540459SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCheck(values[p - pStart] != -2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "uncovered point %" PetscInt_FMT, p);
35220a96aa3bSJed Brown }
35230a96aa3bSJed Brown while (next) {
35240a96aa3bSJed Brown DMLabel nextLabel = next->label;
35250a96aa3bSJed Brown const char *name;
35260a96aa3bSJed Brown PetscBool isDepth, isCellType, isGhost, isVTK;
35270a96aa3bSJed Brown DMLabel label;
35280a96aa3bSJed Brown PetscInt p;
35290a96aa3bSJed Brown
35309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)nextLabel, &name));
35319566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isDepth));
35320a96aa3bSJed Brown if (isDepth) {
35330a96aa3bSJed Brown next = next->next;
35340a96aa3bSJed Brown continue;
35350a96aa3bSJed Brown }
35369566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "celltype", &isCellType));
35370a96aa3bSJed Brown if (isCellType) {
35380a96aa3bSJed Brown next = next->next;
35390a96aa3bSJed Brown continue;
35400a96aa3bSJed Brown }
35419566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "ghost", &isGhost));
35420a96aa3bSJed Brown if (isGhost) {
35430a96aa3bSJed Brown next = next->next;
35440a96aa3bSJed Brown continue;
35450a96aa3bSJed Brown }
35469566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "vtk", &isVTK));
35470a96aa3bSJed Brown if (isVTK) {
35480a96aa3bSJed Brown next = next->next;
35490a96aa3bSJed Brown continue;
35500a96aa3bSJed Brown }
35510a96aa3bSJed Brown if (nextLabel == adaptLabel) {
35520a96aa3bSJed Brown next = next->next;
35530a96aa3bSJed Brown continue;
35540a96aa3bSJed Brown }
35550a96aa3bSJed Brown /* label was created earlier */
35569566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label));
355748a46eb9SPierre Jolivet for (p = pStartA; p < pEndA; p++) PetscCall(DMLabelGetValue(nextLabel, p, &adaptValues[p]));
35581690c2aeSBarry Smith for (p = pStart; p < pEnd; p++) values[p] = PETSC_INT_MIN;
35590a96aa3bSJed Brown
35601baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastBegin(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE));
356157168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceBegin(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX));
35621baa6e33SBarry Smith if (transferForward) PetscCall(PetscSFBcastEnd(transferForward, MPIU_INT, adaptValues, values, MPI_REPLACE));
356357168dbeSPierre Jolivet if (transferBackward) PetscCall(PetscSFReduceEnd(transferBackward, MPIU_INT, adaptValues, values, MPI_MAX));
35640a96aa3bSJed Brown for (p = pStart; p < pEnd; p++) {
35650a96aa3bSJed Brown PetscInt q = p, parent;
35660a96aa3bSJed Brown
35679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL));
35680a96aa3bSJed Brown while (parent != q) {
35691690c2aeSBarry Smith if (values[parent] == PETSC_INT_MIN) values[parent] = values[q];
35700a96aa3bSJed Brown q = parent;
35719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(plex, q, &parent, NULL));
35720a96aa3bSJed Brown }
35730a96aa3bSJed Brown }
357457168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(pointSF, MPIU_INT, values, values, MPI_MAX));
357557168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(pointSF, MPIU_INT, values, values, MPI_MAX));
35769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pointSF, MPIU_INT, values, values, MPI_REPLACE));
35779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pointSF, MPIU_INT, values, values, MPI_REPLACE));
35780a96aa3bSJed Brown
357948a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMLabelSetValue(label, p, values[p]));
35800a96aa3bSJed Brown next = next->next;
35810a96aa3bSJed Brown }
35829566063dSJacob Faibussowitsch PetscCall(PetscFree2(values, adaptValues));
35839566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferForward));
35849566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferBackward));
35850a96aa3bSJed Brown pforest->labelsFinalized = PETSC_TRUE;
35860a96aa3bSJed Brown }
35873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
35880a96aa3bSJed Brown }
35890a96aa3bSJed Brown
DMPforestMapCoordinates_Cell(DM plex,p4est_geometry_t * geom,PetscInt cell,p4est_quadrant_t * q,p4est_topidx_t t,p4est_connectivity_t * conn,PetscScalar * coords)3590d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestMapCoordinates_Cell(DM plex, p4est_geometry_t *geom, PetscInt cell, p4est_quadrant_t *q, p4est_topidx_t t, p4est_connectivity_t *conn, PetscScalar *coords)
3591d71ae5a4SJacob Faibussowitsch {
35920a96aa3bSJed Brown PetscInt closureSize, c, coordStart, coordEnd, coordDim;
35930a96aa3bSJed Brown PetscInt *closure = NULL;
35940a96aa3bSJed Brown PetscSection coordSec;
35950a96aa3bSJed Brown
35960a96aa3bSJed Brown PetscFunctionBegin;
35979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &coordSec));
35989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec, &coordStart, &coordEnd));
35999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex, &coordDim));
36009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, cell, PETSC_TRUE, &closureSize, &closure));
36010a96aa3bSJed Brown for (c = 0; c < closureSize; c++) {
36020a96aa3bSJed Brown PetscInt point = closure[2 * c];
36030a96aa3bSJed Brown
36040a96aa3bSJed Brown if (point >= coordStart && point < coordEnd) {
36050a96aa3bSJed Brown PetscInt dof, off;
36060a96aa3bSJed Brown PetscInt nCoords, i;
36079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec, point, &dof));
360808401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Did not understand coordinate layout");
36090a96aa3bSJed Brown nCoords = dof / coordDim;
36109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec, point, &off));
36110a96aa3bSJed Brown for (i = 0; i < nCoords; i++) {
36120a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim];
36130a96aa3bSJed Brown double coordP4est[3] = {0.};
36140a96aa3bSJed Brown double coordP4estMapped[3] = {0.};
36150a96aa3bSJed Brown PetscInt j;
36160a96aa3bSJed Brown PetscReal treeCoords[P4EST_CHILDREN][3] = {{0.}};
36170a96aa3bSJed Brown PetscReal eta[3] = {0.};
36180a96aa3bSJed Brown PetscInt numRounds = 10;
36190a96aa3bSJed Brown PetscReal coordGuess[3] = {0.};
36200a96aa3bSJed Brown
36210a96aa3bSJed Brown eta[0] = (PetscReal)q->x / (PetscReal)P4EST_ROOT_LEN;
36220a96aa3bSJed Brown eta[1] = (PetscReal)q->y / (PetscReal)P4EST_ROOT_LEN;
36230a96aa3bSJed Brown #if defined(P4_TO_P8)
36240a96aa3bSJed Brown eta[2] = (PetscReal)q->z / (PetscReal)P4EST_ROOT_LEN;
36250a96aa3bSJed Brown #endif
36260a96aa3bSJed Brown
36270a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) {
36280a96aa3bSJed Brown PetscInt k;
36290a96aa3bSJed Brown
36300a96aa3bSJed Brown for (k = 0; k < 3; k++) treeCoords[j][k] = conn->vertices[3 * conn->tree_to_vertex[P4EST_CHILDREN * t + j] + k];
36310a96aa3bSJed Brown }
36320a96aa3bSJed Brown
36330a96aa3bSJed Brown for (j = 0; j < P4EST_CHILDREN; j++) {
36340a96aa3bSJed Brown PetscInt k;
36350a96aa3bSJed Brown PetscReal prod = 1.;
36360a96aa3bSJed Brown
36370a96aa3bSJed Brown for (k = 0; k < P4EST_DIM; k++) prod *= (j & (1 << k)) ? eta[k] : (1. - eta[k]);
36380a96aa3bSJed Brown for (k = 0; k < 3; k++) coordGuess[k] += prod * treeCoords[j][k];
36390a96aa3bSJed Brown }
36400a96aa3bSJed Brown
36410a96aa3bSJed Brown for (j = 0; j < numRounds; j++) {
36420a96aa3bSJed Brown PetscInt dir;
36430a96aa3bSJed Brown
36440a96aa3bSJed Brown for (dir = 0; dir < P4EST_DIM; dir++) {
36450a96aa3bSJed Brown PetscInt k;
36460a96aa3bSJed Brown PetscReal diff[3];
36470a96aa3bSJed Brown PetscReal dXdeta[3] = {0.};
36480a96aa3bSJed Brown PetscReal rhs, scale, update;
36490a96aa3bSJed Brown
36500a96aa3bSJed Brown for (k = 0; k < 3; k++) diff[k] = coordP4est[k] - coordGuess[k];
36510a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) {
36520a96aa3bSJed Brown PetscInt l;
36530a96aa3bSJed Brown PetscReal prod = 1.;
36540a96aa3bSJed Brown
36550a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) {
36560a96aa3bSJed Brown if (l == dir) {
36570a96aa3bSJed Brown prod *= (k & (1 << l)) ? 1. : -1.;
36580a96aa3bSJed Brown } else {
36590a96aa3bSJed Brown prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]);
36600a96aa3bSJed Brown }
36610a96aa3bSJed Brown }
36620a96aa3bSJed Brown for (l = 0; l < 3; l++) dXdeta[l] += prod * treeCoords[k][l];
36630a96aa3bSJed Brown }
36640a96aa3bSJed Brown rhs = 0.;
36650a96aa3bSJed Brown scale = 0;
36660a96aa3bSJed Brown for (k = 0; k < 3; k++) {
36670a96aa3bSJed Brown rhs += diff[k] * dXdeta[k];
36680a96aa3bSJed Brown scale += dXdeta[k] * dXdeta[k];
36690a96aa3bSJed Brown }
36700a96aa3bSJed Brown update = rhs / scale;
36710a96aa3bSJed Brown eta[dir] += update;
36720a96aa3bSJed Brown eta[dir] = PetscMin(eta[dir], 1.);
36730a96aa3bSJed Brown eta[dir] = PetscMax(eta[dir], 0.);
36740a96aa3bSJed Brown
36750a96aa3bSJed Brown coordGuess[0] = coordGuess[1] = coordGuess[2] = 0.;
36760a96aa3bSJed Brown for (k = 0; k < P4EST_CHILDREN; k++) {
36770a96aa3bSJed Brown PetscInt l;
36780a96aa3bSJed Brown PetscReal prod = 1.;
36790a96aa3bSJed Brown
36800a96aa3bSJed Brown for (l = 0; l < P4EST_DIM; l++) prod *= (k & (1 << l)) ? eta[l] : (1. - eta[l]);
36810a96aa3bSJed Brown for (l = 0; l < 3; l++) coordGuess[l] += prod * treeCoords[k][l];
36820a96aa3bSJed Brown }
36830a96aa3bSJed Brown }
36840a96aa3bSJed Brown }
36850a96aa3bSJed Brown for (j = 0; j < 3; j++) coordP4est[j] = (double)eta[j];
36860a96aa3bSJed Brown
3687966bd95aSPierre Jolivet PetscCheck(geom, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded");
36880a96aa3bSJed Brown (geom->X)(geom, t, coordP4est, coordP4estMapped);
36890a96aa3bSJed Brown for (j = 0; j < coordDim; j++) coord[j] = (PetscScalar)coordP4estMapped[j];
36900a96aa3bSJed Brown }
36910a96aa3bSJed Brown }
36920a96aa3bSJed Brown }
36939566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, cell, PETSC_TRUE, &closureSize, &closure));
36943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
36950a96aa3bSJed Brown }
36960a96aa3bSJed Brown
DMPforestMapCoordinates(DM dm,DM plex)3697d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestMapCoordinates(DM dm, DM plex)
3698d71ae5a4SJacob Faibussowitsch {
36990a96aa3bSJed Brown DM_Forest *forest;
37000a96aa3bSJed Brown DM_Forest_pforest *pforest;
37010a96aa3bSJed Brown p4est_geometry_t *geom;
37020a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd;
37030a96aa3bSJed Brown Vec coordLocalVec;
37040a96aa3bSJed Brown PetscScalar *coords;
37050a96aa3bSJed Brown p4est_topidx_t flt, llt, t;
37060a96aa3bSJed Brown p4est_tree_t *trees;
37070a96aa3bSJed Brown PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *);
37080a96aa3bSJed Brown void *mapCtx;
37090a96aa3bSJed Brown
37100a96aa3bSJed Brown PetscFunctionBegin;
37110a96aa3bSJed Brown forest = (DM_Forest *)dm->data;
37120a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data;
37130a96aa3bSJed Brown geom = pforest->topo->geom;
37149566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx));
37153ba16761SJacob Faibussowitsch if (!geom && !map) PetscFunctionReturn(PETSC_SUCCESS);
37169566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(plex, &coordLocalVec));
37179566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordLocalVec, &coords));
37180a96aa3bSJed Brown cLocalStart = pforest->cLocalStart;
37190a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd;
37200a96aa3bSJed Brown flt = pforest->forest->first_local_tree;
37210a96aa3bSJed Brown llt = pforest->forest->last_local_tree;
37220a96aa3bSJed Brown trees = (p4est_tree_t *)pforest->forest->trees->array;
37230a96aa3bSJed Brown if (map) { /* apply the map directly to the existing coordinates */
37240a96aa3bSJed Brown PetscSection coordSec;
37250a96aa3bSJed Brown PetscInt coordStart, coordEnd, p, coordDim, p4estCoordDim, cStart, cEnd, cEndInterior;
37260a96aa3bSJed Brown DM base;
37270a96aa3bSJed Brown
37289566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd));
37292827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(plex, DM_POLYTOPE_FV_GHOST, &cEndInterior, NULL));
37300a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior;
37319566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base));
37329566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &coordSec));
37339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSec, &coordStart, &coordEnd));
37349566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(plex, &coordDim));
37350a96aa3bSJed Brown p4estCoordDim = PetscMin(coordDim, 3);
37360a96aa3bSJed Brown for (p = coordStart; p < coordEnd; p++) {
37370a96aa3bSJed Brown PetscInt *star = NULL, starSize;
37380a96aa3bSJed Brown PetscInt dof, off, cell = -1, coarsePoint = -1;
37390a96aa3bSJed Brown PetscInt nCoords, i;
37409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSec, p, &dof));
374108401ef6SPierre Jolivet PetscCheck(dof % coordDim == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Did not understand coordinate layout");
37420a96aa3bSJed Brown nCoords = dof / coordDim;
37439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSec, p, &off));
37449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star));
37450a96aa3bSJed Brown for (i = 0; i < starSize; i++) {
37460a96aa3bSJed Brown PetscInt point = star[2 * i];
37470a96aa3bSJed Brown
37480a96aa3bSJed Brown if (cStart <= point && point < cEnd) {
37490a96aa3bSJed Brown cell = point;
37500a96aa3bSJed Brown break;
37510a96aa3bSJed Brown }
37520a96aa3bSJed Brown }
37539566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(plex, p, PETSC_FALSE, &starSize, &star));
37540a96aa3bSJed Brown if (cell >= 0) {
37550a96aa3bSJed Brown if (cell < cLocalStart) {
37560a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array;
37570a96aa3bSJed Brown
37580a96aa3bSJed Brown coarsePoint = ghosts[cell].p.which_tree;
37590a96aa3bSJed Brown } else if (cell < cLocalEnd) {
37600a96aa3bSJed Brown cell -= cLocalStart;
37610a96aa3bSJed Brown for (t = flt; t <= llt; t++) {
3762f4f49eeaSPierre Jolivet p4est_tree_t *tree = &trees[t];
37630a96aa3bSJed Brown
37640a96aa3bSJed Brown if (cell >= tree->quadrants_offset && (size_t)cell < tree->quadrants_offset + tree->quadrants.elem_count) {
37650a96aa3bSJed Brown coarsePoint = t;
37660a96aa3bSJed Brown break;
37670a96aa3bSJed Brown }
37680a96aa3bSJed Brown }
37690a96aa3bSJed Brown } else {
37700a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array;
37710a96aa3bSJed Brown
37720a96aa3bSJed Brown coarsePoint = ghosts[cell - cLocalEnd].p.which_tree;
37730a96aa3bSJed Brown }
37740a96aa3bSJed Brown }
37750a96aa3bSJed Brown for (i = 0; i < nCoords; i++) {
37760a96aa3bSJed Brown PetscScalar *coord = &coords[off + i * coordDim];
37770a96aa3bSJed Brown PetscReal coordP4est[3] = {0.};
37780a96aa3bSJed Brown PetscReal coordP4estMapped[3] = {0.};
37790a96aa3bSJed Brown PetscInt j;
37800a96aa3bSJed Brown
37810a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coordP4est[j] = PetscRealPart(coord[j]);
37829566063dSJacob Faibussowitsch PetscCall((map)(base, coarsePoint, p4estCoordDim, coordP4est, coordP4estMapped, mapCtx));
37830a96aa3bSJed Brown for (j = 0; j < p4estCoordDim; j++) coord[j] = (PetscScalar)coordP4estMapped[j];
37840a96aa3bSJed Brown }
37850a96aa3bSJed Brown }
37860a96aa3bSJed Brown } else { /* we have to transform coordinates back to the unit cube (where geom is defined), and then apply geom */
37870a96aa3bSJed Brown PetscInt cStart, cEnd, cEndInterior;
37880a96aa3bSJed Brown
37899566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd));
37902827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(plex, DM_POLYTOPE_FV_GHOST, &cEndInterior, NULL));
37910a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior;
37920a96aa3bSJed Brown if (cLocalStart > 0) {
37930a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array;
37940a96aa3bSJed Brown PetscInt count;
37950a96aa3bSJed Brown
37960a96aa3bSJed Brown for (count = 0; count < cLocalStart; count++) {
37970a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count];
37980a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree;
37990a96aa3bSJed Brown
38009566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count, quad, t, pforest->topo->conn, coords));
38010a96aa3bSJed Brown }
38020a96aa3bSJed Brown }
38030a96aa3bSJed Brown for (t = flt; t <= llt; t++) {
3804f4f49eeaSPierre Jolivet p4est_tree_t *tree = &trees[t];
38050a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset, i;
38060a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count;
38070a96aa3bSJed Brown p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array;
38080a96aa3bSJed Brown
38090a96aa3bSJed Brown for (i = 0; i < numQuads; i++) {
38100a96aa3bSJed Brown PetscInt count = i + offset;
38110a96aa3bSJed Brown
38129566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count, &quads[i], t, pforest->topo->conn, coords));
38130a96aa3bSJed Brown }
38140a96aa3bSJed Brown }
38150a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) {
38160a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array;
38170a96aa3bSJed Brown PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count;
38180a96aa3bSJed Brown PetscInt count;
38190a96aa3bSJed Brown
38200a96aa3bSJed Brown for (count = 0; count < numGhosts - cLocalStart; count++) {
38210a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart];
38220a96aa3bSJed Brown p4est_topidx_t t = quad->p.which_tree;
38230a96aa3bSJed Brown
38249566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates_Cell(plex, geom, count + cLocalEnd, quad, t, pforest->topo->conn, coords));
38250a96aa3bSJed Brown }
38260a96aa3bSJed Brown }
38270a96aa3bSJed Brown }
38289566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordLocalVec, &coords));
38293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
38300a96aa3bSJed Brown }
38310a96aa3bSJed Brown
PforestQuadrantIsInterior(p4est_quadrant_t * quad,PetscBool * is_interior)3832d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestQuadrantIsInterior(p4est_quadrant_t *quad, PetscBool *is_interior)
3833d71ae5a4SJacob Faibussowitsch {
3834852b71a7SToby Isaac PetscFunctionBegin;
3835852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level);
3836852b71a7SToby Isaac if ((quad->x > 0) && (quad->x + h < P4EST_ROOT_LEN)
3837852b71a7SToby Isaac #ifdef P4_TO_P8
3838852b71a7SToby Isaac && (quad->z > 0) && (quad->z + h < P4EST_ROOT_LEN)
3839852b71a7SToby Isaac #endif
3840852b71a7SToby Isaac && (quad->y > 0) && (quad->y + h < P4EST_ROOT_LEN)) {
3841852b71a7SToby Isaac *is_interior = PETSC_TRUE;
3842852b71a7SToby Isaac } else {
3843852b71a7SToby Isaac *is_interior = PETSC_FALSE;
3844852b71a7SToby Isaac }
38453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3846852b71a7SToby Isaac }
3847852b71a7SToby Isaac
3848852b71a7SToby Isaac /* We always use DG coordinates with p4est: if they do not match the vertex
3849852b71a7SToby Isaac coordinates, add space for them in the section */
PforestCheckLocalizeCell(DM plex,PetscInt cDim,Vec cVecOld,DM_Forest_pforest * pforest,PetscSection oldSection,PetscSection newSection,PetscInt cell,PetscInt coarsePoint,p4est_quadrant_t * quad)3850d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestCheckLocalizeCell(DM plex, PetscInt cDim, Vec cVecOld, DM_Forest_pforest *pforest, PetscSection oldSection, PetscSection newSection, PetscInt cell, PetscInt coarsePoint, p4est_quadrant_t *quad)
3851d71ae5a4SJacob Faibussowitsch {
3852852b71a7SToby Isaac PetscBool is_interior;
3853852b71a7SToby Isaac
3854852b71a7SToby Isaac PetscFunctionBegin;
3855852b71a7SToby Isaac PetscCall(PforestQuadrantIsInterior(quad, &is_interior));
3856852b71a7SToby Isaac if (is_interior) { // quads in the interior of a coarse cell can't touch periodic interfaces
3857852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0));
3858852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0));
3859852b71a7SToby Isaac } else {
3860852b71a7SToby Isaac PetscInt cSize;
3861852b71a7SToby Isaac PetscScalar *values = NULL;
3862852b71a7SToby Isaac PetscBool same_coords = PETSC_TRUE;
3863852b71a7SToby Isaac
3864852b71a7SToby Isaac PetscCall(DMPlexVecGetClosure(plex, oldSection, cVecOld, cell, &cSize, &values));
3865852b71a7SToby Isaac PetscAssert(cSize == cDim * P4EST_CHILDREN, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected closure size");
3866852b71a7SToby Isaac for (int c = 0; c < P4EST_CHILDREN; c++) {
3867852b71a7SToby Isaac p4est_qcoord_t quad_coords[3];
3868852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level);
3869852b71a7SToby Isaac double corner_coords[3];
3870852b71a7SToby Isaac double vert_coords[3];
3871852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c];
3872852b71a7SToby Isaac
3873ad540459SPierre Jolivet for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) vert_coords[d] = PetscRealPart(values[c * cDim + d]);
3874852b71a7SToby Isaac
3875852b71a7SToby Isaac quad_coords[0] = quad->x;
3876852b71a7SToby Isaac quad_coords[1] = quad->y;
3877852b71a7SToby Isaac #ifdef P4_TO_P8
3878852b71a7SToby Isaac quad_coords[2] = quad->z;
3879852b71a7SToby Isaac #endif
3880ad540459SPierre Jolivet for (int d = 0; d < 3; d++) quad_coords[d] += (corner & (1 << d)) ? h : 0;
3881*beceaeb6SBarry Smith #if !defined(P4_TO_P8)
3882648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords));
3883852b71a7SToby Isaac #else
3884648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords));
3885852b71a7SToby Isaac #endif
3886852b71a7SToby Isaac for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) {
3887852b71a7SToby Isaac if (fabs(vert_coords[d] - corner_coords[d]) > PETSC_SMALL) {
3888852b71a7SToby Isaac same_coords = PETSC_FALSE;
3889852b71a7SToby Isaac break;
3890852b71a7SToby Isaac }
3891852b71a7SToby Isaac }
3892852b71a7SToby Isaac }
3893852b71a7SToby Isaac if (same_coords) {
3894852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, 0));
3895852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, 0));
3896852b71a7SToby Isaac } else {
3897852b71a7SToby Isaac PetscCall(PetscSectionSetDof(newSection, cell, cSize));
3898852b71a7SToby Isaac PetscCall(PetscSectionSetFieldDof(newSection, cell, 0, cSize));
3899852b71a7SToby Isaac }
3900852b71a7SToby Isaac PetscCall(DMPlexVecRestoreClosure(plex, oldSection, cVecOld, cell, &cSize, &values));
3901852b71a7SToby Isaac }
39023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3903852b71a7SToby Isaac }
3904852b71a7SToby Isaac
PforestLocalizeCell(DM plex,PetscInt cDim,DM_Forest_pforest * pforest,PetscSection newSection,PetscInt cell,PetscInt coarsePoint,p4est_quadrant_t * quad,PetscScalar coords[])3905d71ae5a4SJacob Faibussowitsch static PetscErrorCode PforestLocalizeCell(DM plex, PetscInt cDim, DM_Forest_pforest *pforest, PetscSection newSection, PetscInt cell, PetscInt coarsePoint, p4est_quadrant_t *quad, PetscScalar coords[])
3906d71ae5a4SJacob Faibussowitsch {
3907852b71a7SToby Isaac PetscInt cdof, off;
3908852b71a7SToby Isaac
3909852b71a7SToby Isaac PetscFunctionBegin;
3910852b71a7SToby Isaac PetscCall(PetscSectionGetDof(newSection, cell, &cdof));
39113ba16761SJacob Faibussowitsch if (!cdof) PetscFunctionReturn(PETSC_SUCCESS);
3912852b71a7SToby Isaac
3913852b71a7SToby Isaac PetscCall(PetscSectionGetOffset(newSection, cell, &off));
3914852b71a7SToby Isaac for (PetscInt c = 0, pos = off; c < P4EST_CHILDREN; c++) {
3915852b71a7SToby Isaac p4est_qcoord_t quad_coords[3];
3916852b71a7SToby Isaac p4est_qcoord_t h = P4EST_QUADRANT_LEN(quad->level);
3917852b71a7SToby Isaac double corner_coords[3];
3918852b71a7SToby Isaac PetscInt corner = PetscVertToP4estVert[c];
3919852b71a7SToby Isaac
3920852b71a7SToby Isaac quad_coords[0] = quad->x;
3921852b71a7SToby Isaac quad_coords[1] = quad->y;
3922852b71a7SToby Isaac #ifdef P4_TO_P8
3923852b71a7SToby Isaac quad_coords[2] = quad->z;
3924852b71a7SToby Isaac #endif
3925ad540459SPierre Jolivet for (int d = 0; d < 3; d++) quad_coords[d] += (corner & (1 << d)) ? h : 0;
3926*beceaeb6SBarry Smith #if !defined(P4_TO_P8)
3927648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], corner_coords));
3928852b71a7SToby Isaac #else
3929648bc8c4SBarry Smith PetscCallP4est(p4est_qcoord_to_vertex, (pforest->forest->connectivity, coarsePoint, quad_coords[0], quad_coords[1], quad_coords[2], corner_coords));
3930852b71a7SToby Isaac #endif
3931ad540459SPierre Jolivet for (PetscInt d = 0; d < PetscMin(cDim, 3); d++) coords[pos++] = corner_coords[d];
3932ad540459SPierre Jolivet for (PetscInt d = PetscMin(cDim, 3); d < cDim; d++) coords[pos++] = 0.;
3933852b71a7SToby Isaac }
39343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3935852b71a7SToby Isaac }
3936852b71a7SToby Isaac
DMPforestLocalizeCoordinates(DM dm,DM plex)3937d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestLocalizeCoordinates(DM dm, DM plex)
3938d71ae5a4SJacob Faibussowitsch {
39390a96aa3bSJed Brown DM_Forest *forest;
39400a96aa3bSJed Brown DM_Forest_pforest *pforest;
39416858538eSMatthew G. Knepley DM base, cdm, cdmCell;
3942852b71a7SToby Isaac Vec cVec, cVecOld;
3943852b71a7SToby Isaac PetscSection oldSection, newSection;
39440a96aa3bSJed Brown PetscScalar *coords2;
39456858538eSMatthew G. Knepley const PetscReal *L;
39460a96aa3bSJed Brown PetscInt cLocalStart, cLocalEnd, coarsePoint;
3947852b71a7SToby Isaac PetscInt cDim, newStart, newEnd;
3948852b71a7SToby Isaac PetscInt v, vStart, vEnd, cp, cStart, cEnd, cEndInterior;
39490a96aa3bSJed Brown p4est_topidx_t flt, llt, t;
39500a96aa3bSJed Brown p4est_tree_t *trees;
39516858538eSMatthew G. Knepley PetscBool baseLocalized = PETSC_FALSE;
39520a96aa3bSJed Brown
39530a96aa3bSJed Brown PetscFunctionBegin;
39544fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, NULL, NULL, &L));
39550a96aa3bSJed Brown /* we localize on all cells if we don't have a base DM or the base DM coordinates have not been localized */
39569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cDim));
39579566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base));
39586858538eSMatthew G. Knepley if (base) PetscCall(DMGetCoordinatesLocalized(base, &baseLocalized));
39590a96aa3bSJed Brown if (!baseLocalized) base = NULL;
39603ba16761SJacob Faibussowitsch if (!baseLocalized && !L) PetscFunctionReturn(PETSC_SUCCESS);
39619566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &newStart, &newEnd));
39620a96aa3bSJed Brown
39639566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newSection));
39649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(newSection, 1));
39659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(newSection, 0, cDim));
39669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSection, newStart, newEnd));
39670a96aa3bSJed Brown
39689566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(plex, &oldSection));
39699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(plex, 0, &vStart, &vEnd));
3970852b71a7SToby Isaac PetscCall(DMGetCoordinatesLocal(plex, &cVecOld));
39710a96aa3bSJed Brown
39720a96aa3bSJed Brown forest = (DM_Forest *)dm->data;
39730a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data;
39740a96aa3bSJed Brown cLocalStart = pforest->cLocalStart;
39750a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd;
39760a96aa3bSJed Brown flt = pforest->forest->first_local_tree;
39770a96aa3bSJed Brown llt = pforest->forest->last_local_tree;
39780a96aa3bSJed Brown trees = (p4est_tree_t *)pforest->forest->trees->array;
39790a96aa3bSJed Brown
39809566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd));
39812827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(plex, DM_POLYTOPE_FV_GHOST, &cEndInterior, NULL));
39820a96aa3bSJed Brown cEnd = cEndInterior < 0 ? cEnd : cEndInterior;
3983852b71a7SToby Isaac cp = 0;
39840a96aa3bSJed Brown if (cLocalStart > 0) {
39850a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array;
3986852b71a7SToby Isaac PetscInt cell;
39870a96aa3bSJed Brown
3988852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) {
3989852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell];
3990852b71a7SToby Isaac
39910a96aa3bSJed Brown coarsePoint = quad->p.which_tree;
3992852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad));
39930a96aa3bSJed Brown }
39940a96aa3bSJed Brown }
39950a96aa3bSJed Brown for (t = flt; t <= llt; t++) {
3996f4f49eeaSPierre Jolivet p4est_tree_t *tree = &trees[t];
39970a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset;
39980a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count;
3999852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array;
40000a96aa3bSJed Brown PetscInt i;
40010a96aa3bSJed Brown
40020a96aa3bSJed Brown if (!numQuads) continue;
40030a96aa3bSJed Brown coarsePoint = t;
4004852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) {
4005852b71a7SToby Isaac PetscInt cell = i + offset;
4006852b71a7SToby Isaac p4est_quadrant_t *quad = &quads[i];
40070a96aa3bSJed Brown
4008852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad));
40090a96aa3bSJed Brown }
40100a96aa3bSJed Brown }
40110a96aa3bSJed Brown if (cLocalEnd - cLocalStart < cEnd - cStart) {
40120a96aa3bSJed Brown p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array;
40130a96aa3bSJed Brown PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count;
40140a96aa3bSJed Brown PetscInt count;
40150a96aa3bSJed Brown
4016852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) {
40170a96aa3bSJed Brown p4est_quadrant_t *quad = &ghosts[count + cLocalStart];
40180a96aa3bSJed Brown coarsePoint = quad->p.which_tree;
4019852b71a7SToby Isaac PetscInt cell = count + cLocalEnd;
40200a96aa3bSJed Brown
4021852b71a7SToby Isaac PetscCall(PforestCheckLocalizeCell(plex, cDim, cVecOld, pforest, oldSection, newSection, cell, coarsePoint, quad));
40220a96aa3bSJed Brown }
40230a96aa3bSJed Brown }
4024852b71a7SToby Isaac PetscAssert(cp == cEnd - cStart, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected number of fine cells %" PetscInt_FMT " != %" PetscInt_FMT, cp, cEnd - cStart);
40250a96aa3bSJed Brown
40269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSection));
40276858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(plex, &cdm));
40286858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell));
40296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(plex, cdmCell));
40306858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell));
40316858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(plex, cDim, newSection));
40329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSection, &v));
40339566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &cVec));
40349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)cVec, "coordinates"));
40359566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(cVec, cDim));
40369566063dSJacob Faibussowitsch PetscCall(VecSetSizes(cVec, v, PETSC_DETERMINE));
40379566063dSJacob Faibussowitsch PetscCall(VecSetType(cVec, VECSTANDARD));
40389566063dSJacob Faibussowitsch PetscCall(VecSet(cVec, PETSC_MIN_REAL));
40390a96aa3bSJed Brown
40400a96aa3bSJed Brown /* Localize coordinates on cells if needed */
40416858538eSMatthew G. Knepley PetscCall(VecGetArray(cVec, &coords2));
4042852b71a7SToby Isaac cp = 0;
4043852b71a7SToby Isaac if (cLocalStart > 0) {
4044852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array;
4045852b71a7SToby Isaac PetscInt cell;
4046852b71a7SToby Isaac
4047852b71a7SToby Isaac for (cell = 0; cell < cLocalStart; ++cell, cp++) {
4048852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[cell];
4049852b71a7SToby Isaac
4050852b71a7SToby Isaac coarsePoint = quad->p.which_tree;
4051852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2));
4052852b71a7SToby Isaac }
4053852b71a7SToby Isaac }
40540a96aa3bSJed Brown for (t = flt; t <= llt; t++) {
4055f4f49eeaSPierre Jolivet p4est_tree_t *tree = &trees[t];
40560a96aa3bSJed Brown PetscInt offset = cLocalStart + tree->quadrants_offset;
40570a96aa3bSJed Brown PetscInt numQuads = (PetscInt)tree->quadrants.elem_count;
4058852b71a7SToby Isaac p4est_quadrant_t *quads = (p4est_quadrant_t *)tree->quadrants.array;
4059852b71a7SToby Isaac PetscInt i;
40600a96aa3bSJed Brown
40610a96aa3bSJed Brown if (!numQuads) continue;
4062852b71a7SToby Isaac coarsePoint = t;
4063852b71a7SToby Isaac for (i = 0; i < numQuads; i++, cp++) {
4064852b71a7SToby Isaac PetscInt cell = i + offset;
40650a96aa3bSJed Brown p4est_quadrant_t *quad = &quads[i];
40660a96aa3bSJed Brown
4067852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2));
4068852b71a7SToby Isaac }
4069852b71a7SToby Isaac }
4070852b71a7SToby Isaac if (cLocalEnd - cLocalStart < cEnd - cStart) {
4071852b71a7SToby Isaac p4est_quadrant_t *ghosts = (p4est_quadrant_t *)pforest->ghost->ghosts.array;
4072852b71a7SToby Isaac PetscInt numGhosts = (PetscInt)pforest->ghost->ghosts.elem_count;
4073852b71a7SToby Isaac PetscInt count;
40740a96aa3bSJed Brown
4075852b71a7SToby Isaac for (count = 0; count < numGhosts - cLocalStart; count++, cp++) {
4076852b71a7SToby Isaac p4est_quadrant_t *quad = &ghosts[count + cLocalStart];
4077852b71a7SToby Isaac coarsePoint = quad->p.which_tree;
4078852b71a7SToby Isaac PetscInt cell = count + cLocalEnd;
40790a96aa3bSJed Brown
4080852b71a7SToby Isaac PetscCall(PforestLocalizeCell(plex, cDim, pforest, newSection, cell, coarsePoint, quad, coords2));
40810a96aa3bSJed Brown }
40820a96aa3bSJed Brown }
40839566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cVec, &coords2));
40846858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(plex, cVec));
40859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cVec));
40869566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newSection));
40873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
40880a96aa3bSJed Brown }
40890a96aa3bSJed Brown
40900a96aa3bSJed Brown #define DMForestClearAdaptivityForest_pforest _append_pforest(DMForestClearAdaptivityForest)
DMForestClearAdaptivityForest_pforest(DM dm)4091d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestClearAdaptivityForest_pforest(DM dm)
4092d71ae5a4SJacob Faibussowitsch {
40930a96aa3bSJed Brown DM_Forest *forest;
40940a96aa3bSJed Brown DM_Forest_pforest *pforest;
40950a96aa3bSJed Brown
40960a96aa3bSJed Brown PetscFunctionBegin;
40970a96aa3bSJed Brown forest = (DM_Forest *)dm->data;
40980a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data;
4099f4f49eeaSPierre Jolivet PetscCall(PetscSFDestroy(&pforest->pointAdaptToSelfSF));
4100f4f49eeaSPierre Jolivet PetscCall(PetscSFDestroy(&pforest->pointSelfToAdaptSF));
41019566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointAdaptToSelfCids));
41029566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->pointSelfToAdaptCids));
41033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
41040a96aa3bSJed Brown }
41050a96aa3bSJed Brown
DMConvert_pforest_plex(DM dm,DMType newtype,DM * plex)4106d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMConvert_pforest_plex(DM dm, DMType newtype, DM *plex)
4107d71ae5a4SJacob Faibussowitsch {
41080a96aa3bSJed Brown DM_Forest *forest;
41090a96aa3bSJed Brown DM_Forest_pforest *pforest;
41100a96aa3bSJed Brown DM refTree, newPlex, base;
41110a96aa3bSJed Brown PetscInt adjDim, adjCodim, coordDim;
41120a96aa3bSJed Brown MPI_Comm comm;
41130a96aa3bSJed Brown PetscBool isPforest;
41140a96aa3bSJed Brown PetscInt dim;
41150a96aa3bSJed Brown PetscInt overlap;
41160a96aa3bSJed Brown p4est_connect_type_t ctype;
41170a96aa3bSJed Brown p4est_locidx_t first_local_quad = -1;
41180a96aa3bSJed Brown sc_array_t *points_per_dim, *cone_sizes, *cones, *cone_orientations, *coords, *children, *parents, *childids, *leaves, *remotes;
41190a96aa3bSJed Brown PetscSection parentSection;
41200a96aa3bSJed Brown PetscSF pointSF;
41210a96aa3bSJed Brown size_t zz, count;
41220a96aa3bSJed Brown PetscInt pStart, pEnd;
41230a96aa3bSJed Brown DMLabel ghostLabelBase = NULL;
41240a96aa3bSJed Brown
41250a96aa3bSJed Brown PetscFunctionBegin;
41260a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41270a96aa3bSJed Brown comm = PetscObjectComm((PetscObject)dm);
41289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPFOREST, &isPforest));
412928b400f6SJacob Faibussowitsch PetscCheck(isPforest, comm, PETSC_ERR_ARG_WRONG, "Expected DM type %s, got %s", DMPFOREST, ((PetscObject)dm)->type_name);
4130671c294aSToby Isaac PetscCall(DMSetUp(dm));
41319566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
413263a3b9bcSJacob Faibussowitsch PetscCheck(dim == P4EST_DIM, comm, PETSC_ERR_ARG_WRONG, "Expected DM dimension %d, got %" PetscInt_FMT, P4EST_DIM, dim);
41330a96aa3bSJed Brown forest = (DM_Forest *)dm->data;
41340a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data;
41359566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base));
413648a46eb9SPierre Jolivet if (base) PetscCall(DMGetLabel(base, "ghost", &ghostLabelBase));
41370a96aa3bSJed Brown if (!pforest->plex) {
41380a96aa3bSJed Brown PetscMPIInt size;
4139c7d28b7cSMatthew G. Knepley const char *name;
41400a96aa3bSJed Brown
41419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
41429566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &newPlex));
4143c7d28b7cSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name));
4144c7d28b7cSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)newPlex, name));
41459566063dSJacob Faibussowitsch PetscCall(DMSetType(newPlex, DMPLEX));
41469566063dSJacob Faibussowitsch PetscCall(DMSetMatType(newPlex, dm->mattype));
41470a96aa3bSJed Brown /* share labels */
41489566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dm, newPlex, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
41499566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyDimension(dm, &adjDim));
41509566063dSJacob Faibussowitsch PetscCall(DMForestGetAdjacencyCodimension(dm, &adjCodim));
41519566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim));
41520a96aa3bSJed Brown if (adjDim == 0) {
41530a96aa3bSJed Brown ctype = P4EST_CONNECT_FULL;
41540a96aa3bSJed Brown } else if (adjCodim == 1) {
41550a96aa3bSJed Brown ctype = P4EST_CONNECT_FACE;
41560a96aa3bSJed Brown #if defined(P4_TO_P8)
41570a96aa3bSJed Brown } else if (adjDim == 1) {
41580a96aa3bSJed Brown ctype = P8EST_CONNECT_EDGE;
41590a96aa3bSJed Brown #endif
41600a96aa3bSJed Brown } else {
416163a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid adjacency dimension %" PetscInt_FMT, adjDim);
41620a96aa3bSJed Brown }
416363a3b9bcSJacob Faibussowitsch PetscCheck(ctype == P4EST_CONNECT_FULL, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Adjacency dimension %" PetscInt_FMT " / codimension %" PetscInt_FMT " not supported yet", adjDim, adjCodim);
41649566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap));
416560667520SVaclav Hapla PetscCall(DMPlexSetOverlap_Plex(newPlex, NULL, overlap));
41660a96aa3bSJed Brown
41670a96aa3bSJed Brown points_per_dim = sc_array_new(sizeof(p4est_locidx_t));
41680a96aa3bSJed Brown cone_sizes = sc_array_new(sizeof(p4est_locidx_t));
41690a96aa3bSJed Brown cones = sc_array_new(sizeof(p4est_locidx_t));
41700a96aa3bSJed Brown cone_orientations = sc_array_new(sizeof(p4est_locidx_t));
41710a96aa3bSJed Brown coords = sc_array_new(3 * sizeof(double));
41720a96aa3bSJed Brown children = sc_array_new(sizeof(p4est_locidx_t));
41730a96aa3bSJed Brown parents = sc_array_new(sizeof(p4est_locidx_t));
41740a96aa3bSJed Brown childids = sc_array_new(sizeof(p4est_locidx_t));
41750a96aa3bSJed Brown leaves = sc_array_new(sizeof(p4est_locidx_t));
41760a96aa3bSJed Brown remotes = sc_array_new(2 * sizeof(p4est_locidx_t));
41770a96aa3bSJed Brown
4178792fecdfSBarry Smith PetscCallP4est(p4est_get_plex_data_ext, (pforest->forest, &pforest->ghost, &pforest->lnodes, ctype, (int)((size > 1) ? overlap : 0), &first_local_quad, points_per_dim, cone_sizes, cones, cone_orientations, coords, children, parents, childids, leaves, remotes, 1));
41790a96aa3bSJed Brown
41800a96aa3bSJed Brown pforest->cLocalStart = (PetscInt)first_local_quad;
41810a96aa3bSJed Brown pforest->cLocalEnd = pforest->cLocalStart + (PetscInt)pforest->forest->local_num_quadrants;
41829566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(points_per_dim));
41839566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_sizes));
41849566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cones));
41859566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(cone_orientations));
41869566063dSJacob Faibussowitsch PetscCall(coords_double_to_PetscScalar(coords, coordDim));
41879566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(children));
41889566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(parents));
41899566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(childids));
41909566063dSJacob Faibussowitsch PetscCall(locidx_to_PetscInt(leaves));
41919566063dSJacob Faibussowitsch PetscCall(locidx_pair_to_PetscSFNode(remotes));
41920a96aa3bSJed Brown
41939566063dSJacob Faibussowitsch PetscCall(DMSetDimension(newPlex, P4EST_DIM));
41949566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(newPlex, coordDim));
41959566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(newPlex, P4EST_DIM - 1));
41969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(newPlex, P4EST_DIM, (PetscInt *)points_per_dim->array, (PetscInt *)cone_sizes->array, (PetscInt *)cones->array, (PetscInt *)cone_orientations->array, (PetscScalar *)coords->array));
41979566063dSJacob Faibussowitsch PetscCall(DMPlexConvertOldOrientations_Internal(newPlex));
41989566063dSJacob Faibussowitsch PetscCall(DMCreateReferenceTree_pforest(comm, &refTree));
41999566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlex, refTree));
42009566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &parentSection));
42019566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(newPlex, &pStart, &pEnd));
42029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd));
42030a96aa3bSJed Brown count = children->elem_count;
42040a96aa3bSJed Brown for (zz = 0; zz < count; zz++) {
42050a96aa3bSJed Brown PetscInt child = *((PetscInt *)sc_array_index(children, zz));
42060a96aa3bSJed Brown
42079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(parentSection, child, 1));
42080a96aa3bSJed Brown }
42099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection));
42109566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(newPlex, parentSection, (PetscInt *)parents->array, (PetscInt *)childids->array));
42119566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection));
42129566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &pointSF));
42130a96aa3bSJed Brown /*
42140a96aa3bSJed Brown These arrays defining the sf are from the p4est library, but the code there shows the leaves being populated in increasing order.
42150a96aa3bSJed Brown https://gitlab.com/petsc/petsc/merge_requests/2248#note_240186391
42160a96aa3bSJed Brown */
42179566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(pointSF, pEnd - pStart, (PetscInt)leaves->elem_count, (PetscInt *)leaves->array, PETSC_COPY_VALUES, (PetscSFNode *)remotes->array, PETSC_COPY_VALUES));
42189566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(newPlex, pointSF));
42199566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF));
42200a96aa3bSJed Brown {
42210a96aa3bSJed Brown DM coordDM;
42220a96aa3bSJed Brown
42239566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex, &coordDM));
42249566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(coordDM, pointSF));
42250a96aa3bSJed Brown }
42269566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pointSF));
42270a96aa3bSJed Brown sc_array_destroy(points_per_dim);
42280a96aa3bSJed Brown sc_array_destroy(cone_sizes);
42290a96aa3bSJed Brown sc_array_destroy(cones);
42300a96aa3bSJed Brown sc_array_destroy(cone_orientations);
42310a96aa3bSJed Brown sc_array_destroy(coords);
42320a96aa3bSJed Brown sc_array_destroy(children);
42330a96aa3bSJed Brown sc_array_destroy(parents);
42340a96aa3bSJed Brown sc_array_destroy(childids);
42350a96aa3bSJed Brown sc_array_destroy(leaves);
42360a96aa3bSJed Brown sc_array_destroy(remotes);
42370a96aa3bSJed Brown
42380a96aa3bSJed Brown {
42394fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L;
42400a96aa3bSJed Brown
42414fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
42424fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(newPlex, maxCell, Lstart, L));
42439566063dSJacob Faibussowitsch PetscCall(DMPforestLocalizeCoordinates(dm, newPlex));
42440a96aa3bSJed Brown }
42450a96aa3bSJed Brown
42460a96aa3bSJed Brown if (overlap > 0) { /* the p4est routine can't set all of the coordinates in its routine if there is overlap */
42470a96aa3bSJed Brown Vec coordsGlobal, coordsLocal;
42480a96aa3bSJed Brown const PetscScalar *globalArray;
42490a96aa3bSJed Brown PetscScalar *localArray;
42500a96aa3bSJed Brown PetscSF coordSF;
42510a96aa3bSJed Brown DM coordDM;
42520a96aa3bSJed Brown
42539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex, &coordDM));
42549566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(coordDM, &coordSF));
42559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(newPlex, &coordsGlobal));
42569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coordsLocal));
42579566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordsGlobal, &globalArray));
42589566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordsLocal, &localArray));
42599566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coordSF, MPIU_SCALAR, globalArray, localArray, MPI_REPLACE));
42609566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coordSF, MPIU_SCALAR, globalArray, localArray, MPI_REPLACE));
42619566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordsLocal, &localArray));
42629566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordsGlobal, &globalArray));
42639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(newPlex, coordsLocal));
42640a96aa3bSJed Brown }
42659566063dSJacob Faibussowitsch PetscCall(DMPforestMapCoordinates(dm, newPlex));
42660a96aa3bSJed Brown
42670a96aa3bSJed Brown pforest->plex = newPlex;
42680a96aa3bSJed Brown
42690a96aa3bSJed Brown /* copy labels */
42709566063dSJacob Faibussowitsch PetscCall(DMPforestLabelsFinalize(dm, newPlex));
42710a96aa3bSJed Brown
42720a96aa3bSJed Brown if (ghostLabelBase || pforest->ghostName) { /* we have to do this after copying labels because the labels drive the construction of ghost cells */
42730a96aa3bSJed Brown PetscInt numAdded;
42740a96aa3bSJed Brown DM newPlexGhosted;
42750a96aa3bSJed Brown void *ctx;
42760a96aa3bSJed Brown
42779566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(newPlex, pforest->ghostName, &numAdded, &newPlexGhosted));
42789566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(newPlex, &ctx));
42799566063dSJacob Faibussowitsch PetscCall(DMSetApplicationContext(newPlexGhosted, ctx));
42800a96aa3bSJed Brown /* we want the sf for the ghost dm to be the one for the p4est dm as well */
42819566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(newPlexGhosted, &pointSF));
42829566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, pointSF));
42839566063dSJacob Faibussowitsch PetscCall(DMDestroy(&newPlex));
42849566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(newPlexGhosted, refTree));
42859566063dSJacob Faibussowitsch PetscCall(DMForestClearAdaptivityForest_pforest(dm));
42860a96aa3bSJed Brown newPlex = newPlexGhosted;
42870a96aa3bSJed Brown
42880a96aa3bSJed Brown /* share the labels back */
42899566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm));
42909566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(newPlex, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
42910a96aa3bSJed Brown pforest->plex = newPlex;
42920a96aa3bSJed Brown }
42939566063dSJacob Faibussowitsch PetscCall(DMDestroy(&refTree));
42940a96aa3bSJed Brown if (dm->setfromoptionscalled) {
4295d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)newPlex);
4296dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(newPlex, PetscOptionsObject));
4297dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)newPlex, PetscOptionsObject));
4298d0609cedSBarry Smith PetscOptionsEnd();
42990a96aa3bSJed Brown }
43009566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(newPlex, NULL, "-dm_p4est_plex_view"));
43010a96aa3bSJed Brown {
43026858538eSMatthew G. Knepley DM cdm;
43030a96aa3bSJed Brown PetscSection coordsSec;
43040a96aa3bSJed Brown Vec coords;
43050a96aa3bSJed Brown PetscInt cDim;
43060a96aa3bSJed Brown
43079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(newPlex, &cDim));
43089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(newPlex, &coordsSec));
43099566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dm, cDim, coordsSec));
43109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(newPlex, &coords));
43119566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords));
4312707c51c7SToby Isaac PetscCall(DMGetCoordinateDM(newPlex, &cdm));
4313707c51c7SToby Isaac if (cdm) {
4314707c51c7SToby Isaac PetscFE fe;
4315707c51c7SToby Isaac #if !defined(P4_TO_P8)
4316707c51c7SToby Isaac DMPolytopeType celltype = DM_POLYTOPE_QUADRILATERAL;
4317707c51c7SToby Isaac #else
4318707c51c7SToby Isaac DMPolytopeType celltype = DM_POLYTOPE_HEXAHEDRON;
4319707c51c7SToby Isaac #endif
4320707c51c7SToby Isaac
4321707c51c7SToby Isaac PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dim, celltype, 1, PETSC_DEFAULT, &fe));
4322707c51c7SToby Isaac PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe));
4323707c51c7SToby Isaac PetscCall(PetscFEDestroy(&fe));
4324707c51c7SToby Isaac PetscCall(DMCreateDS(cdm));
4325707c51c7SToby Isaac }
43266858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex, &cdm));
43276858538eSMatthew G. Knepley if (cdm) PetscCall(DMSetCellCoordinateDM(dm, cdm));
43286858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(newPlex, &coordsSec));
43296858538eSMatthew G. Knepley if (coordsSec) PetscCall(DMSetCellCoordinateSection(dm, cDim, coordsSec));
43306858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(newPlex, &coords));
43316858538eSMatthew G. Knepley if (coords) PetscCall(DMSetCellCoordinatesLocal(dm, coords));
43320a96aa3bSJed Brown }
4333cdf84abbSMatthew G. Knepley } else {
4334cdf84abbSMatthew G. Knepley PetscCall(DMCopyLabels(dm, pforest->plex, PETSC_OWN_POINTER, PETSC_FALSE, DM_COPY_LABELS_REPLACE));
43350a96aa3bSJed Brown }
43360a96aa3bSJed Brown newPlex = pforest->plex;
43370a96aa3bSJed Brown if (plex) {
43389566063dSJacob Faibussowitsch PetscCall(DMClone(newPlex, plex));
43396858538eSMatthew G. Knepley #if 0
43409566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(newPlex,&coordDM));
43419566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(*plex,coordDM));
43426858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(newPlex,&coordDM));
43436858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*plex,coordDM));
43446858538eSMatthew G. Knepley #endif
43459566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm, *plex));
43460a96aa3bSJed Brown }
43473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43480a96aa3bSJed Brown }
43490a96aa3bSJed Brown
DMSetFromOptions_pforest(DM dm,PetscOptionItems PetscOptionsObject)4350ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_pforest(DM dm, PetscOptionItems PetscOptionsObject)
4351d71ae5a4SJacob Faibussowitsch {
43520a96aa3bSJed Brown DM_Forest_pforest *pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data;
43530a96aa3bSJed Brown char stringBuffer[256];
43540a96aa3bSJed Brown PetscBool flg;
43550a96aa3bSJed Brown
43560a96aa3bSJed Brown PetscFunctionBegin;
4357dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Forest(dm, PetscOptionsObject));
4358d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DM" P4EST_STRING " options");
4359217f96c1SStefano Zampini PetscCall(PetscOptionsBool("-dm_p4est_partition_for_coarsening", "partition forest to allow for coarsening", "DMP4estSetPartitionForCoarsening", pforest->partition_for_coarsening, &pforest->partition_for_coarsening, NULL));
43609566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_p4est_ghost_label_name", "the name of the ghost label when converting from a DMPlex", NULL, NULL, stringBuffer, sizeof(stringBuffer), &flg));
4361d0609cedSBarry Smith PetscOptionsHeadEnd();
43620a96aa3bSJed Brown if (flg) {
43639566063dSJacob Faibussowitsch PetscCall(PetscFree(pforest->ghostName));
43649566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(stringBuffer, &pforest->ghostName));
43650a96aa3bSJed Brown }
43663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43670a96aa3bSJed Brown }
43680a96aa3bSJed Brown
43690a96aa3bSJed Brown #if !defined(P4_TO_P8)
43700a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP4estGetPartitionForCoarsening
43710a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP4estSetPartitionForCoarsening
43720a96aa3bSJed Brown #else
43730a96aa3bSJed Brown #define DMPforestGetPartitionForCoarsening DMP8estGetPartitionForCoarsening
43740a96aa3bSJed Brown #define DMPforestSetPartitionForCoarsening DMP8estSetPartitionForCoarsening
43750a96aa3bSJed Brown #endif
43760a96aa3bSJed Brown
DMPforestGetPartitionForCoarsening(DM dm,PetscBool * flg)4377d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMPforestGetPartitionForCoarsening(DM dm, PetscBool *flg)
4378d71ae5a4SJacob Faibussowitsch {
43790a96aa3bSJed Brown DM_Forest_pforest *pforest;
43800a96aa3bSJed Brown
43810a96aa3bSJed Brown PetscFunctionBegin;
43820a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
43830a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data;
43840a96aa3bSJed Brown *flg = pforest->partition_for_coarsening;
43853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43860a96aa3bSJed Brown }
43870a96aa3bSJed Brown
DMPforestSetPartitionForCoarsening(DM dm,PetscBool flg)4388d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMPforestSetPartitionForCoarsening(DM dm, PetscBool flg)
4389d71ae5a4SJacob Faibussowitsch {
43900a96aa3bSJed Brown DM_Forest_pforest *pforest;
43910a96aa3bSJed Brown
43920a96aa3bSJed Brown PetscFunctionBegin;
43930a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
43940a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data;
43950a96aa3bSJed Brown pforest->partition_for_coarsening = flg;
43963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43970a96aa3bSJed Brown }
43980a96aa3bSJed Brown
DMPforestGetPlex(DM dm,DM * plex)4399d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPforestGetPlex(DM dm, DM *plex)
4400d71ae5a4SJacob Faibussowitsch {
44010a96aa3bSJed Brown DM_Forest_pforest *pforest;
44020a96aa3bSJed Brown
44030a96aa3bSJed Brown PetscFunctionBegin;
44040a96aa3bSJed Brown if (plex) *plex = NULL;
44059566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm));
44060a96aa3bSJed Brown pforest = (DM_Forest_pforest *)((DM_Forest *)dm->data)->data;
440748a46eb9SPierre Jolivet if (!pforest->plex) PetscCall(DMConvert_pforest_plex(dm, DMPLEX, NULL));
44089566063dSJacob Faibussowitsch PetscCall(DMShareDiscretization(dm, pforest->plex));
44090a96aa3bSJed Brown if (plex) *plex = pforest->plex;
44103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
44110a96aa3bSJed Brown }
44120a96aa3bSJed Brown
44130a96aa3bSJed Brown #define DMCreateInterpolation_pforest _append_pforest(DMCreateInterpolation)
DMCreateInterpolation_pforest(DM dmCoarse,DM dmFine,Mat * interpolation,Vec * scaling)4414d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateInterpolation_pforest(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
4415d71ae5a4SJacob Faibussowitsch {
44160a96aa3bSJed Brown PetscSection gsc, gsf;
44170a96aa3bSJed Brown PetscInt m, n;
44180a96aa3bSJed Brown DM cdm;
44190a96aa3bSJed Brown
44200a96aa3bSJed Brown PetscFunctionBegin;
44219566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf));
44229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
44239566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
44249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
44250a96aa3bSJed Brown
44269566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmFine), interpolation));
44279566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
44289566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, MATAIJ));
44290a96aa3bSJed Brown
44309566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm));
443108401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse, PetscObjectComm((PetscObject)dmFine), PETSC_ERR_SUP, "Only interpolation from coarse DM for now");
44320a96aa3bSJed Brown
44330a96aa3bSJed Brown {
44340a96aa3bSJed Brown DM plexF, plexC;
44350a96aa3bSJed Brown PetscSF sf;
44360a96aa3bSJed Brown PetscInt *cids;
44370a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1};
44380a96aa3bSJed Brown
44399566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse, &plexC));
44409566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine, &plexF));
44419566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids));
44429566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf));
44439566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInterpolatorTree(plexC, plexF, sf, cids, *interpolation));
44449566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf));
44459566063dSJacob Faibussowitsch PetscCall(PetscFree(cids));
44460a96aa3bSJed Brown }
44479566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
44480a96aa3bSJed Brown /* Use naive scaling */
44499566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
44503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
44510a96aa3bSJed Brown }
44520a96aa3bSJed Brown
44530a96aa3bSJed Brown #define DMCreateInjection_pforest _append_pforest(DMCreateInjection)
DMCreateInjection_pforest(DM dmCoarse,DM dmFine,Mat * injection)4454d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateInjection_pforest(DM dmCoarse, DM dmFine, Mat *injection)
4455d71ae5a4SJacob Faibussowitsch {
44560a96aa3bSJed Brown PetscSection gsc, gsf;
44570a96aa3bSJed Brown PetscInt m, n;
44580a96aa3bSJed Brown DM cdm;
44590a96aa3bSJed Brown
44600a96aa3bSJed Brown PetscFunctionBegin;
44619566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf));
44629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &n));
44639566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
44649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &m));
44650a96aa3bSJed Brown
44669566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmFine), injection));
44679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*injection, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
44689566063dSJacob Faibussowitsch PetscCall(MatSetType(*injection, MATAIJ));
44690a96aa3bSJed Brown
44709566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm));
447108401ef6SPierre Jolivet PetscCheck(cdm == dmCoarse, PetscObjectComm((PetscObject)dmFine), PETSC_ERR_SUP, "Only injection to coarse DM for now");
44720a96aa3bSJed Brown
44730a96aa3bSJed Brown {
44740a96aa3bSJed Brown DM plexF, plexC;
44750a96aa3bSJed Brown PetscSF sf;
44760a96aa3bSJed Brown PetscInt *cids;
44770a96aa3bSJed Brown PetscInt dofPerDim[4] = {1, 1, 1, 1};
44780a96aa3bSJed Brown
44799566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmCoarse, &plexC));
44809566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmFine, &plexF));
44819566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmCoarse, dmFine, dofPerDim, &sf, PETSC_TRUE, &cids));
44829566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf));
44839566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorTree(plexC, plexF, sf, cids, *injection));
44849566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf));
44859566063dSJacob Faibussowitsch PetscCall(PetscFree(cids));
44860a96aa3bSJed Brown }
44879566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*injection, NULL, "-inject_mat_view"));
44880a96aa3bSJed Brown /* Use naive scaling */
44893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
44900a96aa3bSJed Brown }
44910a96aa3bSJed Brown
44920a96aa3bSJed Brown #define DMForestTransferVecFromBase_pforest _append_pforest(DMForestTransferVecFromBase)
DMForestTransferVecFromBase_pforest(DM dm,Vec vecIn,Vec vecOut)4493d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestTransferVecFromBase_pforest(DM dm, Vec vecIn, Vec vecOut)
4494d71ae5a4SJacob Faibussowitsch {
44950a96aa3bSJed Brown DM dmIn, dmVecIn, base, basec, plex, coarseDM;
44960a96aa3bSJed Brown DM *hierarchy;
44970a96aa3bSJed Brown PetscSF sfRed = NULL;
44980a96aa3bSJed Brown PetscDS ds;
44990a96aa3bSJed Brown Vec vecInLocal, vecOutLocal;
45000a96aa3bSJed Brown DMLabel subpointMap;
45010a96aa3bSJed Brown PetscInt minLevel, mh, n_hi, i;
45020a96aa3bSJed Brown PetscBool hiforest, *hierarchy_forest;
45030a96aa3bSJed Brown
45040a96aa3bSJed Brown PetscFunctionBegin;
45059566063dSJacob Faibussowitsch PetscCall(VecGetDM(vecIn, &dmVecIn));
45069566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmVecIn, &ds));
450728b400f6SJacob Faibussowitsch PetscCheck(ds, PetscObjectComm((PetscObject)dmVecIn), PETSC_ERR_SUP, "Cannot transfer without a PetscDS object");
45080a96aa3bSJed Brown { /* we cannot stick user contexts into function callbacks for DMProjectFieldLocal! */
45090a96aa3bSJed Brown PetscSection section;
45100a96aa3bSJed Brown PetscInt Nf;
45110a96aa3bSJed Brown
45129566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn, §ion));
45139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf));
451463a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 3, PetscObjectComm((PetscObject)dmVecIn), PETSC_ERR_SUP, "Number of fields %" PetscInt_FMT " are currently not supported! Send an email at petsc-dev@mcs.anl.gov", Nf);
45150a96aa3bSJed Brown }
45169566063dSJacob Faibussowitsch PetscCall(DMForestGetMinimumRefinement(dm, &minLevel));
451763a3b9bcSJacob Faibussowitsch PetscCheck(!minLevel, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot transfer with minimum refinement set to %" PetscInt_FMT ". Rerun with DMForestSetMinimumRefinement(dm,0)", minLevel);
45189566063dSJacob Faibussowitsch PetscCall(DMForestGetBaseDM(dm, &base));
451928b400f6SJacob Faibussowitsch PetscCheck(base, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing base DM");
45200a96aa3bSJed Brown
45219566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0));
45220a96aa3bSJed Brown if (dmVecIn == base) { /* sequential runs */
45239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn));
45240a96aa3bSJed Brown } else {
45250a96aa3bSJed Brown PetscSection secIn, secInRed;
45260a96aa3bSJed Brown Vec vecInRed, vecInLocal;
45270a96aa3bSJed Brown
45289566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)base, "_base_migration_sf", (PetscObject *)&sfRed));
452928b400f6SJacob Faibussowitsch PetscCheck(sfRed, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not the DM set with DMForestSetBaseDM()");
45309566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmVecIn), &secInRed));
45319566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &vecInRed));
45329566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmVecIn, &secIn));
45339566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmVecIn, &vecInLocal));
45349566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmVecIn, vecIn, INSERT_VALUES, vecInLocal));
45359566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmVecIn, vecIn, INSERT_VALUES, vecInLocal));
45369566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeField(dmVecIn, sfRed, secIn, vecInLocal, secInRed, vecInRed));
45379566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmVecIn, &vecInLocal));
45389566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secInRed));
45390a96aa3bSJed Brown vecIn = vecInRed;
45400a96aa3bSJed Brown }
45410a96aa3bSJed Brown
45420a96aa3bSJed Brown /* we first search through the AdaptivityForest hierarchy
45430a96aa3bSJed Brown once we found the first disconnected forest, we upsweep the DM hierarchy */
45440a96aa3bSJed Brown hiforest = PETSC_TRUE;
45450a96aa3bSJed Brown
45460a96aa3bSJed Brown /* upsweep to the coarsest DM */
45470a96aa3bSJed Brown n_hi = 0;
45480a96aa3bSJed Brown coarseDM = dm;
45490a96aa3bSJed Brown do {
45500a96aa3bSJed Brown PetscBool isforest;
45510a96aa3bSJed Brown
45520a96aa3bSJed Brown dmIn = coarseDM;
45530a96aa3bSJed Brown /* need to call DMSetUp to have the hierarchy recursively setup */
45549566063dSJacob Faibussowitsch PetscCall(DMSetUp(dmIn));
45559566063dSJacob Faibussowitsch PetscCall(DMIsForest(dmIn, &isforest));
455628b400f6SJacob Faibussowitsch PetscCheck(isforest, PetscObjectComm((PetscObject)dmIn), PETSC_ERR_SUP, "Cannot currently transfer through a mixed hierarchy! Found DM type %s", ((PetscObject)dmIn)->type_name);
45570a96aa3bSJed Brown coarseDM = NULL;
455848a46eb9SPierre Jolivet if (hiforest) PetscCall(DMForestGetAdaptivityForest(dmIn, &coarseDM));
45590a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */
45600a96aa3bSJed Brown hiforest = PETSC_FALSE;
45619566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn, &coarseDM));
45620a96aa3bSJed Brown }
45630a96aa3bSJed Brown n_hi++;
45640a96aa3bSJed Brown } while (coarseDM);
45650a96aa3bSJed Brown
45669566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n_hi, &hierarchy, n_hi, &hierarchy_forest));
45670a96aa3bSJed Brown
45680a96aa3bSJed Brown i = 0;
45690a96aa3bSJed Brown hiforest = PETSC_TRUE;
45700a96aa3bSJed Brown coarseDM = dm;
45710a96aa3bSJed Brown do {
45720a96aa3bSJed Brown dmIn = coarseDM;
45730a96aa3bSJed Brown coarseDM = NULL;
457448a46eb9SPierre Jolivet if (hiforest) PetscCall(DMForestGetAdaptivityForest(dmIn, &coarseDM));
45750a96aa3bSJed Brown if (!coarseDM) { /* DMForest hierarchy ended, we keep upsweeping through the DM hierarchy */
45760a96aa3bSJed Brown hiforest = PETSC_FALSE;
45779566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmIn, &coarseDM));
45780a96aa3bSJed Brown }
45790a96aa3bSJed Brown i++;
45800a96aa3bSJed Brown hierarchy[n_hi - i] = dmIn;
45810a96aa3bSJed Brown } while (coarseDM);
45820a96aa3bSJed Brown
45830a96aa3bSJed Brown /* project base vector on the coarsest forest (minimum refinement = 0) */
45849566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn, &plex));
45850a96aa3bSJed Brown
45860a96aa3bSJed Brown /* Check this plex is compatible with the base */
45870a96aa3bSJed Brown {
45880a96aa3bSJed Brown IS gnum[2];
45890a96aa3bSJed Brown PetscInt ncells[2], gncells[2];
45900a96aa3bSJed Brown
45919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(base, &gnum[0]));
45929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(plex, &gnum[1]));
45939566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[0], NULL, &ncells[0]));
45949566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(gnum[1], NULL, &ncells[1]));
4595462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(ncells, gncells, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
459663a3b9bcSJacob Faibussowitsch PetscCheck(gncells[0] == gncells[1], PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Invalid number of base cells! Expected %" PetscInt_FMT ", found %" PetscInt_FMT, gncells[0] + 1, gncells[1] + 1);
45970a96aa3bSJed Brown }
45980a96aa3bSJed Brown
45999566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmIn, "_forest_base_subpoint_map", &subpointMap));
460028b400f6SJacob Faibussowitsch PetscCheck(subpointMap, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing _forest_base_subpoint_map label");
46010a96aa3bSJed Brown
46029566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(base, &mh));
46039566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(plex, mh));
46040a96aa3bSJed Brown
46059566063dSJacob Faibussowitsch PetscCall(DMClone(base, &basec));
46069566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmVecIn, basec));
46070a96aa3bSJed Brown if (sfRed) {
46089566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vecIn));
46090a96aa3bSJed Brown vecInLocal = vecIn;
46100a96aa3bSJed Brown } else {
46119566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(basec, &vecInLocal));
46129566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(basec, vecIn, INSERT_VALUES, vecInLocal));
46139566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(basec, vecIn, INSERT_VALUES, vecInLocal));
46140a96aa3bSJed Brown }
46150a96aa3bSJed Brown
46169566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecOutLocal));
46170a96aa3bSJed Brown { /* get degrees of freedom ordered onto dmIn */
46180a96aa3bSJed Brown PetscSF basetocoarse;
46190a96aa3bSJed Brown PetscInt bStart, bEnd, nroots;
46200a96aa3bSJed Brown PetscInt iStart, iEnd, nleaves, leaf;
46210a96aa3bSJed Brown PetscMPIInt rank;
46220a96aa3bSJed Brown PetscSFNode *remotes;
46230a96aa3bSJed Brown PetscSection secIn, secOut;
46240a96aa3bSJed Brown PetscInt *remoteOffsets;
46250a96aa3bSJed Brown PetscSF transferSF;
46260a96aa3bSJed Brown const PetscScalar *inArray;
46270a96aa3bSJed Brown PetscScalar *outArray;
46280a96aa3bSJed Brown
46299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)basec), &rank));
46309566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(basec, &bStart, &bEnd));
46310a96aa3bSJed Brown nroots = PetscMax(bEnd - bStart, 0);
46329566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plex, &iStart, &iEnd));
46330a96aa3bSJed Brown nleaves = PetscMax(iEnd - iStart, 0);
46340a96aa3bSJed Brown
46359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleaves, &remotes));
46360a96aa3bSJed Brown for (leaf = iStart; leaf < iEnd; leaf++) {
46370a96aa3bSJed Brown PetscInt index;
46380a96aa3bSJed Brown
46390a96aa3bSJed Brown remotes[leaf - iStart].rank = rank;
46409566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, leaf, &index));
46410a96aa3bSJed Brown remotes[leaf - iStart].index = index;
46420a96aa3bSJed Brown }
46430a96aa3bSJed Brown
46449566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)basec), &basetocoarse));
46459566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(basetocoarse, nroots, nleaves, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER));
46469566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(basetocoarse));
46479566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(basec, &secIn));
46489566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmIn), &secOut));
46499566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(basetocoarse, secIn, &remoteOffsets, secOut));
46509566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(basetocoarse, secIn, remoteOffsets, secOut, &transferSF));
46519566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets));
46529566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(vecOutLocal, &outArray));
46539566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecInLocal, &inArray));
46549566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(transferSF, MPIU_SCALAR, inArray, outArray, MPI_REPLACE));
46559566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(transferSF, MPIU_SCALAR, inArray, outArray, MPI_REPLACE));
46569566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecInLocal, &inArray));
46579566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(vecOutLocal, &outArray));
46589566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&transferSF));
46599566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secOut));
46609566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&basetocoarse));
46610a96aa3bSJed Brown }
46629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecInLocal));
46639566063dSJacob Faibussowitsch PetscCall(DMDestroy(&basec));
46649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vecIn));
46650a96aa3bSJed Brown
46660a96aa3bSJed Brown /* output */
46670a96aa3bSJed Brown if (n_hi > 1) { /* downsweep the stored hierarchy */
46680a96aa3bSJed Brown Vec vecOut1, vecOut2;
46690a96aa3bSJed Brown DM fineDM;
46700a96aa3bSJed Brown
46719566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmIn, &vecOut1));
46729566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn, vecOutLocal, INSERT_VALUES, vecOut1));
46739566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecOutLocal));
46740a96aa3bSJed Brown for (i = 1; i < n_hi - 1; i++) {
46750a96aa3bSJed Brown fineDM = hierarchy[i];
46769566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(fineDM, &vecOut2));
46779566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn, vecOut1, fineDM, vecOut2, PETSC_TRUE, 0.0));
46789566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn, &vecOut1));
46790a96aa3bSJed Brown vecOut1 = vecOut2;
46800a96aa3bSJed Brown dmIn = fineDM;
46810a96aa3bSJed Brown }
46829566063dSJacob Faibussowitsch PetscCall(DMForestTransferVec(dmIn, vecOut1, dm, vecOut, PETSC_TRUE, 0.0));
46839566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmIn, &vecOut1));
46840a96aa3bSJed Brown } else {
46859566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobal(dmIn, vecOutLocal, INSERT_VALUES, vecOut));
46869566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecOutLocal));
46870a96aa3bSJed Brown }
46889566063dSJacob Faibussowitsch PetscCall(PetscFree2(hierarchy, hierarchy_forest));
46893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
46900a96aa3bSJed Brown }
46910a96aa3bSJed Brown
46920a96aa3bSJed Brown #define DMForestTransferVec_pforest _append_pforest(DMForestTransferVec)
DMForestTransferVec_pforest(DM dmIn,Vec vecIn,DM dmOut,Vec vecOut,PetscBool useBCs,PetscReal time)4693d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestTransferVec_pforest(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time)
4694d71ae5a4SJacob Faibussowitsch {
46950a96aa3bSJed Brown DM adaptIn, adaptOut, plexIn, plexOut;
46960a96aa3bSJed Brown DM_Forest *forestIn, *forestOut, *forestAdaptIn, *forestAdaptOut;
46970a96aa3bSJed Brown PetscInt dofPerDim[] = {1, 1, 1, 1};
46980a96aa3bSJed Brown PetscSF inSF = NULL, outSF = NULL;
46990a96aa3bSJed Brown PetscInt *inCids = NULL, *outCids = NULL;
47000a96aa3bSJed Brown DMAdaptFlag purposeIn, purposeOut;
47010a96aa3bSJed Brown
47020a96aa3bSJed Brown PetscFunctionBegin;
47030a96aa3bSJed Brown forestOut = (DM_Forest *)dmOut->data;
47040a96aa3bSJed Brown forestIn = (DM_Forest *)dmIn->data;
47050a96aa3bSJed Brown
47069566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmOut, &adaptOut));
47079566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmOut, &purposeOut));
47080a96aa3bSJed Brown forestAdaptOut = adaptOut ? (DM_Forest *)adaptOut->data : NULL;
47090a96aa3bSJed Brown
47109566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityForest(dmIn, &adaptIn));
47119566063dSJacob Faibussowitsch PetscCall(DMForestGetAdaptivityPurpose(dmIn, &purposeIn));
47120a96aa3bSJed Brown forestAdaptIn = adaptIn ? (DM_Forest *)adaptIn->data : NULL;
47130a96aa3bSJed Brown
47140a96aa3bSJed Brown if (forestAdaptOut == forestIn) {
47150a96aa3bSJed Brown switch (purposeOut) {
47160a96aa3bSJed Brown case DM_ADAPT_REFINE:
47179566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids));
47189566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF));
47190a96aa3bSJed Brown break;
47200a96aa3bSJed Brown case DM_ADAPT_COARSEN:
47210a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST:
47229566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_TRUE, &outCids));
47239566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF));
47240a96aa3bSJed Brown break;
47250a96aa3bSJed Brown default:
47269566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids));
47279566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_FALSE, &outCids));
47289566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF));
47299566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF));
47300a96aa3bSJed Brown }
47310a96aa3bSJed Brown } else if (forestAdaptIn == forestOut) {
47320a96aa3bSJed Brown switch (purposeIn) {
47330a96aa3bSJed Brown case DM_ADAPT_REFINE:
47349566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_TRUE, &inCids));
47359566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF));
47360a96aa3bSJed Brown break;
47370a96aa3bSJed Brown case DM_ADAPT_COARSEN:
47380a96aa3bSJed Brown case DM_ADAPT_COARSEN_LAST:
47399566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids));
47409566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF));
47410a96aa3bSJed Brown break;
47420a96aa3bSJed Brown default:
47439566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmIn, dmOut, dofPerDim, &inSF, PETSC_TRUE, &inCids));
47449566063dSJacob Faibussowitsch PetscCall(DMPforestGetTransferSF_Internal(dmOut, dmIn, dofPerDim, &outSF, PETSC_FALSE, &outCids));
47459566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(inSF));
47469566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(outSF));
47470a96aa3bSJed Brown }
47480a96aa3bSJed Brown } else SETERRQ(PetscObjectComm((PetscObject)dmIn), PETSC_ERR_SUP, "Only support transfer from pre-adaptivity to post-adaptivity right now");
47499566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmIn, &plexIn));
47509566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dmOut, &plexOut));
47510a96aa3bSJed Brown
47529566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree(plexIn, vecIn, plexOut, vecOut, inSF, outSF, inCids, outCids, useBCs, time));
47539566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids));
47549566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids));
47559566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&inSF));
47569566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&outSF));
47579566063dSJacob Faibussowitsch PetscCall(PetscFree(inCids));
47589566063dSJacob Faibussowitsch PetscCall(PetscFree(outCids));
47593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
47600a96aa3bSJed Brown }
47610a96aa3bSJed Brown
47620a96aa3bSJed Brown #define DMCreateCoordinateDM_pforest _append_pforest(DMCreateCoordinateDM)
DMCreateCoordinateDM_pforest(DM dm,DM * cdm)4763d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateCoordinateDM_pforest(DM dm, DM *cdm)
4764d71ae5a4SJacob Faibussowitsch {
47650a96aa3bSJed Brown DM plex;
47660a96aa3bSJed Brown
47670a96aa3bSJed Brown PetscFunctionBegin;
47680a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47699566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
47709566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(plex, cdm));
47719566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*cdm));
47723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
47730a96aa3bSJed Brown }
47740a96aa3bSJed Brown
47750a96aa3bSJed Brown #define VecViewLocal_pforest _append_pforest(VecViewLocal)
VecViewLocal_pforest(Vec vec,PetscViewer viewer)4776d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecViewLocal_pforest(Vec vec, PetscViewer viewer)
4777d71ae5a4SJacob Faibussowitsch {
47780a96aa3bSJed Brown DM dm, plex;
47790a96aa3bSJed Brown
47800a96aa3bSJed Brown PetscFunctionBegin;
47819566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm));
4782217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm));
47839566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
47849566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex));
47859566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(vec, viewer));
47869566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm));
4787217f96c1SStefano Zampini PetscCall(DMDestroy(&dm));
47883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
47890a96aa3bSJed Brown }
47900a96aa3bSJed Brown
47910a96aa3bSJed Brown #define VecView_pforest _append_pforest(VecView)
VecView_pforest(Vec vec,PetscViewer viewer)4792d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_pforest(Vec vec, PetscViewer viewer)
4793d71ae5a4SJacob Faibussowitsch {
47940a96aa3bSJed Brown DM dm, plex;
47950a96aa3bSJed Brown
47960a96aa3bSJed Brown PetscFunctionBegin;
47979566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm));
4798217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm));
47999566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
48009566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex));
48019566063dSJacob Faibussowitsch PetscCall(VecView_Plex(vec, viewer));
48029566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm));
4803217f96c1SStefano Zampini PetscCall(DMDestroy(&dm));
48043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48050a96aa3bSJed Brown }
48060a96aa3bSJed Brown
48070a96aa3bSJed Brown #define VecView_pforest_Native _infix_pforest(VecView, _Native)
VecView_pforest_Native(Vec vec,PetscViewer viewer)4808d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_pforest_Native(Vec vec, PetscViewer viewer)
4809d71ae5a4SJacob Faibussowitsch {
48100a96aa3bSJed Brown DM dm, plex;
48110a96aa3bSJed Brown
48120a96aa3bSJed Brown PetscFunctionBegin;
48139566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm));
4814217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm));
48159566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
48169566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex));
48179566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Native(vec, viewer));
48189566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm));
4819217f96c1SStefano Zampini PetscCall(DMDestroy(&dm));
48203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48210a96aa3bSJed Brown }
48220a96aa3bSJed Brown
48230a96aa3bSJed Brown #define VecLoad_pforest _append_pforest(VecLoad)
VecLoad_pforest(Vec vec,PetscViewer viewer)4824d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecLoad_pforest(Vec vec, PetscViewer viewer)
4825d71ae5a4SJacob Faibussowitsch {
48260a96aa3bSJed Brown DM dm, plex;
48270a96aa3bSJed Brown
48280a96aa3bSJed Brown PetscFunctionBegin;
48299566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm));
4830217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm));
48319566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
48329566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex));
48339566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex(vec, viewer));
48349566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm));
4835217f96c1SStefano Zampini PetscCall(DMDestroy(&dm));
48363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48370a96aa3bSJed Brown }
48380a96aa3bSJed Brown
48390a96aa3bSJed Brown #define VecLoad_pforest_Native _infix_pforest(VecLoad, _Native)
VecLoad_pforest_Native(Vec vec,PetscViewer viewer)4840d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecLoad_pforest_Native(Vec vec, PetscViewer viewer)
4841d71ae5a4SJacob Faibussowitsch {
48420a96aa3bSJed Brown DM dm, plex;
48430a96aa3bSJed Brown
48440a96aa3bSJed Brown PetscFunctionBegin;
48459566063dSJacob Faibussowitsch PetscCall(VecGetDM(vec, &dm));
4846217f96c1SStefano Zampini PetscCall(PetscObjectReference((PetscObject)dm));
48479566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
48489566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, plex));
48499566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_Native(vec, viewer));
48509566063dSJacob Faibussowitsch PetscCall(VecSetDM(vec, dm));
4851217f96c1SStefano Zampini PetscCall(DMDestroy(&dm));
48523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48530a96aa3bSJed Brown }
48540a96aa3bSJed Brown
48550a96aa3bSJed Brown #define DMCreateGlobalVector_pforest _append_pforest(DMCreateGlobalVector)
DMCreateGlobalVector_pforest(DM dm,Vec * vec)4856d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_pforest(DM dm, Vec *vec)
4857d71ae5a4SJacob Faibussowitsch {
48580a96aa3bSJed Brown PetscFunctionBegin;
48599566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
48609566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
486157d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_VIEW, (PetscErrorCodeFn *)VecView_pforest));
486257d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (PetscErrorCodeFn *)VecView_pforest_Native));
486357d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_LOAD, (PetscErrorCodeFn *)VecLoad_pforest));
486457d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (PetscErrorCodeFn *)VecLoad_pforest_Native));
48653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48660a96aa3bSJed Brown }
48670a96aa3bSJed Brown
48680a96aa3bSJed Brown #define DMCreateLocalVector_pforest _append_pforest(DMCreateLocalVector)
DMCreateLocalVector_pforest(DM dm,Vec * vec)4869d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_pforest(DM dm, Vec *vec)
4870d71ae5a4SJacob Faibussowitsch {
48710a96aa3bSJed Brown PetscFunctionBegin;
48729566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
487357d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_VIEW, (PetscErrorCodeFn *)VecViewLocal_pforest));
48743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48750a96aa3bSJed Brown }
48760a96aa3bSJed Brown
48770a96aa3bSJed Brown #define DMCreateMatrix_pforest _append_pforest(DMCreateMatrix)
DMCreateMatrix_pforest(DM dm,Mat * mat)4878d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_pforest(DM dm, Mat *mat)
4879d71ae5a4SJacob Faibussowitsch {
48800a96aa3bSJed Brown DM plex;
48810a96aa3bSJed Brown
48820a96aa3bSJed Brown PetscFunctionBegin;
48830a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48849566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
48850a96aa3bSJed Brown if (plex->prealloc_only != dm->prealloc_only) plex->prealloc_only = dm->prealloc_only; /* maybe this should go into forest->plex */
48862495aca6SStefano Zampini PetscCall(DMSetMatType(plex, dm->mattype));
48879566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(plex, mat));
48889566063dSJacob Faibussowitsch PetscCall(MatSetDM(*mat, dm));
48893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48900a96aa3bSJed Brown }
48910a96aa3bSJed Brown
48920a96aa3bSJed Brown #define DMProjectFunctionLocal_pforest _append_pforest(DMProjectFunctionLocal)
DMProjectFunctionLocal_pforest(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,InsertMode mode,Vec localX)4893d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMProjectFunctionLocal_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
4894d71ae5a4SJacob Faibussowitsch {
48950a96aa3bSJed Brown DM plex;
48960a96aa3bSJed Brown
48970a96aa3bSJed Brown PetscFunctionBegin;
48980a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48999566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
49009566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLocal(plex, time, funcs, ctxs, mode, localX));
49013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49020a96aa3bSJed Brown }
49030a96aa3bSJed Brown
49040a96aa3bSJed Brown #define DMProjectFunctionLabelLocal_pforest _append_pforest(DMProjectFunctionLabelLocal)
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)4905d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMProjectFunctionLabelLocal_pforest(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
4906d71ae5a4SJacob Faibussowitsch {
49070a96aa3bSJed Brown DM plex;
49080a96aa3bSJed Brown
49090a96aa3bSJed Brown PetscFunctionBegin;
49100a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49119566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
49129566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLabelLocal(plex, time, label, numIds, ids, Ncc, comps, funcs, ctxs, mode, localX));
49133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49140a96aa3bSJed Brown }
49150a96aa3bSJed Brown
49160a96aa3bSJed Brown #define DMProjectFieldLocal_pforest _append_pforest(DMProjectFieldLocal)
DMProjectFieldLocal_pforest(DM dm,PetscReal time,Vec localU,void (** funcs)(PetscInt,PetscInt,PetscInt,const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],PetscReal,const PetscReal[],PetscInt,const PetscScalar[],PetscScalar[]),InsertMode mode,Vec localX)4917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFieldLocal_pforest(DM dm, PetscReal time, Vec localU, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), InsertMode mode, Vec localX)
4918d71ae5a4SJacob Faibussowitsch {
49190a96aa3bSJed Brown DM plex;
49200a96aa3bSJed Brown
49210a96aa3bSJed Brown PetscFunctionBegin;
49220a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49239566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
49249566063dSJacob Faibussowitsch PetscCall(DMProjectFieldLocal(plex, time, localU, funcs, mode, localX));
49253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49260a96aa3bSJed Brown }
49270a96aa3bSJed Brown
49280a96aa3bSJed Brown #define DMComputeL2Diff_pforest _append_pforest(DMComputeL2Diff)
DMComputeL2Diff_pforest(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec X,PetscReal * diff)4929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
4930d71ae5a4SJacob Faibussowitsch {
49310a96aa3bSJed Brown DM plex;
49320a96aa3bSJed Brown
49330a96aa3bSJed Brown PetscFunctionBegin;
49340a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49359566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
49369566063dSJacob Faibussowitsch PetscCall(DMComputeL2Diff(plex, time, funcs, ctxs, X, diff));
49373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49380a96aa3bSJed Brown }
49390a96aa3bSJed Brown
49400a96aa3bSJed Brown #define DMComputeL2FieldDiff_pforest _append_pforest(DMComputeL2FieldDiff)
DMComputeL2FieldDiff_pforest(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec X,PetscReal diff[])4941d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff_pforest(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
4942d71ae5a4SJacob Faibussowitsch {
49430a96aa3bSJed Brown DM plex;
49440a96aa3bSJed Brown
49450a96aa3bSJed Brown PetscFunctionBegin;
49460a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49479566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
49489566063dSJacob Faibussowitsch PetscCall(DMComputeL2FieldDiff(plex, time, funcs, ctxs, X, diff));
49493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49500a96aa3bSJed Brown }
49510a96aa3bSJed Brown
49520a96aa3bSJed Brown #define DMCreatelocalsection_pforest _append_pforest(DMCreatelocalsection)
DMCreatelocalsection_pforest(DM dm)4953d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreatelocalsection_pforest(DM dm)
4954d71ae5a4SJacob Faibussowitsch {
49550a96aa3bSJed Brown DM plex;
49560a96aa3bSJed Brown PetscSection section;
49570a96aa3bSJed Brown
49580a96aa3bSJed Brown PetscFunctionBegin;
49590a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49609566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
49619566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(plex, §ion));
49629566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(dm, section));
49633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49640a96aa3bSJed Brown }
49650a96aa3bSJed Brown
49660a96aa3bSJed Brown #define DMCreateDefaultConstraints_pforest _append_pforest(DMCreateDefaultConstraints)
DMCreateDefaultConstraints_pforest(DM dm)4967d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateDefaultConstraints_pforest(DM dm)
4968d71ae5a4SJacob Faibussowitsch {
49690a96aa3bSJed Brown DM plex;
49700a96aa3bSJed Brown Mat mat;
497179769bd5SJed Brown Vec bias;
49720a96aa3bSJed Brown PetscSection section;
49730a96aa3bSJed Brown
49740a96aa3bSJed Brown PetscFunctionBegin;
49750a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49769566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
49779566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(plex, §ion, &mat, &bias));
49789566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, section, mat, bias));
49793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49800a96aa3bSJed Brown }
49810a96aa3bSJed Brown
49820a96aa3bSJed Brown #define DMGetDimPoints_pforest _append_pforest(DMGetDimPoints)
DMGetDimPoints_pforest(DM dm,PetscInt dim,PetscInt * cStart,PetscInt * cEnd)4983d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_pforest(DM dm, PetscInt dim, PetscInt *cStart, PetscInt *cEnd)
4984d71ae5a4SJacob Faibussowitsch {
49850a96aa3bSJed Brown DM plex;
49860a96aa3bSJed Brown
49870a96aa3bSJed Brown PetscFunctionBegin;
49880a96aa3bSJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49899566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
49909566063dSJacob Faibussowitsch PetscCall(DMGetDimPoints(plex, dim, cStart, cEnd));
49913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
49920a96aa3bSJed Brown }
49930a96aa3bSJed Brown
49940a96aa3bSJed Brown /* Need to forward declare */
49950a96aa3bSJed Brown #define DMInitialize_pforest _append_pforest(DMInitialize)
49960a96aa3bSJed Brown static PetscErrorCode DMInitialize_pforest(DM dm);
49970a96aa3bSJed Brown
49980a96aa3bSJed Brown #define DMClone_pforest _append_pforest(DMClone)
DMClone_pforest(DM dm,DM * newdm)4999d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMClone_pforest(DM dm, DM *newdm)
5000d71ae5a4SJacob Faibussowitsch {
50010a96aa3bSJed Brown PetscFunctionBegin;
50029566063dSJacob Faibussowitsch PetscCall(DMClone_Forest(dm, newdm));
50039566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(*newdm));
50043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50050a96aa3bSJed Brown }
50060a96aa3bSJed Brown
50070a96aa3bSJed Brown #define DMForestCreateCellChart_pforest _append_pforest(DMForestCreateCellChart)
DMForestCreateCellChart_pforest(DM dm,PetscInt * cStart,PetscInt * cEnd)5008d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestCreateCellChart_pforest(DM dm, PetscInt *cStart, PetscInt *cEnd)
5009d71ae5a4SJacob Faibussowitsch {
50100a96aa3bSJed Brown DM_Forest *forest;
50110a96aa3bSJed Brown DM_Forest_pforest *pforest;
50120a96aa3bSJed Brown PetscInt overlap;
50130a96aa3bSJed Brown
50140a96aa3bSJed Brown PetscFunctionBegin;
50159566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm));
50160a96aa3bSJed Brown forest = (DM_Forest *)dm->data;
50170a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data;
50180a96aa3bSJed Brown *cStart = 0;
50199566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap));
50200a96aa3bSJed Brown if (overlap && pforest->ghost) {
50210a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants + pforest->ghost->proc_offsets[pforest->forest->mpisize];
50220a96aa3bSJed Brown } else {
50230a96aa3bSJed Brown *cEnd = pforest->forest->local_num_quadrants;
50240a96aa3bSJed Brown }
50253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50260a96aa3bSJed Brown }
50270a96aa3bSJed Brown
50280a96aa3bSJed Brown #define DMForestCreateCellSF_pforest _append_pforest(DMForestCreateCellSF)
DMForestCreateCellSF_pforest(DM dm,PetscSF * cellSF)5029d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMForestCreateCellSF_pforest(DM dm, PetscSF *cellSF)
5030d71ae5a4SJacob Faibussowitsch {
50310a96aa3bSJed Brown DM_Forest *forest;
50320a96aa3bSJed Brown DM_Forest_pforest *pforest;
50330a96aa3bSJed Brown PetscMPIInt rank;
50340a96aa3bSJed Brown PetscInt overlap;
50350a96aa3bSJed Brown PetscInt cStart, cEnd, cLocalStart, cLocalEnd;
50360a96aa3bSJed Brown PetscInt nRoots, nLeaves, *mine = NULL;
50370a96aa3bSJed Brown PetscSFNode *remote = NULL;
50380a96aa3bSJed Brown PetscSF sf;
50390a96aa3bSJed Brown
50400a96aa3bSJed Brown PetscFunctionBegin;
50419566063dSJacob Faibussowitsch PetscCall(DMForestGetCellChart(dm, &cStart, &cEnd));
50420a96aa3bSJed Brown forest = (DM_Forest *)dm->data;
50430a96aa3bSJed Brown pforest = (DM_Forest_pforest *)forest->data;
50440a96aa3bSJed Brown nRoots = cEnd - cStart;
50450a96aa3bSJed Brown cLocalStart = pforest->cLocalStart;
50460a96aa3bSJed Brown cLocalEnd = pforest->cLocalEnd;
50470a96aa3bSJed Brown nLeaves = 0;
50489566063dSJacob Faibussowitsch PetscCall(DMForestGetPartitionOverlap(dm, &overlap));
50499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
50500a96aa3bSJed Brown if (overlap && pforest->ghost) {
50510a96aa3bSJed Brown PetscSFNode *mirror;
50520a96aa3bSJed Brown p4est_quadrant_t *mirror_array;
50530a96aa3bSJed Brown PetscInt nMirror, nGhostPre, nSelf, q;
50540a96aa3bSJed Brown void **mirrorPtrs;
50550a96aa3bSJed Brown
50560a96aa3bSJed Brown nMirror = (PetscInt)pforest->ghost->mirrors.elem_count;
50570a96aa3bSJed Brown nSelf = cLocalEnd - cLocalStart;
50580a96aa3bSJed Brown nLeaves = nRoots - nSelf;
50590a96aa3bSJed Brown nGhostPre = (PetscInt)pforest->ghost->proc_offsets[rank];
50609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &mine));
50619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nLeaves, &remote));
50629566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nMirror, &mirror, nMirror, &mirrorPtrs));
50630a96aa3bSJed Brown mirror_array = (p4est_quadrant_t *)pforest->ghost->mirrors.array;
50640a96aa3bSJed Brown for (q = 0; q < nMirror; q++) {
5065f4f49eeaSPierre Jolivet p4est_quadrant_t *mir = &mirror_array[q];
50660a96aa3bSJed Brown
50670a96aa3bSJed Brown mirror[q].rank = rank;
50680a96aa3bSJed Brown mirror[q].index = (PetscInt)mir->p.piggy3.local_num + cLocalStart;
5069f4f49eeaSPierre Jolivet mirrorPtrs[q] = (void *)&mirror[q];
50700a96aa3bSJed Brown }
5071792fecdfSBarry Smith PetscCallP4est(p4est_ghost_exchange_custom, (pforest->forest, pforest->ghost, sizeof(PetscSFNode), mirrorPtrs, remote));
50729566063dSJacob Faibussowitsch PetscCall(PetscFree2(mirror, mirrorPtrs));
50730a96aa3bSJed Brown for (q = 0; q < nGhostPre; q++) mine[q] = q;
50740a96aa3bSJed Brown for (; q < nLeaves; q++) mine[q] = (q - nGhostPre) + cLocalEnd;
50750a96aa3bSJed Brown }
50769566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &sf));
50779566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sf, nRoots, nLeaves, mine, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER));
50780a96aa3bSJed Brown *cellSF = sf;
50793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50800a96aa3bSJed Brown }
50810a96aa3bSJed Brown
DMCreateNeumannOverlap_pforest(DM dm,IS * ovl,Mat * J,PetscErrorCode (** setup)(Mat,PetscReal,Vec,Vec,PetscReal,IS,void *),void ** setup_ctx)5082d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateNeumannOverlap_pforest(DM dm, IS *ovl, Mat *J, PetscErrorCode (**setup)(Mat, PetscReal, Vec, Vec, PetscReal, IS, void *), void **setup_ctx)
5083d71ae5a4SJacob Faibussowitsch {
50840a96aa3bSJed Brown DM plex;
50850a96aa3bSJed Brown
50860a96aa3bSJed Brown PetscFunctionBegin;
50879566063dSJacob Faibussowitsch PetscCall(DMPforestGetPlex(dm, &plex));
5088e4d5475eSStefano Zampini PetscCall(DMCopyAuxiliaryVec(dm, plex));
50899566063dSJacob Faibussowitsch PetscCall(DMCreateNeumannOverlap_Plex(plex, ovl, J, setup, setup_ctx));
5090e4d5475eSStefano Zampini PetscCall(DMClearAuxiliaryVec(plex));
50910a96aa3bSJed Brown if (!*setup) {
50929566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", setup));
509348a46eb9SPierre Jolivet if (*setup) PetscCall(PetscObjectCompose((PetscObject)*ovl, "_DM_Original_HPDDM", (PetscObject)dm));
50940a96aa3bSJed Brown }
50953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50960a96aa3bSJed Brown }
50970a96aa3bSJed Brown
5098907a3e9cSStefano Zampini #define DMCreateDomainDecomposition_pforest _append_pforest(DMCreateDomainDecomposition)
DMCreateDomainDecomposition_pforest(DM dm,PetscInt * nsub,char *** names,IS ** innerises,IS ** outerises,DM ** dms)5099907a3e9cSStefano Zampini static PetscErrorCode DMCreateDomainDecomposition_pforest(DM dm, PetscInt *nsub, char ***names, IS **innerises, IS **outerises, DM **dms)
5100907a3e9cSStefano Zampini {
5101907a3e9cSStefano Zampini DM plex;
5102907a3e9cSStefano Zampini
5103907a3e9cSStefano Zampini PetscFunctionBegin;
5104907a3e9cSStefano Zampini PetscCall(DMPforestGetPlex(dm, &plex));
5105e4d5475eSStefano Zampini PetscCall(DMCopyAuxiliaryVec(dm, plex));
5106907a3e9cSStefano Zampini PetscCall(DMCreateDomainDecomposition(plex, nsub, names, innerises, outerises, dms));
5107e4d5475eSStefano Zampini PetscCall(DMClearAuxiliaryVec(plex));
5108907a3e9cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
5109907a3e9cSStefano Zampini }
5110907a3e9cSStefano Zampini
5111907a3e9cSStefano Zampini #define DMCreateDomainDecompositionScatters_pforest _append_pforest(DMCreateDomainDecompositionScatters)
DMCreateDomainDecompositionScatters_pforest(DM dm,PetscInt n,DM * subdms,VecScatter ** iscat,VecScatter ** oscat,VecScatter ** lscat)5112907a3e9cSStefano Zampini static PetscErrorCode DMCreateDomainDecompositionScatters_pforest(DM dm, PetscInt n, DM *subdms, VecScatter **iscat, VecScatter **oscat, VecScatter **lscat)
5113907a3e9cSStefano Zampini {
5114907a3e9cSStefano Zampini DM plex;
5115907a3e9cSStefano Zampini
5116907a3e9cSStefano Zampini PetscFunctionBegin;
5117907a3e9cSStefano Zampini PetscCall(DMPforestGetPlex(dm, &plex));
5118e4d5475eSStefano Zampini PetscCall(DMCopyAuxiliaryVec(dm, plex));
5119907a3e9cSStefano Zampini PetscCall(DMCreateDomainDecompositionScatters(plex, n, subdms, iscat, oscat, lscat));
5120907a3e9cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS);
5121907a3e9cSStefano Zampini }
5122907a3e9cSStefano Zampini
DMInitialize_pforest(DM dm)5123d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_pforest(DM dm)
5124d71ae5a4SJacob Faibussowitsch {
51250a96aa3bSJed Brown PetscFunctionBegin;
51260a96aa3bSJed Brown dm->ops->setup = DMSetUp_pforest;
51270a96aa3bSJed Brown dm->ops->view = DMView_pforest;
51280a96aa3bSJed Brown dm->ops->clone = DMClone_pforest;
51290a96aa3bSJed Brown dm->ops->createinterpolation = DMCreateInterpolation_pforest;
51300a96aa3bSJed Brown dm->ops->createinjection = DMCreateInjection_pforest;
51310a96aa3bSJed Brown dm->ops->setfromoptions = DMSetFromOptions_pforest;
51320a96aa3bSJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_pforest;
513399acd26cSksagiyam dm->ops->createcellcoordinatedm = NULL;
51340a96aa3bSJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_pforest;
51350a96aa3bSJed Brown dm->ops->createlocalvector = DMCreateLocalVector_pforest;
51360a96aa3bSJed Brown dm->ops->creatematrix = DMCreateMatrix_pforest;
51370a96aa3bSJed Brown dm->ops->projectfunctionlocal = DMProjectFunctionLocal_pforest;
51380a96aa3bSJed Brown dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_pforest;
51390a96aa3bSJed Brown dm->ops->projectfieldlocal = DMProjectFieldLocal_pforest;
51400a96aa3bSJed Brown dm->ops->createlocalsection = DMCreatelocalsection_pforest;
51410a96aa3bSJed Brown dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_pforest;
51420a96aa3bSJed Brown dm->ops->computel2diff = DMComputeL2Diff_pforest;
51430a96aa3bSJed Brown dm->ops->computel2fielddiff = DMComputeL2FieldDiff_pforest;
51440a96aa3bSJed Brown dm->ops->getdimpoints = DMGetDimPoints_pforest;
5145907a3e9cSStefano Zampini dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_pforest;
5146907a3e9cSStefano Zampini dm->ops->createddscatters = DMCreateDomainDecompositionScatters_pforest;
51470a96aa3bSJed Brown
51489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_plex_pforest) "_C", DMConvert_plex_pforest));
51499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, PetscStringize(DMConvert_pforest_plex) "_C", DMConvert_pforest_plex));
51509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_pforest));
51519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMForestGetPartitionOverlap));
51523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
51530a96aa3bSJed Brown }
51540a96aa3bSJed Brown
51550a96aa3bSJed Brown #define DMCreate_pforest _append_pforest(DMCreate)
DMCreate_pforest(DM dm)5156d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_pforest(DM dm)
5157d71ae5a4SJacob Faibussowitsch {
51580a96aa3bSJed Brown DM_Forest *forest;
51590a96aa3bSJed Brown DM_Forest_pforest *pforest;
51600a96aa3bSJed Brown
51610a96aa3bSJed Brown PetscFunctionBegin;
51629566063dSJacob Faibussowitsch PetscCall(PetscP4estInitialize());
51639566063dSJacob Faibussowitsch PetscCall(DMCreate_Forest(dm));
51649566063dSJacob Faibussowitsch PetscCall(DMInitialize_pforest(dm));
51659566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, P4EST_DIM));
51660a96aa3bSJed Brown
51670a96aa3bSJed Brown /* set forest defaults */
51689566063dSJacob Faibussowitsch PetscCall(DMForestSetTopology(dm, "unit"));
51699566063dSJacob Faibussowitsch PetscCall(DMForestSetMinimumRefinement(dm, 0));
51709566063dSJacob Faibussowitsch PetscCall(DMForestSetInitialRefinement(dm, 0));
51719566063dSJacob Faibussowitsch PetscCall(DMForestSetMaximumRefinement(dm, P4EST_QMAXLEVEL));
51729566063dSJacob Faibussowitsch PetscCall(DMForestSetGradeFactor(dm, 2));
51739566063dSJacob Faibussowitsch PetscCall(DMForestSetAdjacencyDimension(dm, 0));
51749566063dSJacob Faibussowitsch PetscCall(DMForestSetPartitionOverlap(dm, 0));
51750a96aa3bSJed Brown
51760a96aa3bSJed Brown /* create p4est data */
51774dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&pforest));
51780a96aa3bSJed Brown
51790a96aa3bSJed Brown forest = (DM_Forest *)dm->data;
51800a96aa3bSJed Brown forest->data = pforest;
51810a96aa3bSJed Brown forest->destroy = DMForestDestroy_pforest;
51820a96aa3bSJed Brown forest->ftemplate = DMForestTemplate_pforest;
51830a96aa3bSJed Brown forest->transfervec = DMForestTransferVec_pforest;
51840a96aa3bSJed Brown forest->transfervecfrombase = DMForestTransferVecFromBase_pforest;
51850a96aa3bSJed Brown forest->createcellchart = DMForestCreateCellChart_pforest;
51860a96aa3bSJed Brown forest->createcellsf = DMForestCreateCellSF_pforest;
51870a96aa3bSJed Brown forest->clearadaptivityforest = DMForestClearAdaptivityForest_pforest;
51880a96aa3bSJed Brown forest->getadaptivitysuccess = DMForestGetAdaptivitySuccess_pforest;
51890a96aa3bSJed Brown pforest->topo = NULL;
51900a96aa3bSJed Brown pforest->forest = NULL;
51910a96aa3bSJed Brown pforest->ghost = NULL;
51920a96aa3bSJed Brown pforest->lnodes = NULL;
51930a96aa3bSJed Brown pforest->partition_for_coarsening = PETSC_TRUE;
51940a96aa3bSJed Brown pforest->coarsen_hierarchy = PETSC_FALSE;
51950a96aa3bSJed Brown pforest->cLocalStart = -1;
51960a96aa3bSJed Brown pforest->cLocalEnd = -1;
51970a96aa3bSJed Brown pforest->labelsFinalized = PETSC_FALSE;
51980a96aa3bSJed Brown pforest->ghostName = NULL;
51993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
52000a96aa3bSJed Brown }
52010a96aa3bSJed Brown
52020a96aa3bSJed Brown #endif /* defined(PETSC_HAVE_P4EST) */
5203