Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -415,11 +415,16 @@ registry lookup.
For field-coupled finite-difference JVPs, the exact boundary evaluation level must also equal the
active Program resource level before the perturbed field solve or the frozen-field restoration is
allowed to dispatch. A fine-level caller therefore cannot forge a coarse point and reuse level 0.
This identity guard does not create a fine-level tangent-field solve. Supporting a boundary JVP that
reads solved fields requires a provider contract that materializes the field tangent from the state
direction on every participating level, couples those tangents across CompositeFAC when requested,
and restores the frozen primal field transactionally. Reusing the primal field pointer would omit
the derivative of the field solve and is therefore not a valid fallback.
The generated finite-difference route materializes that derivative by re-solving the exact prepared
provider from the perturbed state on both levels of the proved 2D ratio-2 L0/L1 hierarchy, evaluating
the complete residual, and restoring the frozen primal field transactionally; it never reuses the
unperturbed field pointer as a tangent. A two-rank native consensus/numerical oracle covers this
algebra, but the generated-Program route has no installed MPI end-to-end proof. The public capability
row therefore advertises only host single-process execution. A partially refined CompositeFAC
hierarchy with a dynamic physical boundary remains a separate explicit refusal until its correction
owns a level-qualified homogeneous/JVP boundary operator.
The public report exposes that unsupported subcase separately as
`amr:composite_dynamic_boundary`; it is not hidden behind the available level-qualified JVP row.
Linear and nonlinear field routes both retain the accepted warm start until their `SolveReport` is
consumed; an invalid boundary evaluation or iteration limit restores that value and cannot update the
published aux channel.
Expand Down
46 changes: 34 additions & 12 deletions python/pops/_capabilities_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,8 @@ def _python_contract_rows(flags: Any, source: str) -> list[Any]:

mpi = bool(_flag_value(flags, "supports_mpi"))
gpu = bool(_flag_value(flags, "supports_gpu"))
amr_status = _status_from_flag(flags, "supports_amr")
composite_boundary_status = "partial" if amr_status == "available" else amr_status
return [
_row(
"boundary:prepared_transport",
Expand Down Expand Up @@ -494,9 +496,7 @@ def _python_contract_rows(flags: Any, source: str) -> list[Any]:
"solver outcome, block counter, or restart metadata; a typed candidate failure "
"rejects the step and never substitutes another solver"
),
requested=(
"prepared Riemann recovery chain with requested/used solver diagnostics"
),
requested=("prepared Riemann recovery chain with requested/used solver diagnostics"),
available_route=(
"one explicitly selected Riemann solver with typed rejection and transactional "
"rollback"
Expand Down Expand Up @@ -574,19 +574,41 @@ def _python_contract_rows(flags: Any, source: str) -> list[Any]:
_row(
"amr:field_coupled_rhs_jacvec",
layout="amr",
backend="none",
backend="production",
platform="host",
mpi=mpi,
gpu=gpu,
status="unavailable",
mpi=False,
gpu=False,
status=amr_status,
limitation=(
"field-coupled finite-difference rhs_jacvec re-solves the exact prepared field "
"provider from the perturbed state on both levels of the proved 2D ratio-2 L0/L1 "
"hierarchy, then restores the frozen primal publication transactionally; a "
"two-rank native consensus/numerical oracle exists, but the generated-Program "
"route has no installed MPI end-to-end proof and therefore advertises only host "
"single-process execution"
),
source=source,
),
_row(
"amr:composite_dynamic_boundary",
layout="amr",
backend="production",
platform="host",
mpi=False,
gpu=False,
status=composite_boundary_status,
limitation=(
"field-coupled rhs_jacvec has no level-qualified tangent-field provider ABI "
"for AMR level > 0"
"the proved fully refined 2D ratio-2 L0/L1 hierarchy passes the exact finest-level "
"logical time, state dependencies and nonlinear/JVP context to its dynamic field "
"boundary; a partially refined CompositeFAC hierarchy is refused because its "
"coarse-fine correction lacks a level-qualified homogeneous/JVP boundary operator"
),
available_route=(
"fully refined 2D ratio-2 L0/L1 host single-process CompositeFAC hierarchy"
),
requested="field_coupled rhs_jacvec on AMR level > 0",
available_route="field_coupled rhs_jacvec on AMR level 0",
alternative=(
"use the level-0 route or implement a level-qualified tangent-field provider ABI"
"use a fully refined hierarchy or implement the level-qualified homogeneous/JVP "
"coarse-fine correction boundary"
),
source=source,
),
Expand Down
15 changes: 12 additions & 3 deletions tests/python/integration/amr/test_amr_runtime_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,20 @@ def test_inspect_before_build_reports_unbuilt_patches_honestly():
assert report.regrid.frozen is True


def test_inspect_no_longer_lists_the_served_fine_level_field_jacvec_as_a_limitation():
def test_inspect_separates_served_field_jacvec_from_partial_composite_boundary():
report = AmrSystem(n=16, L=1.0, periodicity=(True, True)).amr.inspect()
rows = [row for row in report.limitations if row["feature"] == "amr:field_coupled_rhs_jacvec"]
field_rows = [
row for row in report.limitations if row["feature"] == "amr:field_coupled_rhs_jacvec"
]
boundary_rows = [
row for row in report.limitations if row["feature"] == "amr:composite_dynamic_boundary"
]

assert rows == []
assert field_rows == []
assert len(boundary_rows) == 1
assert boundary_rows[0]["status"] == "partial"
assert "partially refined CompositeFAC hierarchy is refused" in boundary_rows[0]["reason"]
assert "level-qualified homogeneous/JVP boundary operator" in boundary_rows[0]["reason"]


# --- compiled static delegation ------------------------------------------------
Expand Down
48 changes: 45 additions & 3 deletions tests/python/unit/codegen/test_fail_closed_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,50 @@ def test_mpi_world_route_reports_only_proved_native_availability(supports_mpi, e
assert external_amr.available_route == (
"external FieldSolver@2 on one uniform host/serial level"
)
field_jacvec = routes["amr:field_coupled_rhs_jacvec"]
assert field_jacvec.status == "available"
assert field_jacvec.layout == "amr"
assert field_jacvec.backend == "production"
assert field_jacvec.mpi is False
assert field_jacvec.gpu is False
assert "proved 2D ratio-2 L0/L1 hierarchy" in field_jacvec.limitation
assert "restores the frozen primal publication transactionally" in field_jacvec.limitation
assert "two-rank native consensus/numerical oracle exists" in field_jacvec.limitation
assert (
"generated-Program route has no installed MPI end-to-end proof" in field_jacvec.limitation
)
assert "host single-process execution" in field_jacvec.limitation
assert field_jacvec.available_route == ""
assert field_jacvec.alternative == ""
composite_boundary = routes["amr:composite_dynamic_boundary"]
assert composite_boundary.status == "partial"
assert composite_boundary.layout == "amr"
assert composite_boundary.backend == "production"
assert composite_boundary.mpi is False
assert composite_boundary.gpu is False
assert "fully refined 2D ratio-2 L0/L1 hierarchy" in composite_boundary.limitation
assert "partially refined CompositeFAC hierarchy is refused" in composite_boundary.limitation
assert "level-qualified homogeneous/JVP boundary operator" in composite_boundary.limitation
assert composite_boundary.available_route == (
"fully refined 2D ratio-2 L0/L1 host single-process CompositeFAC hierarchy"
)
assert "coarse-fine correction boundary" in composite_boundary.alternative


def test_amr_field_jacvec_routes_follow_the_artifact_amr_flag():
report = capability_reports.native_capability_report(
flags={"supports_mpi": True, "supports_gpu": False, "supports_amr": False},
source="uniform-test-manifest",
)
routes = {row.feature: row for row in report.routes}

field_jacvec = routes["amr:field_coupled_rhs_jacvec"]
assert field_jacvec.status == "unavailable"
assert field_jacvec.error_message

composite_boundary = routes["amr:composite_dynamic_boundary"]
assert composite_boundary.status == "unavailable"
assert composite_boundary.error_message


def test_transport_boundary_routes_report_exact_supported_envelope_and_missing_kernels():
Expand Down Expand Up @@ -152,9 +196,7 @@ def test_transport_boundary_routes_report_exact_supported_envelope_and_missing_k
flags={"supports_mpi": True, "supports_gpu": True, "supports_amr": True},
source="test-gpu-manifest",
)
gpu_post_riemann = {
row.feature: row for row in gpu_report.routes
}["boundary:post_riemann_flux"]
gpu_post_riemann = {row.feature: row for row in gpu_report.routes}["boundary:post_riemann_flux"]
assert gpu_post_riemann.gpu is False


Expand Down
Loading