import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "validation")) import json import unittest import numpy as np from les_flow_oracle import H, U, NU, TIMES, solve, relative, amplitude class OracleTests(unittest.TestCase): def test_linear_exact(self): y, states = solve(0, n=256) for t, u in states.items(): exact = U * np.sin(np.pi * y / H) * np.exp(-NU * (np.pi / H) ** 2 * t) self.assertLess(relative(u, exact), 1e-5) def test_nonlinear_refinement_symmetry_and_dissipation(self): y, states = solve(1, n=256) yc, coarse = solve(1, n=128) energy = U**2 / 2 for t, u in states.items(): self.assertTrue(np.all(np.isfinite(u))) self.assertGreaterEqual(float(u.min()), 0) self.assertLessEqual(float(u.max()), U) np.testing.assert_allclose(u, u[::-1], atol=1e-14) self.assertLess(float(np.mean(u * u)), energy) energy = float(np.mean(u * u)) self.assertLess(relative(np.interp(yc, y, u), coarse[t]), 8e-5) def test_filter_is_independent_of_oracle_grid(self): y, a = solve(1, n=128, times=(TIMES[-1],)) _, b = solve(0.5, n=128, times=(TIMES[-1],), delta=2) np.testing.assert_array_equal(a[TIMES[-1]], b[TIMES[-1]]) def test_fixed_grid_timestep_halving(self): errors = [] for cs in (0.0, 0.16, 1.0): _, full = solve(cs, n=256, cfl=0.4) _, half = solve(cs, n=256, cfl=0.2) errors.extend(relative(full[t], half[t]) for t in TIMES) self.assertLess(max(errors), 1e-8) print( json.dumps({"fixed_grid_timestep_half_max_relative": max(errors)}), flush=True, ) def test_signal_and_wrong_convention_separate(self): y, std = solve(1, n=256, times=(TIMES[-1],)) _, wrong = solve(2 ** (-0.25), n=256, times=(TIMES[-1],)) t = TIMES[-1] base = U * np.exp(-NU * (np.pi / H) ** 2 * t) signal = (base - amplitude(y, std[t])) / base separation = relative(wrong[t], std[t]) print( json.dumps( { "final_time": t, "standard_sgs_amplitude_signal": signal, "wrong_convention_profile_separation": separation, } ), flush=True, ) self.assertGreater(signal, 0.04) self.assertGreater(separation, 0.01) if __name__ == "__main__": unittest.main()