worldgen

git clone https://git.godosa.eu/worldgen

master

raw ยท 4326 bytes

import json
import unittest

import numpy as np

from mapgen import seabed as SB
from mapgen.graph import distance_to
from tests.helpers import make_ctx


def sea_ctx(tect=None):
    ctx = make_ctx(3, tect=tect or {"plate": []})
    g = ctx.grid
    land = (np.abs(g.lat) < 30) & (np.abs(g.lon) < 40)
    ridge = np.abs(g.lon - 120) < 1.0
    d_div = distance_to(g, ridge)
    age = np.where(land, 0.0, np.minimum(d_div / 30.0, 200.0))
    ctx.data.update({"elevation_eroded_m": np.where(land, 500.0, -4500.0).astype(np.float32), "ocean": ~land,
                     "continental": land, "ocean_age_myr": age.astype(np.float32), "d_div_km": d_div,
                     "d_over_km": np.full(g.n, np.inf), "d_sub_km": np.full(g.n, np.inf),
                     "T_mean": 25.0 - 0.5 * np.abs(g.lat), "vel": np.zeros((g.n, 3))})
    return ctx


class SeabedTest(unittest.TestCase):
    def test_land_has_no_sea_floor(self):
        ctx = sea_ctx()
        out = SB.run(ctx)
        land = ~ctx.data["ocean"]
        for k in ("vent_potential", "seabed_type", "seabed_mineral", "bottom_temp_c", "sediment_m"):
            self.assertTrue(np.all(np.asarray(out[k])[land] == 0), k)

    def test_vents_on_the_ridge_not_far_from_it(self):
        ctx = sea_ctx()
        out = SB.run(ctx)
        d = ctx.data["d_div_km"]
        self.assertGreaterEqual(out["vent_potential"][d == 0].min(), 0.5)
        self.assertLess(out["vent_potential"][ctx.data["ocean"] & (d > 3000)].max(), 0.05)

    def test_sediment_thickens_with_age_away_from_land(self):
        ctx = sea_ctx()
        out = SB.run(ctx)
        g = ctx.grid
        young = ctx.data["ocean"] & (ctx.data["d_div_km"] < 300) & (np.abs(g.lon) > 90)
        old = ctx.data["ocean"] & (ctx.data["ocean_age_myr"] > 100) & (np.abs(g.lon) > 90)
        self.assertLess(out["sediment_m"][young].mean(), out["sediment_m"][old].mean())

    def test_bottom_temperature(self):
        ctx = sea_ctx()
        g = ctx.grid
        eq, polar = g.cell_index(0.0, 170.0), g.cell_index(-80.0, 170.0)
        z = np.asarray(ctx.data["elevation_eroded_m"]).copy()
        shallow = g.cell_index(-20.0, 170.0)
        z[shallow] = -100.0
        ctx.data["elevation_eroded_m"] = z
        out = SB.run(ctx)
        self.assertAlmostEqual(out["bottom_temp_c"][eq], 1.0 + 3.0 * np.cos(np.radians(g.lat[eq])) ** 2, places=4)
        self.assertLess(out["bottom_temp_c"][polar], 1.3)
        deep = 1.0 + 3.0 * np.cos(np.radians(g.lat[shallow])) ** 2
        t = 25.0 - 0.5 * abs(g.lat[shallow])
        self.assertAlmostEqual(out["bottom_temp_c"][shallow], deep + 0.875 * (t - deep), places=3)

    def test_plateau_volcanic_field_makes_volcanic_sea_floor(self):
        plat = {"name": "p", "center": [0.0, -150.0], "area_km2": 3.0e6, "top_m": [1500.0, 3000.0]}
        ctx = sea_ctx({"plate": [], "plateau": [plat]})
        out = SB.run(ctx)
        from mapgen.crust import center_dist
        near = center_dist(ctx.grid, [0.0, -150.0]) < 800.0
        self.assertTrue(np.isin(out["seabed_type"][near], [SB.SB_VOLCANIC, SB.SB_VENTS]).any())
        self.assertGreater(out["vent_potential"][near].max(), 0.3)

    def test_deterministic(self):
        a, b = SB.run(sea_ctx()), SB.run(sea_ctx())
        for k in a:
            np.testing.assert_array_equal(a[k], b[k])


class SeabedRenderTest(unittest.TestCase):
    def test_rasters_legends_and_plateaus_in_the_build(self):
        from mapgen.testing import built_world
        out = built_world() / "out" / "r2"
        fields = json.loads((out / "fields.json").read_text())
        for name in ("pressure", "o2_fraction", "fire", "vent_potential", "bottom_temp", "sediment",
                     "plant_height"):
            self.assertIn(name, fields["continuous"])
            self.assertTrue((out / "raster" / f"{name}.png").exists(), name)
        for name in ("seabed_type", "seabed_mineral"):
            self.assertIn(name, fields["categorical"])
        meta = json.loads((out / "cells_meta.json").read_text())
        self.assertEqual(meta["legends"]["seabed_type"], SB.SEABED_NAMES)
        self.assertEqual(meta["plateaus"], [])
        with np.load(out / "cells.npz") as z:
            for k in ("vent_potential", "seabed_type", "pressure_bar", "fire_reactivity", "plateau_id"):
                self.assertIn(k, z.files)