Files
CelerisLab/tests/unit/test_re100.py
T

104 lines
3.3 KiB
Python

import sys, json, hashlib
from pathlib import Path
import numpy as np
import pytest
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "tests/validation"))
import re100_helpers as h
import periodic as p
@pytest.mark.parametrize("n", [20, 40, 80])
def test_units(n):
x = h.parameters(n, 0.01)
assert x["viscosity"] * x["dx"] ** 2 / x["dt"] == pytest.approx(0.001)
assert x["mean_speed"] * x["dx"] / x["dt"] == pytest.approx(1.0)
assert x["mean_speed"] * n / x["viscosity"] == pytest.approx(100)
assert x["peak_mach"] == pytest.approx(0.015 * np.sqrt(3))
assert (x["top"] - x["bottom"]) * x["dx"] == pytest.approx(0.41)
assert (x["nx"] - 1) * x["dx"] == pytest.approx(2.2)
assert (np.array(x["center"]) - [0, 0.5]) * x["dx"] == pytest.approx([0.2, 0.2])
cfg, _, _ = h.make_config(n, 0.01, "MRT", "neq_extrap", "zou_he_local")
assert cfg["method"]["inlet"]["scheme"] == "zou_he_local"
def test_pressure_units():
x = h.parameters(40, 0.01)
ny, nx = x["ny"], x["nx"]
xx = np.arange(nx)[None, :]
rho = np.broadcast_to(1 + xx * 1e-6, (ny, nx))
fluid = np.ones_like(rho, dtype=bool)
assert h.pressure_probes(rho, fluid, x)["dp"] == pytest.approx(
-40e-6 / 0.01**2 / 3, abs=1e-10
)
def rows(amplitude=1.0, drift=0.0):
out = []
for t in np.arange(240, 300.001, 0.02):
out.append(
dict(
tstar=t,
tstar_force=t,
cl=amplitude * np.sin(2 * np.pi * t / 3.3),
cd=3.2 + 0.03 * np.cos(4 * np.pi * t / 3.3) + drift * t,
dp=2.46 + 0.04 * np.sin(4 * np.pi * t / 3.3),
mass=1.0,
flux_in=1.0,
flux_out=1.0,
)
)
return out
def test_periodic_synthetic():
a = p.assess(rows())
assert a["periodic"]
assert len(a["cycles"]) > 5
assert a["cycles"][-1]["st"] == pytest.approx(1 / 3.3, rel=1e-5)
assert not p.assess(rows(amplitude=0.01))["periodic"]
assert not p.assess(rows(drift=0.01))["periodic"]
assert not p.assess(rows()[:100])["periodic"]
def test_production_unmodified():
m = json.loads(
(ROOT / "tests/validation/data/dfg_re100/source_manifest.json").read_text()
)
assert m["commit"] == h.PIN
for name, digest in m["production_sha256"].items():
assert hashlib.sha256((ROOT / name).read_bytes()).hexdigest() == digest, name
def test_reference():
r = json.loads(
(ROOT / "tests/validation/data/dfg_re100/reference_cycle.json").read_text()
)
assert 0.301 < r["st"] < 0.303
assert 3.22 < r["cd_max"] < 3.23
assert 2.5 < r["dp_max"] < 2.51
assert p.compare(r, r)["reference_agreement"]
def test_stale_cycles_rejected():
r = rows()
level = next(x["cl"] for x in r if x["tstar"] >= 284.5)
for x in r:
if x["tstar"] >= 284.5:
x["cl"] = level
assert not p.assess(r)["periodic"]
def test_min_time_is_used(monkeypatch):
monkeypatch.setitem(p.GATES, "min_tstar", 290.0)
assert not p.assess(rows())["periodic"]
def test_nonconsecutive_cycles_rejected(monkeypatch):
cycles = p.extract(rows())
bad = cycles[-6:]
bad.pop(2)
monkeypatch.setattr(p, "extract", lambda *a, **k: bad)
assert not p.assess(rows())["periodic"]