aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/tests/test_climate_ocean.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_climate_ocean.py')
-rw-r--r--tests/test_climate_ocean.py81
1 files changed, 81 insertions, 0 deletions
diff --git a/tests/test_climate_ocean.py b/tests/test_climate_ocean.py
new file mode 100644
index 0000000..8132c6e
--- /dev/null
+++ b/tests/test_climate_ocean.py
@@ -0,0 +1,81 @@
+import unittest
+from pathlib import Path
+
+import numpy as np
+
+from mapgen import climate as CL
+from tests.helpers import make_ctx
+
+GOLDEN = Path(__file__).parent / "data" / "climate_golden_r2.npz"
+NEW = ("current", "current_speed", "sst", "upwelling", "productivity")
+
+
+def golden_ctx(cfg=None):
+ ctx = make_ctx(2, cfg=cfg)
+ g = ctx.grid
+ land = (np.abs(g.lat) < 40) & (np.abs(g.lon) < 50)
+ ctx.data["elevation_eroded_m"] = np.where(land, np.where(np.abs(g.lon) < 10, 2500.0, 300.0),
+ -4000.0).astype(np.float32)
+ return ctx, land
+
+
+class OceanDisabledTest(unittest.TestCase):
+ def test_disabled_reproduces_pre_ocean_climate(self):
+ ctx, land = golden_ctx({"ocean": {"enabled": False}})
+ out = CL.run(ctx)
+ ref = np.load(GOLDEN)
+ for k in ref.files:
+ np.testing.assert_array_equal(out[k], ref[k], err_msg=k)
+ self.assertTrue(np.all(out["current"] == 0) and np.all(out["productivity"] == 0))
+ np.testing.assert_array_equal(out["sst"], out["T_mean"].astype(np.float32))
+
+
+class OceanCoupledTest(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.ctx, cls.land = golden_ctx()
+ cls.out = CL.run(cls.ctx)
+
+ def test_new_fields(self):
+ g, out = self.ctx.grid, self.out
+ for k in NEW:
+ self.assertIn(k, out)
+ self.assertEqual(out[k].dtype, np.float32, k)
+ self.assertTrue(np.all(np.isfinite(out[k])), k)
+ self.assertEqual(out["current"].shape, (g.n, 3))
+ self.assertTrue(np.all(out["current"][self.land] == 0))
+ np.testing.assert_allclose(out["current_speed"], np.linalg.norm(out["current"], axis=1), rtol=1e-5)
+ sea = ~self.land
+ self.assertTrue(np.all((out["sst"][sea] >= -1.8) & (out["sst"][sea] < 40))) # sea water freezes at −1.8 °C
+
+ def test_currents_change_the_climate(self):
+ ref = np.load(GOLDEN)
+ self.assertGreater(np.abs(self.out["T_mean"] - ref["T_mean"]).max(), 0.5) # the old gyre rule is gone
+
+ def test_winds_come_from_current_free_temperatures(self):
+ ctx, _ = golden_ctx({"ocean": {"relax_days": 30.0}}) # other SST, same winds
+ np.testing.assert_array_equal(CL.run(ctx)["wind_jun"], self.out["wind_jun"])
+
+ def test_unknown_ocean_key_is_an_error(self):
+ from mapgen.config import ConfigError
+ ctx, _ = golden_ctx({"ocean": {"frictoin_days": 3.0}})
+ with self.assertRaises(ConfigError):
+ CL.run(ctx)
+
+ def test_all_land_world(self):
+ ctx = make_ctx(2)
+ ctx.data["elevation_eroded_m"] = np.full(ctx.grid.n, 500.0, np.float32)
+ out = CL.run(ctx)
+ self.assertTrue(np.all(out["current"] == 0))
+
+ def test_locked_world_has_still_ocean(self):
+ ctx, land = golden_ctx({"climate": {"lock": True}})
+ out = CL.run(ctx)
+ self.assertTrue(np.all(out["current"] == 0) and np.all(out["upwelling"] == 0))
+ np.testing.assert_array_equal(out["sst"], out["T_mean"].astype(np.float32))
+
+ def test_upwelling_and_productivity_filled(self):
+ sea = ~self.land
+ self.assertGreater(np.abs(self.out["upwelling"][sea]).max(), 1.0)
+ self.assertGreater(self.out["productivity"][sea].max(), 0.05)
+ self.assertTrue(np.all(self.out["productivity"][self.land] == 0))