AMR Reference Tracking Benchmark

This example benchmarks the dynamic AMR path on a transported entropy pulse. The AMR hierarchy is allowed to regrid every coarse step, and the final density field is compared against a trusted $128 \times 128$ uniform-grid reference generated by the validated structured-grid hyperbolic solver.

Mathematical Setup

The transported entropy pulse is the same smooth solution used in the AMR verification study, but here the question is different: can the dynamic AMR hierarchy follow the feature while using far fewer active cells than the reference grid?

Reference

  • Berger, M.J. & Colella, P. (1989). Local Adaptive Mesh Refinement for Shock Hydrodynamics. Journal of Computational Physics, 82, 64-84.
using CairoMakie

amr_common_path = joinpath(@__DIR__, "amr_common.jl")
isfile(amr_common_path) || (amr_common_path = joinpath(@__DIR__, "..", "literate_verification", "amr_common.jl"))
include(amr_common_path)

base_cells = [8, 12, 16]
reference_cells = 128
reference = uniform_reference_density(reference_cells)
results = [
    dynamic_reference_tracking_case(
            base;
            max_level = 2,
            reference_density = reference.density,
            reference_cells,
        ) for base in base_cells
]
errors = [result.density_error for result in results]
active_cells = [result.active_cells for result in results]
compressions = [result.compression for result in results]

fig = Figure(fontsize = 22, size = (1100, 420))
ax1 = Axis(
    fig[1, 1],
    xlabel = "Active AMR cells",
    ylabel = L"L^1(\rho) \text{ vs uniform reference}",
    xscale = log10,
    yscale = log10,
    title = "Dynamic AMR Accuracy",
)
scatterlines!(
    ax1,
    active_cells,
    errors;
    color = :darkorange,
    marker = :diamond,
    linewidth = 2,
    markersize = 12,
)
ax2 = Axis(
    fig[1, 2],
    xlabel = "Base block cells per side",
    ylabel = "Active-cell fraction vs 128x128 reference",
    title = "Adaptive Compression",
)
scatterlines!(
    ax2,
    base_cells,
    compressions;
    color = :seagreen,
    marker = :circle,
    linewidth = 2,
    markersize = 12,
)
resize_to_layout!(fig)
fig
Example block output

Test Assertions

The adaptive hierarchy should actually reach level 2, the error should improve as the AMR budget increases, and the active-cell count should remain well below the dense $128 \times 128$ reference grid.

if isdefined(@__MODULE__, :record_evidence_result)
    record_evidence_result(
        metrics = Dict(
            "density_errors" => errors,
            "active_cells" => active_cells,
            "compression" => compressions,
            "finest_budget_error" => errors[end],
        ),
        artifacts = ["amr_reference_tracking.png"],
        notes = [
            "Dynamic AMR benchmark uses the maintained solve_amr(prob) path because remeshing is not yet part of the canonical ODEProblem contract.",
            "The reference baseline is a trusted uniform 128x128 structured-grid solution on the same transported pulse.",
        ],
        summary = Dict(
            "base_cells" => base_cells,
            "active_cells" => active_cells,
            "compression" => compressions,
            "density_errors" => errors,
        ),
    )
end

Just the code

An uncommented version of this example is given below. You can view the source code for this file here.

using CairoMakie

amr_common_path = joinpath(@__DIR__, "amr_common.jl")
isfile(amr_common_path) || (amr_common_path = joinpath(@__DIR__, "..", "literate_verification", "amr_common.jl"))
include(amr_common_path)

base_cells = [8, 12, 16]
reference_cells = 128
reference = uniform_reference_density(reference_cells)
results = [
    dynamic_reference_tracking_case(
            base;
            max_level = 2,
            reference_density = reference.density,
            reference_cells,
        ) for base in base_cells
]
errors = [result.density_error for result in results]
active_cells = [result.active_cells for result in results]
compressions = [result.compression for result in results]

fig = Figure(fontsize = 22, size = (1100, 420))
ax1 = Axis(
    fig[1, 1],
    xlabel = "Active AMR cells",
    ylabel = L"L^1(\rho) \text{ vs uniform reference}",
    xscale = log10,
    yscale = log10,
    title = "Dynamic AMR Accuracy",
)
scatterlines!(
    ax1,
    active_cells,
    errors;
    color = :darkorange,
    marker = :diamond,
    linewidth = 2,
    markersize = 12,
)
ax2 = Axis(
    fig[1, 2],
    xlabel = "Base block cells per side",
    ylabel = "Active-cell fraction vs 128x128 reference",
    title = "Adaptive Compression",
)
scatterlines!(
    ax2,
    base_cells,
    compressions;
    color = :seagreen,
    marker = :circle,
    linewidth = 2,
    markersize = 12,
)
resize_to_layout!(fig)
fig


if isdefined(@__MODULE__, :record_evidence_result)
    record_evidence_result(
        metrics = Dict(
            "density_errors" => errors,
            "active_cells" => active_cells,
            "compression" => compressions,
            "finest_budget_error" => errors[end],
        ),
        artifacts = ["amr_reference_tracking.png"],
        notes = [
            "Dynamic AMR benchmark uses the maintained solve_amr(prob) path because remeshing is not yet part of the canonical ODEProblem contract.",
            "The reference baseline is a trusted uniform 128x128 structured-grid solution on the same transported pulse.",
        ],
        summary = Dict(
            "base_cells" => base_cells,
            "active_cells" => active_cells,
            "compression" => compressions,
            "density_errors" => errors,
        ),
    )
end

This page was generated using Literate.jl.