aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/tests/test_crust.py
blob: 1bfca601fceb67494cd9a5d681d58dfb77409e4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import unittest

import numpy as np

from mapgen import crust as CR
from mapgen.plates import CONV, DIV
from tests.helpers import make_ctx

TECT = {"plate": [],
        "lip": [{"name": "l", "center": [10.0, -30.0], "radius_km": 1500.0}],
        "volcano": [{"name": "v", "center": [-10.0, 20.0], "radius_km": 700.0, "height_m": 7000.0,
                     "scar_azimuths": [90.0]}]}


def ctx3():
    ctx = make_ctx(3, tect=TECT, cfg={"crust": {"edge_noise": 0.0}})
    g = ctx.grid
    land = ((np.abs(g.lat) < 35) & (np.abs(g.lon) < 60)).astype(float)
    bt = np.zeros(g.n, np.int8)
    bt[np.abs(g.lon - 120) < 1.0] = DIV   # a mid-ocean ridge along lon 120
    bt[np.abs(g.lon - 0) < 1.0] = CONV
    ctx.data.update({"sk_land": land, "m_land_hint": np.zeros(g.n), "bnd_type": bt})
    return ctx


class CrustTest(unittest.TestCase):
    def test_classes(self):
        ctx = ctx3()
        out = CR.run(ctx)
        g = ctx.grid
        age = out["age_class"]
        self.assertTrue(out["continental"][g.cell_index(20.0, -50.0)])
        self.assertFalse(out["continental"][g.cell_index(0.0, 150.0)])
        self.assertEqual(age[g.cell_index(0.0, 150.0)], CR.OCEANIC)
        self.assertEqual(age[g.cell_index(10.0, -30.0)], CR.LIP)
        self.assertEqual(age[g.cell_index(-10.0, 20.0)], CR.VOLCANO)
        self.assertEqual(age[g.cell_index(-10.0, 24.0)], CR.SCAR)      # east sector, ~900 km out
        self.assertEqual(age[g.cell_index(20.0, 3.0)], CR.POST_OROGEN)

    def test_ocean_age_grows_from_ridge(self):
        ctx = ctx3()
        out = CR.run(ctx)
        g = ctx.grid
        ocean = ~out["continental"] & (np.abs(g.lat) < 20) & (np.abs(g.lon - 120) < 20)
        r = np.corrcoef(np.abs(g.lon[ocean] - 120), out["ocean_age_myr"][ocean])[0, 1]
        self.assertGreater(r, 0.95)
        self.assertTrue(np.all(out["ocean_age_myr"][out["continental"]] == 0))


class ShelfTest(unittest.TestCase):
    def test_continental_shelf_is_resolution_independent(self):
        from mapgen.graph import distance_to
        for res in (3, 4):
            ctx = make_ctx(res, tect={"plate": []}, cfg={"crust": {"edge_noise": 0.0}})
            g = ctx.grid
            land = ((np.abs(g.lat) < 30) & (np.abs(g.lon) < 40)).astype(float)
            ctx.data.update({"sk_land": land, "m_land_hint": np.zeros(g.n), "bnd_type": np.zeros(g.n, np.int8)})
            cont = CR.run(ctx)["continental"]
            d = distance_to(g, land > 0.5)
            self.assertTrue(np.all(cont[land > 0.5]), res)
            self.assertGreater(cont[(d > 0) & (d < 300)].mean(), 0.8, res)     # shelf
            self.assertEqual(cont[d > 700].sum(), 0, res)                      # but not far out


class FractalMarginTest(unittest.TestCase):
    @staticmethod
    def _edge(noise):
        from mapgen.graph import components
        ctx = make_ctx(4, tect={"plate": []}, cfg={"crust": {"edge_noise": noise}})
        g = ctx.grid
        land = ((np.abs(g.lat) < 30) & (np.abs(g.lon) < 60)).astype(float)
        ctx.data.update({"sk_land": land, "m_land_hint": np.zeros(g.n), "bnd_type": np.zeros(g.n, np.int8)})
        cont = CR.run(ctx)["continental"]
        lab = components(g, cont)
        sizes = np.bincount(lab[cont])
        return int(np.sum(cont[g.src] != cont[g.dst])), int(np.sum((sizes > 0) & (sizes < 0.05 * sizes.max())))

    def test_margins_are_fractal_with_fragments(self):
        smooth, _ = self._edge(0.0)
        edges, fragments = self._edge(CR.DEFAULTS["edge_noise"])
        self.assertGreater(edges, 1.4 * smooth)
        self.assertGreaterEqual(fragments, 3)


class RevisionCrustTest(unittest.TestCase):
    def test_no_patch_no_plateau_keeps_crust(self):
        out = CR.run(ctx3())
        np.testing.assert_array_equal(out["continental"], out["continental_base"])
        self.assertTrue(np.all(out["plateau_id"] == -1))

    def test_land_patch_adds_continental_crust_only_around_its_disc(self):
        ctx = ctx3()
        ctx.tect = {**TECT, "land_patch": [{"name": "fill", "center": [0.0, 150.0], "radius_km": 2000.0,
                                            "edge_noise": 0.4}]}
        out = CR.run(ctx)
        g = ctx.grid
        i = g.cell_index(0.0, 150.0)
        self.assertTrue(out["continental"][i])
        self.assertFalse(out["continental_base"][i])
        far = CR.center_dist(g, [0.0, 150.0]) > 4500.0
        np.testing.assert_array_equal(out["continental"][far], out["continental_base"][far])
        self.assertEqual(out["age_class"][i] == CR.OCEANIC, False)

    def test_plateau_cells_become_continental_crust_with_ids(self):
        ctx = ctx3()
        ctx.tect = {**TECT, "plateau": [{"name": "p", "center": [0.0, 150.0], "area_km2": 3.0e6,
                                         "top_m": [1500.0, 3000.0]}]}
        out = CR.run(ctx)
        i = ctx.grid.cell_index(0.0, 150.0)
        self.assertEqual(out["plateau_id"][i], 0)
        self.assertTrue(out["continental"][i])
        self.assertFalse(out["continental_base"][i])
        self.assertNotEqual(out["age_class"][i], CR.OCEANIC)
        self.assertGreater(out["ocean_age_myr"][i], 0.0, "the plateau keeps the age of the sea floor around it")