SELF_QuadTreeMesh_2D Module

Forest-of-quadtrees data structure for adaptive h-refinement of 2-D quadrilateral meshes (AMR Stage 2b). Each base-mesh element is the root of a quadtree; refinement replaces a leaf with four children (one per reference sub-quadrant, SELF child ordering 1=SW,2=SE,3=NE,4=NW), and coarsening merges a family of four leaf siblings back into their parent. The forest tracks refinement levels and the active leaf set; the physical geometry of any leaf is produced by repeated exact isoparametric subdivision of its root (SELF_RefinementPrimitives_2D).

This module owns the adaptive mesh mutation only. Turning an adaptively refined (and hence generally nonconforming) forest into a solver-ready Mesh2D_t - face-neighbour queries, 2:1 balancing, hanging-node/mortar generation - is AMR Stage 4, and dynamic MPI re-partitioning is Stage 5. The intended driver loop each adaptation step is:

indicator%Estimate(solution,ivar) ! AMR Stage 1 : per-leaf refine/keep/coarsen flags forest%AdaptFromFlags(indicator%flag) ! AMR Stage 2b : mutate the forest (this module) ... Stage 4 : balance + emit Mesh2D_t + mortars ; Stage 3 : transfer the solution ...

Coarsening does not currently reclaim the storage of removed child nodes (the node arrays grow monotonically); the active leaf set is always recovered by traversal from the roots, so orphaned nodes are simply never revisited. Storage compaction is a future optimisation.


Uses

  • module~~self_quadtreemesh_2d~~UsesGraph module~self_quadtreemesh_2d SELF_QuadTreeMesh_2D module~self_mesh_2d SELF_Mesh_2D module~self_quadtreemesh_2d->module~self_mesh_2d module~self_constants SELF_Constants module~self_quadtreemesh_2d->module~self_constants module~self_refinementprimitives_2d SELF_RefinementPrimitives_2D module~self_quadtreemesh_2d->module~self_refinementprimitives_2d module~self_lagrange SELF_Lagrange module~self_quadtreemesh_2d->module~self_lagrange module~self_mesh_2d_t SELF_Mesh_2D_t module~self_mesh_2d->module~self_mesh_2d_t iso_c_binding iso_c_binding module~self_constants->iso_c_binding iso_fortran_env iso_fortran_env module~self_constants->iso_fortran_env module~self_refinementprimitives_2d->module~self_constants module~self_refinementprimitives_2d->module~self_lagrange module~self_lagrange->module~self_constants module~self_lagrange->iso_c_binding module~self_lagrange->iso_fortran_env module~self_lagrange_t SELF_Lagrange_t module~self_lagrange->module~self_lagrange_t module~self_mesh_2d_t->module~self_constants module~self_mesh_2d_t->module~self_lagrange module~self_mesh_2d_t->iso_c_binding HDF5 HDF5 module~self_mesh_2d_t->HDF5 module~self_domaindecomposition SELF_DomainDecomposition module~self_mesh_2d_t->module~self_domaindecomposition module~self_hdf5 SELF_HDF5 module~self_mesh_2d_t->module~self_hdf5 module~self_quadrature SELF_Quadrature module~self_mesh_2d_t->module~self_quadrature module~self_mesh SELF_Mesh module~self_mesh_2d_t->module~self_mesh module~self_supportroutines SELF_SupportRoutines module~self_mesh_2d_t->module~self_supportroutines module~self_lagrange_t->module~self_constants module~self_lagrange_t->iso_c_binding module~self_lagrange_t->iso_fortran_env module~self_lagrange_t->HDF5 module~self_lagrange_t->module~self_hdf5 module~self_lagrange_t->module~self_quadrature module~self_lagrange_t->module~self_supportroutines module~self_domaindecomposition_t SELF_DomainDecomposition_t module~self_domaindecomposition->module~self_domaindecomposition_t module~self_hdf5->module~self_constants module~self_hdf5->iso_fortran_env module~self_hdf5->HDF5 mpi mpi module~self_hdf5->mpi module~self_quadrature->module~self_constants module~self_quadrature->iso_fortran_env module~self_mesh->module~self_constants module~self_mesh->iso_c_binding module~self_mesh->module~self_domaindecomposition module~self_supportroutines->module~self_constants module~self_supportroutines->iso_fortran_env module~self_domaindecomposition_t->module~self_constants module~self_domaindecomposition_t->module~self_lagrange module~self_domaindecomposition_t->iso_c_binding module~self_domaindecomposition_t->module~self_supportroutines module~self_domaindecomposition_t->mpi

Used by

  • module~~self_quadtreemesh_2d~~UsedByGraph module~self_quadtreemesh_2d SELF_QuadTreeMesh_2D module~self_transferplan_2d SELF_TransferPlan_2D module~self_transferplan_2d->module~self_quadtreemesh_2d module~self_adaptivemesh_2d SELF_AdaptiveMesh_2D module~self_adaptivemesh_2d->module~self_quadtreemesh_2d module~self_amrcontroller_2d SELF_AMRController_2D module~self_amrcontroller_2d->module~self_quadtreemesh_2d module~self_amrcontroller_2d->module~self_transferplan_2d module~self_amrcontroller_2d->module~self_adaptivemesh_2d module~self_dgmodel2d_t SELF_DGModel2D_t module~self_amrcontroller_2d->module~self_dgmodel2d_t module~self_dgmodel2d_t->module~self_transferplan_2d module~self_dgmodel2d~2 SELF_DGModel2D module~self_dgmodel2d~2->module~self_transferplan_2d module~self_dgmodel2d~2->module~self_dgmodel2d_t module~self_dgmodel2d SELF_DGModel2D module~self_dgmodel2d->module~self_dgmodel2d_t module~self_ecdgmodel2d_t SELF_ECDGModel2D_t module~self_ecdgmodel2d_t->module~self_dgmodel2d module~self_lineareuler2d_pml_t self_LinearEuler2D_PML_t module~self_lineareuler2d_pml_t->module~self_dgmodel2d module~self_lineareuler2d_t self_LinearEuler2D_t module~self_lineareuler2d_pml_t->module~self_lineareuler2d_t module~self_nulldgmodel2d_t self_NullDGModel2D_t module~self_nulldgmodel2d_t->module~self_dgmodel2d module~self_linearshallowwater2d_t self_LinearShallowWater2D_t module~self_linearshallowwater2d_t->module~self_dgmodel2d module~self_lineareuler2d_t->module~self_dgmodel2d module~self_advection_diffusion_2d_t self_advection_diffusion_2d_t module~self_advection_diffusion_2d_t->module~self_dgmodel2d module~self_advection_diffusion_2d~2 self_advection_diffusion_2d module~self_advection_diffusion_2d~2->module~self_advection_diffusion_2d_t module~self_lineareuler2d self_LinearEuler2D module~self_lineareuler2d->module~self_lineareuler2d_t module~self_ecdgmodel2d SELF_ECDGModel2D module~self_ecdgmodel2d->module~self_ecdgmodel2d_t module~self_ecdgmodel2d~2 SELF_ECDGModel2D module~self_ecdgmodel2d~2->module~self_ecdgmodel2d_t module~self_lineareuler2d_pml self_LinearEuler2D_PML module~self_lineareuler2d_pml->module~self_lineareuler2d_pml_t module~self_ecadvection2d~2 SELF_ECAdvection2D module~self_ecadvection2d~2->module~self_ecdgmodel2d_t module~self_ecadvection2d_t SELF_ECAdvection2D_t module~self_ecadvection2d~2->module~self_ecadvection2d_t module~self_esatmo2d SELF_ESAtmo2D module~self_esatmo2d->module~self_ecdgmodel2d_t module~self_esatmo2d_t SELF_ESAtmo2D_t module~self_esatmo2d->module~self_esatmo2d_t module~self_lineareuler2d_pml~2 self_LinearEuler2D_PML module~self_lineareuler2d_pml~2->module~self_lineareuler2d_pml_t module~self_nulldgmodel2d self_NullDGModel2D module~self_nulldgmodel2d->module~self_nulldgmodel2d_t module~self_nulldgmodel2d~2 self_NullDGModel2D module~self_nulldgmodel2d~2->module~self_nulldgmodel2d_t module~self_linearshallowwater2d self_LinearShallowWater2D module~self_linearshallowwater2d->module~self_linearshallowwater2d_t module~self_linearshallowwater2d~2 self_LinearShallowWater2D module~self_linearshallowwater2d~2->module~self_linearshallowwater2d_t module~self_lineareuler2d~2 self_LinearEuler2D module~self_lineareuler2d~2->module~self_lineareuler2d_t module~self_advection_diffusion_2d self_advection_diffusion_2d module~self_advection_diffusion_2d->module~self_advection_diffusion_2d_t module~self_ecadvection2d_t->module~self_ecdgmodel2d module~self_esatmo2d_t->module~self_ecdgmodel2d module~self_ecadvection2d SELF_ECAdvection2D module~self_ecadvection2d->module~self_ecadvection2d_t module~self_esatmo2d~2 SELF_ESAtmo2D module~self_esatmo2d~2->module~self_esatmo2d_t

Contents


Variables

TypeVisibilityAttributesNameInitial
integer, public, parameter:: QUADTREE_COARSEN =-1
integer, public, parameter:: QUADTREE_KEEP =0
integer, public, parameter:: QUADTREE_REFINE =1

Derived Types

type, public :: QuadTreeMesh2D

Components

TypeVisibilityAttributesNameInitial
integer, public :: capacity =0
integer, public, allocatable:: child(:,:)
integer, public, allocatable:: leaf(:)
integer, public, allocatable:: level(:)
integer, public :: nGeo =0
integer, public :: nLeaves =0
integer, public :: nNodes =0
integer, public :: nRoots =0
integer, public, allocatable:: parent(:)
integer, public, allocatable:: quadrant(:)
integer, public :: quadrature =0
integer, public, allocatable:: rootBC(:,:)
real(kind=prec), public, allocatable:: rootCoords(:,:,:,:)
integer, public, allocatable:: rootElem(:)
integer, public, allocatable:: rootFlip(:,:)
integer, public, allocatable:: rootMaterial(:)
integer, public, allocatable:: rootNbr(:,:)
integer, public, allocatable:: rootNbrSide(:,:)

Type-Bound Procedures

procedure, public :: AdaptFromFlags => AdaptFromFlags_QuadTreeMesh2D
procedure, public :: Balance2to1 => Balance2to1_QuadTreeMesh2D
procedure, private :: EnsureCapacity => EnsureCapacity_QuadTreeMesh2D
procedure, public :: FaceNeighbor => FaceNeighbor_QuadTreeMesh2D
procedure, public :: Free => Free_QuadTreeMesh2D
procedure, public :: Init => Init_QuadTreeMesh2D
procedure, public :: InitGlobal => InitGlobal_QuadTreeMesh2D
procedure, public :: LeafCoords => LeafCoords_QuadTreeMesh2D
procedure, public :: MaxLevel => MaxLevel_QuadTreeMesh2D
procedure, public :: MaxLevelJump => MaxLevelJump_QuadTreeMesh2D
procedure, public :: RebuildLeaves => RebuildLeaves_QuadTreeMesh2D
procedure, public :: RefineNode => RefineNode_QuadTreeMesh2D

Functions

public function MaxLevelJump_QuadTreeMesh2D(this) result(mx)

Largest refinement-level difference across any leaf face (0 on a conforming or uniformly refined forest, 1 on a 2:1-balanced adaptive forest). Because FaceNeighbor returns the equal-or-larger neighbour, every level difference is observed from the finer leaf as a coarser leaf neighbour; internal (finer) neighbours contribute nothing from this side.

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(in) :: this

Return Value integer

public function MaxLevel_QuadTreeMesh2D(this) result(mx)

Highest refinement level among the active leaves.

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(in) :: this

Return Value integer

public pure function qt_internal(s, c) result(isInternal)

.true. if child c's side s is interior to its parent (its neighbour across s is a sibling).

Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: s
integer, intent(in) :: c

Return Value logical

public pure function qt_opposite(s) result(o)

The local side directly across an element from side s.

Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: s

Return Value integer

public pure function qt_reflect(s, c) result(rc)

Sibling child index obtained by reflecting c across side s (swap the y-half for the horizontal faces S/N, the x-half for the vertical faces E/W).

Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: s
integer, intent(in) :: c

Return Value integer

public pure function qt_subpos(c, s) result(t)

Sub-position (1 or 2, in the positive direction of side s) of child c along side s; 0 if c does not touch side s.

Arguments

TypeIntentOptionalAttributesName
integer, intent(in) :: c
integer, intent(in) :: s

Return Value integer


Subroutines

public subroutine AdaptFromFlags_QuadTreeMesh2D(this, flag)

Mutate the forest from a per-leaf flag array (indexed over the current leaves in this%leaf order, e.g. the flag array produced by SELF_RefinementIndicator_2D):

Read more…

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(inout) :: this
integer, intent(in) :: flag(1:this%nLeaves)

public subroutine Balance2to1_QuadTreeMesh2D(this)

Enforce the 2:1 balance condition: no leaf face may separate elements differing by more than one refinement level. Iterates to a fixed point - in each sweep, any leaf whose equal-or-larger neighbour is a leaf two or more levels coarser triggers refinement of that coarser neighbour; refinement can ripple, so sweeps repeat until nothing changes. The leaf set is rebuilt on return.

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(inout) :: this

public subroutine EnsureCapacity_QuadTreeMesh2D(this, need)

Grow the node arrays (amortized doubling) so at least need nodes fit.

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(inout) :: this
integer, intent(in) :: need

public recursive subroutine FaceNeighbor_QuadTreeMesh2D(this, node, s, nbr, ns, nf)

Find the equal-or-larger face neighbour of node across its local side s using the classic quadtree ascend/descend search. Returns: nbr - neighbour node id (0 = physical domain boundary). It is either a LEAF at any level <= level(node), or an INTERNAL node at exactly level(node) (meaning the shared face is subdivided on the neighbour side, i.e. finer neighbours exist). ns - the neighbour's local side that faces node. nf - the flip between the two shared edges (0 same direction, 1 reversed), inherited from the base-mesh face where the search crosses a root boundary. With this, a 2:1 hanging face is exactly "nbr is a leaf with level(nbr) = level(node)-1", and finer neighbours are exactly "nbr is internal".

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(in) :: this
integer, intent(in) :: node
integer, intent(in) :: s
integer, intent(out) :: nbr
integer, intent(out) :: ns
integer, intent(out) :: nf

public subroutine Free_QuadTreeMesh2D(this)

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(inout) :: this

public subroutine InitGlobal_QuadTreeMesh2D(this, nRoots, nGeo, quadrature, rootCoords, rootNbr, rootNbrSide, rootFlip, rootBC, rootMaterial)

Initialize the forest directly from GLOBAL base-mesh tables (one root per global base element, all leaves at level 0). This is the initialization path for a rank-replicated forest over a decomposed base mesh (AMR Stage 5): every rank passes the same gathered tables and holds an identical forest. rootNbr carries global element ids (0 = physical boundary), rootNbrSide/rootFlip decode the base sideInfo(4) pairing, rootBC the base boundary-condition id per side, and rootMaterial the base material id per element.

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(out) :: this
integer, intent(in) :: nRoots
integer, intent(in) :: nGeo
integer, intent(in) :: quadrature
real(kind=prec), intent(in) :: rootCoords(1:2,1:nGeo+1,1:nGeo+1,1:nRoots)
integer, intent(in) :: rootNbr(1:4,1:nRoots)
integer, intent(in) :: rootNbrSide(1:4,1:nRoots)
integer, intent(in) :: rootFlip(1:4,1:nRoots)
integer, intent(in) :: rootBC(1:4,1:nRoots)
integer, intent(in) :: rootMaterial(1:nRoots)

public subroutine Init_QuadTreeMesh2D(this, mesh)

Initialize the forest with one root per base-mesh element (all leaves at level 0). The base geometry (node coordinates) is copied so leaf geometry can be regenerated after any amount of refinement without holding a reference to the mesh. Requires a single-rank mesh (a decomposed mesh only stores its local elements); a rank-replicated forest over a decomposed base is built by gathering the global tables and calling InitGlobal.

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(out) :: this
type(Mesh2D), intent(in) :: mesh

public subroutine LeafCoords_QuadTreeMesh2D(this, leafIndex, geomInterp, coords)

Physical geometry-node coordinates of leaf leafIndex, produced by repeated exact isoparametric subdivision of its root element along the quadtree path. geomInterp must be a degree-nGeo Lagrange interpolant on the mesh's geometry (quadrature) nodes - the same interpolant SELF_MeshRefinement_2D builds. Level 0 leaves return the root geometry directly.

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(in) :: this
integer, intent(in) :: leafIndex
type(Lagrange), intent(in) :: geomInterp
real(kind=prec), intent(out) :: coords(1:2,1:this%nGeo+1,1:this%nGeo+1)

public subroutine RebuildLeaves_QuadTreeMesh2D(this)

Recompute the active leaf set by depth-first traversal from the roots. Traversal (rather than a scan of all nodes) is what makes orphaned nodes left behind by coarsening invisible.

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(inout) :: this

public subroutine RefineNode_QuadTreeMesh2D(this, node)

Subdivide one leaf node into four children. Does nothing (with a warning) if the node is already refined. The caller is responsible for rebuilding the leaf list afterwards (or calling AdaptFromFlags, which does so).

Arguments

TypeIntentOptionalAttributesName
class(QuadTreeMesh2D), intent(inout) :: this
integer, intent(in) :: node