SELF_AMRController_2D Module

Adaptive-mesh-refinement controller for 2-D DG models: the driver that closes the serial AMR loop around a live, time-stepping model. One call to Adapt performs one adaptation epoch between time steps:

  1. estimate - the Legendre modal-decay indicator flags each element refine/keep/coarsen from the current solution (driving variable ivar, e.g. pressure);
  2. cap - refine flags on leaves already at maxLevel are demoted to keep, bounding the finest resolution (and the stable time step) a priori;
  3. halo - refine flags spread to face neighbours for nHalo passes, so a feature moving at speed c stays inside the refined band provided the adaptation cadence satisfies kdtc <= nHalo * h_fine;
  4. mutate - AdaptFromFlags + Balance2to1 update the quad-forest; if the leaf set is unchanged the epoch is a no-op and the model is untouched;
  5. transfer - BuildTransferPlan maps old leaves to new (copy / exact prolongation / conservative restriction), EmitMesh produces the solver-ready nonconforming mesh, and a new SEMQuad geometry is generated;
  6. regrid - model%Regrid rebinds the model's storage and boundary conditions to the new mesh, preserving its time state and parameters; the transferred solution is applied and uploaded to the device.

The controller owns the forest, the indicator, and the meshes/geometries it emits. The mesh is rebuilt each epoch and the previous one freed after the model is rebound. Geometry instead lives in two long-lived buffers that alternate (AMR Stage 6c), so it is resized rather than reallocated and the previous epoch's geometry remains available while the new one is built. The base mesh and geometry the model was initialized with belong to the caller and are never freed here, but the base mesh must outlive the controller: it supplies the boundary-condition metadata and the communicator for every emitted mesh. After controller%Free the model's mesh/geometry pointers are dangling, so free or stop using the model first.

MPI (AMR Stage 5): the forest is rank-replicated. At Init the global base-mesh tables are allgathered so every rank builds an identical forest; each epoch the rank-local indicator flags are allgathered (one small collective) so every rank applies identical mutations and computes identical transfer plans and global connectivity. EmitMesh re-decomposes the new leaf list into contiguous (space-filling-curve) ranges, so repartitioning and load balance are implicit in every epoch. Solution migration gathers the old rank-local solutions into a global field and applies the plan to the new rank-local range only - simple and correct at single-node scale; a point-to-point exchange is a drop-in replacement behind the same interface. All collectives run between time steps at the adaptation cadence; nothing is added to the time-stepping loop.

Because refinement halves the element scale per level, an explicit-stability time step chosen for the base mesh must shrink with the finest active level; RecommendedTimeStep(dtBase) = dtBase / 2**MaxLevel gives the level-based bound to pass to ForwardStep after each epoch.

Debug switches for the Stage 6c incremental geometry path, resolved once from the environment on first use. Present so that a suspected geometry problem can be split between the reuse copy and the compacted generation without rebuilding:

SELF_AMR_GEOM_NO_REUSE=1 regenerate every element (the reuse predicate never fires) SELF_AMR_GEOM_VERIFY=1 additionally generate the full geometry the old way and compare element by element, reporting the first quantity that differs


Uses

  • module~~self_amrcontroller_2d~~UsesGraph module~self_amrcontroller_2d SELF_AMRController_2D module~self_refinementindicator_2d~2 SELF_RefinementIndicator_2D module~self_amrcontroller_2d->module~self_refinementindicator_2d~2 module~self_transferplan_2d SELF_TransferPlan_2D module~self_amrcontroller_2d->module~self_transferplan_2d module~self_adaptivemesh_2d SELF_AdaptiveMesh_2D module~self_amrcontroller_2d->module~self_adaptivemesh_2d iso_fortran_env iso_fortran_env module~self_amrcontroller_2d->iso_fortran_env module~self_geometry_2d SELF_Geometry_2D module~self_amrcontroller_2d->module~self_geometry_2d module~self_dgmodel2d_t SELF_DGModel2D_t module~self_amrcontroller_2d->module~self_dgmodel2d_t mpi mpi module~self_amrcontroller_2d->mpi module~self_mesh_2d SELF_Mesh_2D module~self_amrcontroller_2d->module~self_mesh_2d module~self_quadtreemesh_2d SELF_QuadTreeMesh_2D module~self_amrcontroller_2d->module~self_quadtreemesh_2d module~self_lagrange SELF_Lagrange module~self_amrcontroller_2d->module~self_lagrange module~self_domaindecomposition SELF_DomainDecomposition module~self_amrcontroller_2d->module~self_domaindecomposition module~self_constants SELF_Constants module~self_amrcontroller_2d->module~self_constants module~self_refinementindicator_2d~2->module~self_constants module~self_refinementindicator_2d_t SELF_RefinementIndicator_2D_t module~self_refinementindicator_2d~2->module~self_refinementindicator_2d_t module~self_transferplan_2d->module~self_quadtreemesh_2d module~self_transferplan_2d->module~self_lagrange module~self_transferplan_2d->module~self_constants module~self_solutiontransfer_2d SELF_SolutionTransfer_2D module~self_transferplan_2d->module~self_solutiontransfer_2d module~self_adaptivemesh_2d->module~self_mesh_2d module~self_adaptivemesh_2d->module~self_quadtreemesh_2d module~self_adaptivemesh_2d->module~self_lagrange module~self_adaptivemesh_2d->module~self_constants module~self_refinementprimitives_2d SELF_RefinementPrimitives_2D module~self_adaptivemesh_2d->module~self_refinementprimitives_2d module~self_geometry_2d->module~self_mesh_2d module~self_geometry_2d->module~self_lagrange module~self_geometry_2d->module~self_constants module~self_vector_2d SELF_Vector_2D module~self_geometry_2d->module~self_vector_2d module~self_data SELF_Data module~self_geometry_2d->module~self_data module~self_tensor_2d~2 SELF_Tensor_2D module~self_geometry_2d->module~self_tensor_2d~2 module~self_scalar_2d SELF_Scalar_2D module~self_geometry_2d->module~self_scalar_2d module~self_supportroutines SELF_SupportRoutines module~self_geometry_2d->module~self_supportroutines module~self_dgmodel2d_t->module~self_transferplan_2d module~self_dgmodel2d_t->module~self_geometry_2d module~self_dgmodel2d_t->module~self_mesh_2d module~self_mappedscalar_2d SELF_MappedScalar_2D module~self_dgmodel2d_t->module~self_mappedscalar_2d FEQParse FEQParse module~self_dgmodel2d_t->FEQParse module~self_metadata SELF_Metadata module~self_dgmodel2d_t->module~self_metadata module~self_hdf5 SELF_HDF5 module~self_dgmodel2d_t->module~self_hdf5 HDF5 HDF5 module~self_dgmodel2d_t->HDF5 module~self_model SELF_Model module~self_dgmodel2d_t->module~self_model module~self_dgmodel2d_t->module~self_supportroutines module~self_boundaryconditions SELF_BoundaryConditions module~self_dgmodel2d_t->module~self_boundaryconditions module~self_mappedvector_2d~2 SELF_MappedVector_2D module~self_dgmodel2d_t->module~self_mappedvector_2d~2 module~self_mesh_2d_t SELF_Mesh_2D_t module~self_mesh_2d->module~self_mesh_2d_t module~self_quadtreemesh_2d->module~self_mesh_2d module~self_quadtreemesh_2d->module~self_lagrange module~self_quadtreemesh_2d->module~self_constants module~self_quadtreemesh_2d->module~self_refinementprimitives_2d module~self_lagrange->iso_fortran_env module~self_lagrange->module~self_constants iso_c_binding iso_c_binding module~self_lagrange->iso_c_binding module~self_lagrange_t SELF_Lagrange_t module~self_lagrange->module~self_lagrange_t module~self_domaindecomposition_t SELF_DomainDecomposition_t module~self_domaindecomposition->module~self_domaindecomposition_t module~self_constants->iso_fortran_env module~self_constants->iso_c_binding module~self_mappedscalar_2d_t SELF_MappedScalar_2D_t module~self_mappedscalar_2d->module~self_mappedscalar_2d_t module~self_refinementindicator_2d_t->module~self_lagrange module~self_refinementindicator_2d_t->module~self_constants module~self_refinementindicator_2d_t->iso_c_binding module~self_refinementindicator_2d_t->module~self_scalar_2d module~self_solutiontransfer_2d->module~self_lagrange module~self_solutiontransfer_2d->module~self_constants module~self_refinementprimitives_2d->module~self_lagrange module~self_refinementprimitives_2d->module~self_constants module~self_vector_2d_t SELF_Vector_2D_t module~self_vector_2d->module~self_vector_2d_t module~self_data->module~self_lagrange module~self_data->module~self_constants module~self_data->FEQParse module~self_data->module~self_metadata module~self_data->iso_c_binding module~self_data->module~self_hdf5 module~self_data->HDF5 module~self_metadata->module~self_hdf5 module~self_metadata->HDF5 module~self_mesh_2d_t->module~self_lagrange module~self_mesh_2d_t->module~self_domaindecomposition module~self_mesh_2d_t->module~self_constants module~self_mesh_2d_t->iso_c_binding module~self_mesh_2d_t->module~self_hdf5 module~self_mesh_2d_t->HDF5 module~self_mesh_2d_t->module~self_supportroutines 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_hdf5->iso_fortran_env module~self_hdf5->mpi module~self_hdf5->module~self_constants module~self_hdf5->HDF5 module~self_model->FEQParse module~self_model->module~self_metadata module~self_model->module~self_hdf5 module~self_model->HDF5 module~self_model->module~self_supportroutines module~self_tensor_2d_t SELF_Tensor_2D_t module~self_tensor_2d~2->module~self_tensor_2d_t module~self_scalar_2d->module~self_constants module~self_scalar_2d->iso_c_binding module~self_scalar_2d_t SELF_Scalar_2D_t module~self_scalar_2d->module~self_scalar_2d_t module~self_supportroutines->iso_fortran_env module~self_supportroutines->module~self_constants module~self_boundaryconditions->module~self_metadata module~self_boundaryconditions->iso_c_binding module~self_boundaryconditions->module~self_supportroutines module~self_lagrange_t->iso_fortran_env module~self_lagrange_t->module~self_constants module~self_lagrange_t->iso_c_binding module~self_lagrange_t->module~self_hdf5 module~self_lagrange_t->HDF5 module~self_lagrange_t->module~self_supportroutines module~self_lagrange_t->module~self_quadrature module~self_domaindecomposition_t->mpi module~self_domaindecomposition_t->module~self_lagrange module~self_domaindecomposition_t->module~self_constants module~self_domaindecomposition_t->iso_c_binding module~self_domaindecomposition_t->module~self_supportroutines module~self_mappedvector_2d_t SELF_MappedVector_2D_t module~self_mappedvector_2d~2->module~self_mappedvector_2d_t module~self_mappedscalar_2d_t->module~self_geometry_2d module~self_mappedscalar_2d_t->module~self_mesh_2d module~self_mappedscalar_2d_t->module~self_lagrange module~self_mappedscalar_2d_t->module~self_domaindecomposition module~self_mappedscalar_2d_t->module~self_constants module~self_mappedscalar_2d_t->FEQParse module~self_mappedscalar_2d_t->iso_c_binding module~self_mappedscalar_2d_t->module~self_tensor_2d~2 module~self_mappedscalar_2d_t->module~self_scalar_2d module~self_tensor_2d_t->module~self_lagrange module~self_tensor_2d_t->module~self_constants module~self_tensor_2d_t->module~self_data module~self_tensor_2d_t->FEQParse module~self_tensor_2d_t->module~self_metadata module~self_tensor_2d_t->iso_c_binding module~self_tensor_2d_t->module~self_hdf5 module~self_tensor_2d_t->HDF5 module~self_datapool SELF_DataPool module~self_tensor_2d_t->module~self_datapool module~self_quadrature->iso_fortran_env module~self_quadrature->module~self_constants module~self_vector_2d_t->module~self_lagrange module~self_vector_2d_t->module~self_constants module~self_vector_2d_t->module~self_data module~self_vector_2d_t->FEQParse module~self_vector_2d_t->module~self_metadata module~self_vector_2d_t->iso_c_binding module~self_vector_2d_t->module~self_hdf5 module~self_vector_2d_t->HDF5 module~self_vector_2d_t->module~self_datapool module~self_mesh->module~self_domaindecomposition module~self_mesh->module~self_constants module~self_mesh->iso_c_binding module~self_scalar_2d_t->module~self_lagrange module~self_scalar_2d_t->module~self_constants module~self_scalar_2d_t->module~self_data module~self_scalar_2d_t->FEQParse module~self_scalar_2d_t->module~self_metadata module~self_scalar_2d_t->iso_c_binding module~self_scalar_2d_t->module~self_hdf5 module~self_scalar_2d_t->HDF5 module~self_scalar_2d_t->module~self_datapool module~self_mappedvector_2d_t->module~self_geometry_2d module~self_mappedvector_2d_t->module~self_mesh_2d module~self_mappedvector_2d_t->module~self_lagrange module~self_mappedvector_2d_t->module~self_domaindecomposition module~self_mappedvector_2d_t->module~self_constants module~self_mappedvector_2d_t->module~self_vector_2d module~self_mappedvector_2d_t->FEQParse module~self_mappedvector_2d_t->iso_c_binding module~self_mappedvector_2d_t->module~self_tensor_2d~2 module~self_datapool->module~self_constants

Contents


Variables

TypeVisibilityAttributesNameInitial
logical, public, save:: geomDebugResolved =.false.
logical, public, save:: geomFull =.false.

SELF_AMR_GEOM_FULL=1: bypass the incremental path

logical, public, save:: geomNoReuse =.false.
logical, public, save:: geomVerify =.false.

Derived Types

type, public :: AMRController2D

Components

TypeVisibilityAttributesNameInitial
type(SEMQuad), public, pointer:: activeGeom=> null()

geometry the model currently runs on

type(Mesh2D), public, pointer:: activeMesh=> null()

mesh the model currently runs on

type(Mesh2D), public, pointer:: baseMesh=> null()

caller-owned; metadata source for EmitMesh

real(kind=prec), public :: coarsenThreshold =0.0_prec
type(QuadTreeMesh2D), public :: forest
type(SEMQuad), public, pointer:: genGeom=> null()

Cumulative geometry-reuse accounting (AMR Stage 6c), so a run can report what fraction of elements avoided regeneration rather than leaving the payoff to be estimated.

type(SEMQuad), public, pointer:: geomA=> null()
type(SEMQuad), public, pointer:: geomB=> null()
integer, public :: geomSlot =0

Scratch geometry holding just the elements an epoch actually changed, generated compacted and then scattered into place. Persistent and resized, so it allocates only when an epoch changes more elements than any epoch before it.

type(RefinementIndicator2D), public :: indicator
type(Lagrange), public, pointer:: interp=> null()

the model's solution interpolant

integer, public :: ivar =SELF_AMR_ALLVARS

driving variable for the indicator

integer, public :: maxLevel =1

refinement-level cap

integer(kind=int64), public :: nGeomGenerated =0
integer(kind=int64), public :: nGeomReused =0
integer, public :: nHalo =1

refine-flag halo-expansion passes

logical, public :: ownsActive =.false.

whether activeMesh was emitted by us (vs the caller's) Two long-lived geometry buffers, alternated each epoch (AMR Stage 6c). Geometry is now resized in place rather than allocated and freed per epoch, which is what lets Stage 6b's amortization apply to it; alternating means the PREVIOUS epoch's geometry is still intact while the new one is filled, which the incremental reuse path needs. geomSlot records which buffer activeGeom currently is, or 0 while it is still the caller's geometry.

real(kind=prec), public :: refineThreshold =0.0_prec

Type-Bound Procedures

procedure, public :: Adapt => Adapt_AMRController2D
procedure, private :: BuildGeometry => BuildGeometry_AMRController2D
procedure, public :: Free => Free_AMRController2D
procedure, public :: Init => Init_AMRController2D
procedure, private :: NextGeomBuffer => NextGeomBuffer_AMRController2D
procedure, public :: RecommendedTimeStep => RecommendedTimeStep_AMRController2D

Functions

public function RecommendedTimeStep_AMRController2D(this, dtBase) result(dt)

Level-based explicit-stability time step: refinement halves the element scale per level, so a time step dtBase that is stable on the base (level-0) mesh scales to dtBase / 2**MaxLevel on the current forest. Deterministic and exact for the quadtree (child elements are exact half-scale subdivisions); no geometry reduction is needed.

Arguments

TypeIntentOptionalAttributesName
class(AMRController2D), intent(in) :: this
real(kind=prec), intent(in) :: dtBase

Return Value real(kind=prec)


Subroutines

public subroutine Adapt_AMRController2D(this, model, adapted)

Perform one adaptation epoch on the model (see the module documentation). On return, adapted reports whether the mesh changed; when it did, the model is already rebound to the new mesh with the solution transferred (conservatively), and the caller should re-evaluate its time step (RecommendedTimeStep) before the next ForwardStep. When the leaf set is unchanged the model is untouched.

Read more…

Arguments

TypeIntentOptionalAttributesName
class(AMRController2D), intent(inout) :: this
class(DGModel2D_t), intent(inout) :: model
logical, intent(out) :: adapted

public subroutine AllgatherPerElemInts(decomp, perElem, localArr, globalArr)

Allgather an integer array with perElem entries per element from the decomposition's contiguous rank-local element ranges into the global element ordering.

Arguments

TypeIntentOptionalAttributesName
type(DomainDecomposition), intent(in) :: decomp
integer, intent(in) :: perElem
integer, intent(in) :: localArr(*)
integer, intent(out) :: globalArr(*)

public subroutine AllgatherPerElemReals(decomp, perElem, localArr, globalArr)

Allgather a real(prec) array with perElem entries per element from the decomposition's contiguous rank-local element ranges into the global element ordering.

Arguments

TypeIntentOptionalAttributesName
type(DomainDecomposition), intent(in) :: decomp
integer, intent(in) :: perElem
real(kind=prec), intent(in) :: localArr(*)
real(kind=prec), intent(out) :: globalArr(*)

public subroutine BuildGeometry_AMRController2D(this, newMesh, plan, newGeom, nReused)

Fill newGeom for the emitted mesh, reusing the previous epoch's geometry for every element that did not change and generating only the rest (AMR Stage 6c). nReused reports how many elements were copied rather than computed.

Read more…

Arguments

TypeIntentOptionalAttributesName
class(AMRController2D), intent(inout) :: this
type(Mesh2D), intent(in) :: newMesh
type(TransferPlan2D), intent(in) :: plan
type(SEMQuad), intent(inout) :: newGeom
integer, intent(out) :: nReused

public subroutine Free_AMRController2D(this)

Release the forest, the indicator, and any controller-emitted mesh/geometry. The caller-owned base mesh/geometry are untouched. A model still pointing at a controller-emitted mesh must not be used after this call.

Arguments

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

public subroutine InitForestFromDecomposedMesh(forest, mesh)

Build a rank-replicated forest over a decomposed base mesh: allgather the global node coordinates, side table, and material ids (by the decomposition's contiguous element ownership) and initialize the forest from the global tables. Collective over the mesh communicator; runs once, at controller initialization.

Arguments

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

public subroutine Init_AMRController2D(this, model, refineThreshold, coarsenThreshold, ivar, maxLevel, nHalo)

Attach the controller to an initialized model. The model's current mesh becomes the forest's base mesh (level 0); its geometry interpolant drives the indicator and the solution transfer. Thresholds are the sigma = log10 modal-energy-ratio cut-offs of the refinement indicator (refineThreshold > coarsenThreshold; see SELF_RefinementIndicator_2D). ivar is the driving solution variable (or SELF_AMR_ALLVARS). maxLevel >= 0 caps the refinement depth; nHalo >= 0 sets the refine-flag halo width in elements.

Arguments

TypeIntentOptionalAttributesName
class(AMRController2D), intent(out) :: this
class(DGModel2D_t), intent(in) :: model
real(kind=prec), intent(in) :: refineThreshold
real(kind=prec), intent(in) :: coarsenThreshold
integer, intent(in) :: ivar
integer, intent(in) :: maxLevel
integer, intent(in) :: nHalo

public subroutine NextGeomBuffer_AMRController2D(this, nElem, geom, slot)

Select the geometry buffer to fill this epoch: whichever of the two is not currently active, so the previous epoch's geometry stays intact and readable (AMR Stage 6c).

Read more…

Arguments

TypeIntentOptionalAttributesName
class(AMRController2D), intent(inout) :: this
integer, intent(in) :: nElem
type(SEMQuad), intent(out), pointer:: geom
integer, intent(out) :: slot

public subroutine ResolveGeomDebug()

Read the Stage 6c geometry debug switches once.

Arguments

None

public subroutine VerifyGeometry(this, newMesh, newGeom)

Generate the geometry the original way and report, per quantity, the largest discrepancy against the incrementally built one. Diagnostic only; gated by SELF_AMR_GEOM_VERIFY.

Read more…

Arguments

TypeIntentOptionalAttributesName
class(AMRController2D), intent(inout) :: this
type(Mesh2D), intent(in) :: newMesh
type(SEMQuad), intent(in) :: newGeom