earthsciencekit 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- earthsciencekit/__init__.py +6 -0
- earthsciencekit/_validation.py +62 -0
- earthsciencekit/atmosphere/__init__.py +57 -0
- earthsciencekit/atmosphere/core/__init__.py +5 -0
- earthsciencekit/atmosphere/core/base.py +10 -0
- earthsciencekit/atmosphere/systems/__init__.py +1 -0
- earthsciencekit/atmosphere/systems/dynamics.py +208 -0
- earthsciencekit/atmosphere/systems/hydrostatics.py +214 -0
- earthsciencekit/atmosphere/systems/moisture.py +162 -0
- earthsciencekit/atmosphere/systems/thermodynamics.py +222 -0
- earthsciencekit/atmosphere/tests/__init__.py +0 -0
- earthsciencekit/atmosphere/tests/test_models.py +741 -0
- earthsciencekit/atmosphere/tests/test_physics.py +81 -0
- earthsciencekit/atmosphere/visualizers/__init__.py +9 -0
- earthsciencekit/climate/__init__.py +63 -0
- earthsciencekit/climate/core/__init__.py +5 -0
- earthsciencekit/climate/core/base.py +10 -0
- earthsciencekit/climate/systems/__init__.py +1 -0
- earthsciencekit/climate/systems/carbon.py +76 -0
- earthsciencekit/climate/systems/forcing.py +124 -0
- earthsciencekit/climate/systems/radiation.py +214 -0
- earthsciencekit/climate/systems/response.py +402 -0
- earthsciencekit/climate/systems/sea_level.py +77 -0
- earthsciencekit/climate/tests/__init__.py +0 -0
- earthsciencekit/climate/tests/test_models.py +1015 -0
- earthsciencekit/climate/tests/test_physics.py +16 -0
- earthsciencekit/climate/visualizers/__init__.py +9 -0
- earthsciencekit/constants/__init__.py +23 -0
- earthsciencekit/geophysics/__init__.py +77 -0
- earthsciencekit/geophysics/core/__init__.py +5 -0
- earthsciencekit/geophysics/core/base.py +10 -0
- earthsciencekit/geophysics/systems/__init__.py +1 -0
- earthsciencekit/geophysics/systems/deformation.py +161 -0
- earthsciencekit/geophysics/systems/dynamo.py +159 -0
- earthsciencekit/geophysics/systems/figure.py +292 -0
- earthsciencekit/geophysics/systems/gravity.py +235 -0
- earthsciencekit/geophysics/systems/magnetism.py +354 -0
- earthsciencekit/geophysics/tests/__init__.py +0 -0
- earthsciencekit/geophysics/tests/test_models.py +898 -0
- earthsciencekit/geophysics/tests/test_physics.py +171 -0
- earthsciencekit/geophysics/visualizers/__init__.py +9 -0
- earthsciencekit/integrators/__init__.py +62 -0
- earthsciencekit/oceanography/__init__.py +61 -0
- earthsciencekit/oceanography/core/__init__.py +5 -0
- earthsciencekit/oceanography/core/base.py +10 -0
- earthsciencekit/oceanography/systems/__init__.py +1 -0
- earthsciencekit/oceanography/systems/circulation.py +388 -0
- earthsciencekit/oceanography/systems/hydrography.py +212 -0
- earthsciencekit/oceanography/systems/inertial.py +86 -0
- earthsciencekit/oceanography/systems/waves.py +281 -0
- earthsciencekit/oceanography/tests/__init__.py +0 -0
- earthsciencekit/oceanography/tests/test_models.py +916 -0
- earthsciencekit/oceanography/tests/test_physics.py +102 -0
- earthsciencekit/oceanography/visualizers/__init__.py +9 -0
- earthsciencekit/plate_tectonics/__init__.py +59 -0
- earthsciencekit/plate_tectonics/core/__init__.py +5 -0
- earthsciencekit/plate_tectonics/core/base.py +10 -0
- earthsciencekit/plate_tectonics/systems/__init__.py +1 -0
- earthsciencekit/plate_tectonics/systems/boundaries.py +201 -0
- earthsciencekit/plate_tectonics/systems/cooling.py +238 -0
- earthsciencekit/plate_tectonics/systems/isostasy.py +157 -0
- earthsciencekit/plate_tectonics/systems/kinematics.py +290 -0
- earthsciencekit/plate_tectonics/tests/__init__.py +0 -0
- earthsciencekit/plate_tectonics/tests/test_models.py +920 -0
- earthsciencekit/plate_tectonics/tests/test_physics.py +94 -0
- earthsciencekit/plate_tectonics/visualizers/__init__.py +9 -0
- earthsciencekit/py.typed +0 -0
- earthsciencekit/results.py +73 -0
- earthsciencekit/seismology/__init__.py +59 -0
- earthsciencekit/seismology/core/__init__.py +5 -0
- earthsciencekit/seismology/core/base.py +10 -0
- earthsciencekit/seismology/systems/__init__.py +1 -0
- earthsciencekit/seismology/systems/interfaces.py +102 -0
- earthsciencekit/seismology/systems/rays.py +221 -0
- earthsciencekit/seismology/systems/sources.py +249 -0
- earthsciencekit/seismology/systems/waves.py +268 -0
- earthsciencekit/seismology/tests/__init__.py +0 -0
- earthsciencekit/seismology/tests/test_models.py +852 -0
- earthsciencekit/seismology/tests/test_physics.py +100 -0
- earthsciencekit/seismology/visualizers/__init__.py +9 -0
- earthsciencekit/tests/__init__.py +0 -0
- earthsciencekit/tests/test_core.py +181 -0
- earthsciencekit/tests/test_relations.py +36 -0
- earthsciencekit/units/__init__.py +66 -0
- earthsciencekit/visualizers/__init__.py +45 -0
- earthsciencekit/volcanology/__init__.py +61 -0
- earthsciencekit/volcanology/core/__init__.py +5 -0
- earthsciencekit/volcanology/core/base.py +10 -0
- earthsciencekit/volcanology/systems/__init__.py +1 -0
- earthsciencekit/volcanology/systems/eruptions.py +161 -0
- earthsciencekit/volcanology/systems/geochemistry.py +226 -0
- earthsciencekit/volcanology/systems/geochronology.py +304 -0
- earthsciencekit/volcanology/systems/magma.py +190 -0
- earthsciencekit/volcanology/tests/__init__.py +0 -0
- earthsciencekit/volcanology/tests/test_models.py +485 -0
- earthsciencekit/volcanology/tests/test_physics.py +176 -0
- earthsciencekit/volcanology/visualizers/__init__.py +9 -0
- earthsciencekit-0.2.0.dist-info/METADATA +127 -0
- earthsciencekit-0.2.0.dist-info/RECORD +102 -0
- earthsciencekit-0.2.0.dist-info/WHEEL +5 -0
- earthsciencekit-0.2.0.dist-info/licenses/LICENSE +15 -0
- earthsciencekit-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,916 @@
|
|
|
1
|
+
"""Golden checks and invalid-input contracts for every public model."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from earthsciencekit import oceanography as domain
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_hydrostatic_pressure_reference():
|
|
10
|
+
result = domain.hydrostatic_pressure(*[1000, 100, 10])
|
|
11
|
+
np.testing.assert_allclose(result, 1e6, rtol=1e-11, atol=1e-12)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
15
|
+
def test_hydrostatic_pressure_rejects_invalid(bad):
|
|
16
|
+
args = [1000, 100, 10]
|
|
17
|
+
args[0] = bad
|
|
18
|
+
with pytest.raises(ValueError):
|
|
19
|
+
domain.hydrostatic_pressure(*args)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_linear_density_reference():
|
|
23
|
+
result = domain.linear_density(*[1000, 1, 0, 0.0002, 0.0008])
|
|
24
|
+
np.testing.assert_allclose(result, 999.8, rtol=1e-11, atol=1e-12)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
28
|
+
def test_linear_density_rejects_invalid(bad):
|
|
29
|
+
args = [1000, 1, 0, 0.0002, 0.0008]
|
|
30
|
+
args[0] = bad
|
|
31
|
+
with pytest.raises(ValueError):
|
|
32
|
+
domain.linear_density(*args)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_buoyancy_frequency_squared_reference():
|
|
36
|
+
result = domain.buoyancy_frequency_squared(*[1000, -0.01, 10])
|
|
37
|
+
np.testing.assert_allclose(result, 0.0001, rtol=1e-11, atol=1e-12)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
41
|
+
def test_buoyancy_frequency_squared_rejects_invalid(bad):
|
|
42
|
+
args = [1000, -0.01, 10]
|
|
43
|
+
args[0] = bad
|
|
44
|
+
with pytest.raises(ValueError):
|
|
45
|
+
domain.buoyancy_frequency_squared(*args)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_geostrophic_current_reference():
|
|
49
|
+
result = domain.geostrophic_current(*[1e-05, 0.0001, 10])
|
|
50
|
+
np.testing.assert_allclose(result, 1, rtol=1e-11, atol=1e-12)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
54
|
+
def test_geostrophic_current_rejects_invalid(bad):
|
|
55
|
+
args = [1e-05, 0.0001, 10]
|
|
56
|
+
args[0] = bad
|
|
57
|
+
with pytest.raises(ValueError):
|
|
58
|
+
domain.geostrophic_current(*args)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_ekman_transport_reference():
|
|
62
|
+
result = domain.ekman_transport(*[0.1, 1000, 0.0001])
|
|
63
|
+
np.testing.assert_allclose(result, 1, rtol=1e-11, atol=1e-12)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
67
|
+
def test_ekman_transport_rejects_invalid(bad):
|
|
68
|
+
args = [0.1, 1000, 0.0001]
|
|
69
|
+
args[0] = bad
|
|
70
|
+
with pytest.raises(ValueError):
|
|
71
|
+
domain.ekman_transport(*args)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_inertial_period_reference():
|
|
75
|
+
result = domain.inertial_period(*[0.0001])
|
|
76
|
+
np.testing.assert_allclose(result, 2 * np.pi * 1e4, rtol=1e-11, atol=1e-12)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
80
|
+
def test_inertial_period_rejects_invalid(bad):
|
|
81
|
+
args = [0.0001]
|
|
82
|
+
args[0] = bad
|
|
83
|
+
with pytest.raises(ValueError):
|
|
84
|
+
domain.inertial_period(*args)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_shallow_wave_speed_reference():
|
|
88
|
+
result = domain.shallow_wave_speed(*[100, 10])
|
|
89
|
+
np.testing.assert_allclose(result, np.sqrt(1000), rtol=1e-11, atol=1e-12)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
93
|
+
def test_shallow_wave_speed_rejects_invalid(bad):
|
|
94
|
+
args = [100, 10]
|
|
95
|
+
args[0] = bad
|
|
96
|
+
with pytest.raises(ValueError):
|
|
97
|
+
domain.shallow_wave_speed(*args)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_deep_wave_speed_reference():
|
|
101
|
+
result = domain.deep_wave_speed(*[6.283185307179586, 10])
|
|
102
|
+
np.testing.assert_allclose(result, np.sqrt(10), rtol=1e-11, atol=1e-12)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
106
|
+
def test_deep_wave_speed_rejects_invalid(bad):
|
|
107
|
+
args = [6.283185307179586, 10]
|
|
108
|
+
args[0] = bad
|
|
109
|
+
with pytest.raises(ValueError):
|
|
110
|
+
domain.deep_wave_speed(*args)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_wave_angular_frequency_reference():
|
|
114
|
+
result = domain.wave_angular_frequency(*[1, 1, 10])
|
|
115
|
+
np.testing.assert_allclose(result, np.sqrt(10 * np.tanh(1)), rtol=1e-11, atol=1e-12)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
119
|
+
def test_wave_angular_frequency_rejects_invalid(bad):
|
|
120
|
+
args = [1, 1, 10]
|
|
121
|
+
args[0] = bad
|
|
122
|
+
with pytest.raises(ValueError):
|
|
123
|
+
domain.wave_angular_frequency(*args)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_deep_group_speed_reference():
|
|
127
|
+
result = domain.deep_group_speed(*[6.283185307179586, 10])
|
|
128
|
+
np.testing.assert_allclose(result, 0.5 * np.sqrt(10), rtol=1e-11, atol=1e-12)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
132
|
+
def test_deep_group_speed_rejects_invalid(bad):
|
|
133
|
+
args = [6.283185307179586, 10]
|
|
134
|
+
args[0] = bad
|
|
135
|
+
with pytest.raises(ValueError):
|
|
136
|
+
domain.deep_group_speed(*args)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def test_rossby_radius_reference():
|
|
140
|
+
result = domain.rossby_radius(*[0.01, 1000, 0.0001])
|
|
141
|
+
np.testing.assert_allclose(result, 1e5 / np.pi, rtol=1e-11, atol=1e-12)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
145
|
+
def test_rossby_radius_rejects_invalid(bad):
|
|
146
|
+
args = [0.01, 1000, 0.0001]
|
|
147
|
+
args[0] = bad
|
|
148
|
+
with pytest.raises(ValueError):
|
|
149
|
+
domain.rossby_radius(*args)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_reduced_gravity_reference():
|
|
153
|
+
result = domain.reduced_gravity(*[2, 1000, 10])
|
|
154
|
+
np.testing.assert_allclose(result, 0.02, rtol=1e-11, atol=1e-12)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
158
|
+
def test_reduced_gravity_rejects_invalid(bad):
|
|
159
|
+
args = [2, 1000, 10]
|
|
160
|
+
args[0] = bad
|
|
161
|
+
with pytest.raises(ValueError):
|
|
162
|
+
domain.reduced_gravity(*args)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def test_internal_wave_speed_reference():
|
|
166
|
+
result = domain.internal_wave_speed(*[0.02, 100, 100])
|
|
167
|
+
np.testing.assert_allclose(result, 1, rtol=1e-11, atol=1e-12)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
171
|
+
def test_internal_wave_speed_rejects_invalid(bad):
|
|
172
|
+
args = [0.02, 100, 100]
|
|
173
|
+
args[0] = bad
|
|
174
|
+
with pytest.raises(ValueError):
|
|
175
|
+
domain.internal_wave_speed(*args)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def test_volume_transport_reference():
|
|
179
|
+
result = domain.volume_transport(*[1, 1000, 100])
|
|
180
|
+
np.testing.assert_allclose(result, 1e5, rtol=1e-11, atol=1e-12)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
184
|
+
def test_volume_transport_rejects_invalid(bad):
|
|
185
|
+
args = [1, 1000, 100]
|
|
186
|
+
args[0] = bad
|
|
187
|
+
with pytest.raises(ValueError):
|
|
188
|
+
domain.volume_transport(*args)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_tidal_elevation_reference():
|
|
192
|
+
result = domain.tidal_elevation(*[0, 2, 12, 0])
|
|
193
|
+
np.testing.assert_allclose(result, 2, rtol=1e-11, atol=1e-12)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
197
|
+
def test_tidal_elevation_rejects_invalid(bad):
|
|
198
|
+
args = [0, 2, 12, 0]
|
|
199
|
+
args[0] = bad
|
|
200
|
+
with pytest.raises(ValueError):
|
|
201
|
+
domain.tidal_elevation(*args)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def test_hydrostatic_pressure_broadcasting():
|
|
205
|
+
args = [1000, 100, 10]
|
|
206
|
+
reference = domain.hydrostatic_pressure(*args)
|
|
207
|
+
args[0] = np.full((2, 1), args[0])
|
|
208
|
+
result = domain.hydrostatic_pressure(*args)
|
|
209
|
+
assert result.shape == (2, 1)
|
|
210
|
+
np.testing.assert_allclose(result, reference)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def test_hydrostatic_pressure_density_physical_bound():
|
|
214
|
+
args = [1000, 100, 10]
|
|
215
|
+
args[0] = 0
|
|
216
|
+
with pytest.raises(ValueError):
|
|
217
|
+
domain.hydrostatic_pressure(*args)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def test_hydrostatic_pressure_depth_physical_bound():
|
|
221
|
+
args = [1000, 100, 10]
|
|
222
|
+
args[1] = -1
|
|
223
|
+
with pytest.raises(ValueError):
|
|
224
|
+
domain.hydrostatic_pressure(*args)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def test_hydrostatic_pressure_gravity_physical_bound():
|
|
228
|
+
args = [1000, 100, 10]
|
|
229
|
+
args[2] = 0
|
|
230
|
+
with pytest.raises(ValueError):
|
|
231
|
+
domain.hydrostatic_pressure(*args)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def test_linear_density_broadcasting():
|
|
235
|
+
args = [1000, 1, 0, 0.0002, 0.0008]
|
|
236
|
+
reference = domain.linear_density(*args)
|
|
237
|
+
args[0] = np.full((2, 1), args[0])
|
|
238
|
+
result = domain.linear_density(*args)
|
|
239
|
+
assert result.shape == (2, 1)
|
|
240
|
+
np.testing.assert_allclose(result, reference)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def test_linear_density_reference_density_physical_bound():
|
|
244
|
+
args = [1000, 1, 0, 0.0002, 0.0008]
|
|
245
|
+
args[0] = 0
|
|
246
|
+
with pytest.raises(ValueError):
|
|
247
|
+
domain.linear_density(*args)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def test_linear_density_thermal_expansion_physical_bound():
|
|
251
|
+
args = [1000, 1, 0, 0.0002, 0.0008]
|
|
252
|
+
args[3] = -1
|
|
253
|
+
with pytest.raises(ValueError):
|
|
254
|
+
domain.linear_density(*args)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def test_linear_density_haline_contraction_physical_bound():
|
|
258
|
+
args = [1000, 1, 0, 0.0002, 0.0008]
|
|
259
|
+
args[4] = -1
|
|
260
|
+
with pytest.raises(ValueError):
|
|
261
|
+
domain.linear_density(*args)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def test_buoyancy_frequency_squared_broadcasting():
|
|
265
|
+
args = [1000, -0.01, 10]
|
|
266
|
+
reference = domain.buoyancy_frequency_squared(*args)
|
|
267
|
+
args[0] = np.full((2, 1), args[0])
|
|
268
|
+
result = domain.buoyancy_frequency_squared(*args)
|
|
269
|
+
assert result.shape == (2, 1)
|
|
270
|
+
np.testing.assert_allclose(result, reference)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def test_buoyancy_frequency_squared_density_physical_bound():
|
|
274
|
+
args = [1000, -0.01, 10]
|
|
275
|
+
args[0] = 0
|
|
276
|
+
with pytest.raises(ValueError):
|
|
277
|
+
domain.buoyancy_frequency_squared(*args)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def test_buoyancy_frequency_squared_gravity_physical_bound():
|
|
281
|
+
args = [1000, -0.01, 10]
|
|
282
|
+
args[2] = 0
|
|
283
|
+
with pytest.raises(ValueError):
|
|
284
|
+
domain.buoyancy_frequency_squared(*args)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def test_geostrophic_current_broadcasting():
|
|
288
|
+
args = [1e-05, 0.0001, 10]
|
|
289
|
+
reference = domain.geostrophic_current(*args)
|
|
290
|
+
args[0] = np.full((2, 1), args[0])
|
|
291
|
+
result = domain.geostrophic_current(*args)
|
|
292
|
+
assert result.shape == (2, 1)
|
|
293
|
+
np.testing.assert_allclose(result, reference)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def test_geostrophic_current_coriolis_physical_bound():
|
|
297
|
+
args = [1e-05, 0.0001, 10]
|
|
298
|
+
args[1] = 0
|
|
299
|
+
with pytest.raises(ValueError):
|
|
300
|
+
domain.geostrophic_current(*args)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def test_geostrophic_current_gravity_physical_bound():
|
|
304
|
+
args = [1e-05, 0.0001, 10]
|
|
305
|
+
args[2] = 0
|
|
306
|
+
with pytest.raises(ValueError):
|
|
307
|
+
domain.geostrophic_current(*args)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def test_ekman_transport_broadcasting():
|
|
311
|
+
args = [0.1, 1000, 0.0001]
|
|
312
|
+
reference = domain.ekman_transport(*args)
|
|
313
|
+
args[0] = np.full((2, 1), args[0])
|
|
314
|
+
result = domain.ekman_transport(*args)
|
|
315
|
+
assert result.shape == (2, 1)
|
|
316
|
+
np.testing.assert_allclose(result, reference)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def test_ekman_transport_density_physical_bound():
|
|
320
|
+
args = [0.1, 1000, 0.0001]
|
|
321
|
+
args[1] = 0
|
|
322
|
+
with pytest.raises(ValueError):
|
|
323
|
+
domain.ekman_transport(*args)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def test_ekman_transport_coriolis_physical_bound():
|
|
327
|
+
args = [0.1, 1000, 0.0001]
|
|
328
|
+
args[2] = 0
|
|
329
|
+
with pytest.raises(ValueError):
|
|
330
|
+
domain.ekman_transport(*args)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def test_inertial_period_broadcasting():
|
|
334
|
+
args = [0.0001]
|
|
335
|
+
reference = domain.inertial_period(*args)
|
|
336
|
+
args[0] = np.full((2, 1), args[0])
|
|
337
|
+
result = domain.inertial_period(*args)
|
|
338
|
+
assert result.shape == (2, 1)
|
|
339
|
+
np.testing.assert_allclose(result, reference)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def test_inertial_period_coriolis_physical_bound():
|
|
343
|
+
args = [0.0001]
|
|
344
|
+
args[0] = 0
|
|
345
|
+
with pytest.raises(ValueError):
|
|
346
|
+
domain.inertial_period(*args)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def test_shallow_wave_speed_broadcasting():
|
|
350
|
+
args = [100, 10]
|
|
351
|
+
reference = domain.shallow_wave_speed(*args)
|
|
352
|
+
args[0] = np.full((2, 1), args[0])
|
|
353
|
+
result = domain.shallow_wave_speed(*args)
|
|
354
|
+
assert result.shape == (2, 1)
|
|
355
|
+
np.testing.assert_allclose(result, reference)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def test_shallow_wave_speed_depth_physical_bound():
|
|
359
|
+
args = [100, 10]
|
|
360
|
+
args[0] = 0
|
|
361
|
+
with pytest.raises(ValueError):
|
|
362
|
+
domain.shallow_wave_speed(*args)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def test_shallow_wave_speed_gravity_physical_bound():
|
|
366
|
+
args = [100, 10]
|
|
367
|
+
args[1] = 0
|
|
368
|
+
with pytest.raises(ValueError):
|
|
369
|
+
domain.shallow_wave_speed(*args)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def test_deep_wave_speed_broadcasting():
|
|
373
|
+
args = [6.283185307179586, 10]
|
|
374
|
+
reference = domain.deep_wave_speed(*args)
|
|
375
|
+
args[0] = np.full((2, 1), args[0])
|
|
376
|
+
result = domain.deep_wave_speed(*args)
|
|
377
|
+
assert result.shape == (2, 1)
|
|
378
|
+
np.testing.assert_allclose(result, reference)
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def test_deep_wave_speed_wavelength_physical_bound():
|
|
382
|
+
args = [6.283185307179586, 10]
|
|
383
|
+
args[0] = 0
|
|
384
|
+
with pytest.raises(ValueError):
|
|
385
|
+
domain.deep_wave_speed(*args)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def test_deep_wave_speed_gravity_physical_bound():
|
|
389
|
+
args = [6.283185307179586, 10]
|
|
390
|
+
args[1] = 0
|
|
391
|
+
with pytest.raises(ValueError):
|
|
392
|
+
domain.deep_wave_speed(*args)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def test_wave_angular_frequency_broadcasting():
|
|
396
|
+
args = [1, 1, 10]
|
|
397
|
+
reference = domain.wave_angular_frequency(*args)
|
|
398
|
+
args[0] = np.full((2, 1), args[0])
|
|
399
|
+
result = domain.wave_angular_frequency(*args)
|
|
400
|
+
assert result.shape == (2, 1)
|
|
401
|
+
np.testing.assert_allclose(result, reference)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def test_wave_angular_frequency_wavenumber_physical_bound():
|
|
405
|
+
args = [1, 1, 10]
|
|
406
|
+
args[0] = 0
|
|
407
|
+
with pytest.raises(ValueError):
|
|
408
|
+
domain.wave_angular_frequency(*args)
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def test_wave_angular_frequency_depth_physical_bound():
|
|
412
|
+
args = [1, 1, 10]
|
|
413
|
+
args[1] = 0
|
|
414
|
+
with pytest.raises(ValueError):
|
|
415
|
+
domain.wave_angular_frequency(*args)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def test_wave_angular_frequency_gravity_physical_bound():
|
|
419
|
+
args = [1, 1, 10]
|
|
420
|
+
args[2] = 0
|
|
421
|
+
with pytest.raises(ValueError):
|
|
422
|
+
domain.wave_angular_frequency(*args)
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def test_deep_group_speed_broadcasting():
|
|
426
|
+
args = [6.283185307179586, 10]
|
|
427
|
+
reference = domain.deep_group_speed(*args)
|
|
428
|
+
args[0] = np.full((2, 1), args[0])
|
|
429
|
+
result = domain.deep_group_speed(*args)
|
|
430
|
+
assert result.shape == (2, 1)
|
|
431
|
+
np.testing.assert_allclose(result, reference)
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def test_deep_group_speed_wavelength_physical_bound():
|
|
435
|
+
args = [6.283185307179586, 10]
|
|
436
|
+
args[0] = 0
|
|
437
|
+
with pytest.raises(ValueError):
|
|
438
|
+
domain.deep_group_speed(*args)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def test_deep_group_speed_gravity_physical_bound():
|
|
442
|
+
args = [6.283185307179586, 10]
|
|
443
|
+
args[1] = 0
|
|
444
|
+
with pytest.raises(ValueError):
|
|
445
|
+
domain.deep_group_speed(*args)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def test_rossby_radius_broadcasting():
|
|
449
|
+
args = [0.01, 1000, 0.0001]
|
|
450
|
+
reference = domain.rossby_radius(*args)
|
|
451
|
+
args[0] = np.full((2, 1), args[0])
|
|
452
|
+
result = domain.rossby_radius(*args)
|
|
453
|
+
assert result.shape == (2, 1)
|
|
454
|
+
np.testing.assert_allclose(result, reference)
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def test_rossby_radius_buoyancy_frequency_physical_bound():
|
|
458
|
+
args = [0.01, 1000, 0.0001]
|
|
459
|
+
args[0] = 0
|
|
460
|
+
with pytest.raises(ValueError):
|
|
461
|
+
domain.rossby_radius(*args)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def test_rossby_radius_depth_physical_bound():
|
|
465
|
+
args = [0.01, 1000, 0.0001]
|
|
466
|
+
args[1] = 0
|
|
467
|
+
with pytest.raises(ValueError):
|
|
468
|
+
domain.rossby_radius(*args)
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def test_rossby_radius_coriolis_physical_bound():
|
|
472
|
+
args = [0.01, 1000, 0.0001]
|
|
473
|
+
args[2] = 0
|
|
474
|
+
with pytest.raises(ValueError):
|
|
475
|
+
domain.rossby_radius(*args)
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
def test_reduced_gravity_broadcasting():
|
|
479
|
+
args = [2, 1000, 10]
|
|
480
|
+
reference = domain.reduced_gravity(*args)
|
|
481
|
+
args[0] = np.full((2, 1), args[0])
|
|
482
|
+
result = domain.reduced_gravity(*args)
|
|
483
|
+
assert result.shape == (2, 1)
|
|
484
|
+
np.testing.assert_allclose(result, reference)
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def test_reduced_gravity_density_difference_physical_bound():
|
|
488
|
+
args = [2, 1000, 10]
|
|
489
|
+
args[0] = -1
|
|
490
|
+
with pytest.raises(ValueError):
|
|
491
|
+
domain.reduced_gravity(*args)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def test_reduced_gravity_reference_density_physical_bound():
|
|
495
|
+
args = [2, 1000, 10]
|
|
496
|
+
args[1] = 0
|
|
497
|
+
with pytest.raises(ValueError):
|
|
498
|
+
domain.reduced_gravity(*args)
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def test_reduced_gravity_gravity_physical_bound():
|
|
502
|
+
args = [2, 1000, 10]
|
|
503
|
+
args[2] = 0
|
|
504
|
+
with pytest.raises(ValueError):
|
|
505
|
+
domain.reduced_gravity(*args)
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
def test_internal_wave_speed_broadcasting():
|
|
509
|
+
args = [0.02, 100, 100]
|
|
510
|
+
reference = domain.internal_wave_speed(*args)
|
|
511
|
+
args[0] = np.full((2, 1), args[0])
|
|
512
|
+
result = domain.internal_wave_speed(*args)
|
|
513
|
+
assert result.shape == (2, 1)
|
|
514
|
+
np.testing.assert_allclose(result, reference)
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def test_internal_wave_speed_reduced_gravity_physical_bound():
|
|
518
|
+
args = [0.02, 100, 100]
|
|
519
|
+
args[0] = 0
|
|
520
|
+
with pytest.raises(ValueError):
|
|
521
|
+
domain.internal_wave_speed(*args)
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
def test_internal_wave_speed_upper_depth_physical_bound():
|
|
525
|
+
args = [0.02, 100, 100]
|
|
526
|
+
args[1] = 0
|
|
527
|
+
with pytest.raises(ValueError):
|
|
528
|
+
domain.internal_wave_speed(*args)
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
def test_internal_wave_speed_lower_depth_physical_bound():
|
|
532
|
+
args = [0.02, 100, 100]
|
|
533
|
+
args[2] = 0
|
|
534
|
+
with pytest.raises(ValueError):
|
|
535
|
+
domain.internal_wave_speed(*args)
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
def test_volume_transport_broadcasting():
|
|
539
|
+
args = [1, 1000, 100]
|
|
540
|
+
reference = domain.volume_transport(*args)
|
|
541
|
+
args[0] = np.full((2, 1), args[0])
|
|
542
|
+
result = domain.volume_transport(*args)
|
|
543
|
+
assert result.shape == (2, 1)
|
|
544
|
+
np.testing.assert_allclose(result, reference)
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def test_volume_transport_width_physical_bound():
|
|
548
|
+
args = [1, 1000, 100]
|
|
549
|
+
args[1] = 0
|
|
550
|
+
with pytest.raises(ValueError):
|
|
551
|
+
domain.volume_transport(*args)
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
def test_volume_transport_depth_physical_bound():
|
|
555
|
+
args = [1, 1000, 100]
|
|
556
|
+
args[2] = 0
|
|
557
|
+
with pytest.raises(ValueError):
|
|
558
|
+
domain.volume_transport(*args)
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
def test_tidal_elevation_broadcasting():
|
|
562
|
+
args = [0, 2, 12, 0]
|
|
563
|
+
reference = domain.tidal_elevation(*args)
|
|
564
|
+
args[0] = np.full((2, 1), args[0])
|
|
565
|
+
result = domain.tidal_elevation(*args)
|
|
566
|
+
assert result.shape == (2, 1)
|
|
567
|
+
np.testing.assert_allclose(result, reference)
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
def test_tidal_elevation_amplitude_physical_bound():
|
|
571
|
+
args = [0, 2, 12, 0]
|
|
572
|
+
args[1] = -1
|
|
573
|
+
with pytest.raises(ValueError):
|
|
574
|
+
domain.tidal_elevation(*args)
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def test_tidal_elevation_period_physical_bound():
|
|
578
|
+
args = [0, 2, 12, 0]
|
|
579
|
+
args[2] = 0
|
|
580
|
+
with pytest.raises(ValueError):
|
|
581
|
+
domain.tidal_elevation(*args)
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def test_gerstner_orbit_radius_reference():
|
|
585
|
+
result = domain.gerstner_orbit_radius(*[0.6931471805599453, 0.5, 1])
|
|
586
|
+
np.testing.assert_allclose(result, 0.25, rtol=1e-11, atol=1e-12)
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
590
|
+
def test_gerstner_orbit_radius_rejects_invalid(bad):
|
|
591
|
+
args = [0.6931471805599453, 0.5, 1]
|
|
592
|
+
args[0] = bad
|
|
593
|
+
with pytest.raises(ValueError):
|
|
594
|
+
domain.gerstner_orbit_radius(*args)
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def test_gerstner_orbit_radius_broadcasting():
|
|
598
|
+
args = [0.6931471805599453, 0.5, 1]
|
|
599
|
+
reference = domain.gerstner_orbit_radius(*args)
|
|
600
|
+
args[0] = np.full((2, 1), args[0])
|
|
601
|
+
result = domain.gerstner_orbit_radius(*args)
|
|
602
|
+
assert result.shape == (2, 1)
|
|
603
|
+
np.testing.assert_allclose(result, reference)
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
def test_gerstner_orbit_radius_rest_depth_physical_bound():
|
|
607
|
+
args = [0.6931471805599453, 0.5, 1]
|
|
608
|
+
args[0] = -1
|
|
609
|
+
with pytest.raises(ValueError):
|
|
610
|
+
domain.gerstner_orbit_radius(*args)
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
def test_gerstner_orbit_radius_amplitude_physical_bound():
|
|
614
|
+
args = [0.6931471805599453, 0.5, 1]
|
|
615
|
+
args[1] = -1
|
|
616
|
+
with pytest.raises(ValueError):
|
|
617
|
+
domain.gerstner_orbit_radius(*args)
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
def test_gerstner_orbit_radius_wavenumber_physical_bound():
|
|
621
|
+
args = [0.6931471805599453, 0.5, 1]
|
|
622
|
+
args[2] = 0
|
|
623
|
+
with pytest.raises(ValueError):
|
|
624
|
+
domain.gerstner_orbit_radius(*args)
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def test_sverdrup_transport_reference():
|
|
628
|
+
result = domain.sverdrup_transport(*[6, 2, 3])
|
|
629
|
+
np.testing.assert_allclose(result, 1, rtol=1e-11, atol=1e-12)
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
633
|
+
def test_sverdrup_transport_rejects_invalid(bad):
|
|
634
|
+
args = [6, 2, 3]
|
|
635
|
+
args[0] = bad
|
|
636
|
+
with pytest.raises(ValueError):
|
|
637
|
+
domain.sverdrup_transport(*args)
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
def test_sverdrup_transport_broadcasting():
|
|
641
|
+
args = [6, 2, 3]
|
|
642
|
+
reference = domain.sverdrup_transport(*args)
|
|
643
|
+
args[0] = np.full((2, 1), args[0])
|
|
644
|
+
result = domain.sverdrup_transport(*args)
|
|
645
|
+
assert result.shape == (2, 1)
|
|
646
|
+
np.testing.assert_allclose(result, reference)
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
def test_sverdrup_transport_density_physical_bound():
|
|
650
|
+
args = [6, 2, 3]
|
|
651
|
+
args[1] = 0
|
|
652
|
+
with pytest.raises(ValueError):
|
|
653
|
+
domain.sverdrup_transport(*args)
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
def test_sverdrup_transport_beta_physical_bound():
|
|
657
|
+
args = [6, 2, 3]
|
|
658
|
+
args[2] = 0
|
|
659
|
+
with pytest.raises(ValueError):
|
|
660
|
+
domain.sverdrup_transport(*args)
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
def test_stommel_streamfunction_reference():
|
|
664
|
+
result = domain.stommel_streamfunction(*[1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1])
|
|
665
|
+
np.testing.assert_allclose(result, 1 - 1 / np.cosh(1), rtol=1e-11, atol=1e-12)
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
669
|
+
def test_stommel_streamfunction_rejects_invalid(bad):
|
|
670
|
+
args = [1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1]
|
|
671
|
+
args[0] = bad
|
|
672
|
+
with pytest.raises(ValueError):
|
|
673
|
+
domain.stommel_streamfunction(*args)
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def test_stommel_streamfunction_broadcasting():
|
|
677
|
+
args = [1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1]
|
|
678
|
+
reference = domain.stommel_streamfunction(*args)
|
|
679
|
+
args[0] = np.full((2, 1), args[0])
|
|
680
|
+
result = domain.stommel_streamfunction(*args)
|
|
681
|
+
assert result.shape == (2, 1)
|
|
682
|
+
np.testing.assert_allclose(result, reference)
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
def test_stommel_streamfunction_x_physical_bound():
|
|
686
|
+
args = [1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1]
|
|
687
|
+
args[0] = -1
|
|
688
|
+
with pytest.raises(ValueError):
|
|
689
|
+
domain.stommel_streamfunction(*args)
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
def test_stommel_streamfunction_y_physical_bound():
|
|
693
|
+
args = [1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1]
|
|
694
|
+
args[1] = -1
|
|
695
|
+
with pytest.raises(ValueError):
|
|
696
|
+
domain.stommel_streamfunction(*args)
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
def test_stommel_streamfunction_basin_width_physical_bound():
|
|
700
|
+
args = [1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1]
|
|
701
|
+
args[3] = 0
|
|
702
|
+
with pytest.raises(ValueError):
|
|
703
|
+
domain.stommel_streamfunction(*args)
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
def test_stommel_streamfunction_basin_length_physical_bound():
|
|
707
|
+
args = [1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1]
|
|
708
|
+
args[4] = 0
|
|
709
|
+
with pytest.raises(ValueError):
|
|
710
|
+
domain.stommel_streamfunction(*args)
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
def test_stommel_streamfunction_density_physical_bound():
|
|
714
|
+
args = [1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1]
|
|
715
|
+
args[5] = 0
|
|
716
|
+
with pytest.raises(ValueError):
|
|
717
|
+
domain.stommel_streamfunction(*args)
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
def test_stommel_streamfunction_beta_physical_bound():
|
|
721
|
+
args = [1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1]
|
|
722
|
+
args[6] = -1
|
|
723
|
+
with pytest.raises(ValueError):
|
|
724
|
+
domain.stommel_streamfunction(*args)
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
def test_stommel_streamfunction_friction_physical_bound():
|
|
728
|
+
args = [1, 0.5 * np.pi, 1, 2, np.pi, 1, 0, 1]
|
|
729
|
+
args[7] = 0
|
|
730
|
+
with pytest.raises(ValueError):
|
|
731
|
+
domain.stommel_streamfunction(*args)
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
def test_thermohaline_forcing_reference():
|
|
735
|
+
result = domain.thermohaline_forcing(*[-1, 2, 3])
|
|
736
|
+
np.testing.assert_allclose(result, 1, rtol=1e-11, atol=1e-12)
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
740
|
+
def test_thermohaline_forcing_rejects_invalid(bad):
|
|
741
|
+
args = [-1, 2, 3]
|
|
742
|
+
args[0] = bad
|
|
743
|
+
with pytest.raises(ValueError):
|
|
744
|
+
domain.thermohaline_forcing(*args)
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
def test_thermohaline_forcing_broadcasting():
|
|
748
|
+
args = [-1, 2, 3]
|
|
749
|
+
reference = domain.thermohaline_forcing(*args)
|
|
750
|
+
args[0] = np.full((2, 1), args[0])
|
|
751
|
+
result = domain.thermohaline_forcing(*args)
|
|
752
|
+
assert result.shape == (2, 1)
|
|
753
|
+
np.testing.assert_allclose(result, reference)
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
def test_thermohaline_forcing_thermal_flow_physical_bound():
|
|
757
|
+
args = [-1, 2, 3]
|
|
758
|
+
args[1] = 0
|
|
759
|
+
with pytest.raises(ValueError):
|
|
760
|
+
domain.thermohaline_forcing(*args)
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
def test_thermohaline_forcing_haline_coefficient_physical_bound():
|
|
764
|
+
args = [-1, 2, 3]
|
|
765
|
+
args[2] = 0
|
|
766
|
+
with pytest.raises(ValueError):
|
|
767
|
+
domain.thermohaline_forcing(*args)
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
def test_abyssal_temperature_reference():
|
|
771
|
+
result = domain.abyssal_temperature(*[0.6931471805599453, 1, 4, 1.3862943611198906, 1, 1])
|
|
772
|
+
np.testing.assert_allclose(result, 2, rtol=1e-11, atol=1e-12)
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
776
|
+
def test_abyssal_temperature_rejects_invalid(bad):
|
|
777
|
+
args = [0.6931471805599453, 1, 4, 1.3862943611198906, 1, 1]
|
|
778
|
+
args[0] = bad
|
|
779
|
+
with pytest.raises(ValueError):
|
|
780
|
+
domain.abyssal_temperature(*args)
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
def test_abyssal_temperature_broadcasting():
|
|
784
|
+
args = [0.6931471805599453, 1, 4, 1.3862943611198906, 1, 1]
|
|
785
|
+
reference = domain.abyssal_temperature(*args)
|
|
786
|
+
args[0] = np.full((2, 1), args[0])
|
|
787
|
+
result = domain.abyssal_temperature(*args)
|
|
788
|
+
assert result.shape == (2, 1)
|
|
789
|
+
np.testing.assert_allclose(result, reference)
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
def test_abyssal_temperature_height_physical_bound():
|
|
793
|
+
args = [0.6931471805599453, 1, 4, 1.3862943611198906, 1, 1]
|
|
794
|
+
args[0] = -1
|
|
795
|
+
with pytest.raises(ValueError):
|
|
796
|
+
domain.abyssal_temperature(*args)
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
def test_abyssal_temperature_bottom_temperature_physical_bound():
|
|
800
|
+
args = [0.6931471805599453, 1, 4, 1.3862943611198906, 1, 1]
|
|
801
|
+
args[1] = 0
|
|
802
|
+
with pytest.raises(ValueError):
|
|
803
|
+
domain.abyssal_temperature(*args)
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
def test_abyssal_temperature_top_temperature_physical_bound():
|
|
807
|
+
args = [0.6931471805599453, 1, 4, 1.3862943611198906, 1, 1]
|
|
808
|
+
args[2] = 0
|
|
809
|
+
with pytest.raises(ValueError):
|
|
810
|
+
domain.abyssal_temperature(*args)
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
def test_abyssal_temperature_column_height_physical_bound():
|
|
814
|
+
args = [0.6931471805599453, 1, 4, 1.3862943611198906, 1, 1]
|
|
815
|
+
args[3] = 0
|
|
816
|
+
with pytest.raises(ValueError):
|
|
817
|
+
domain.abyssal_temperature(*args)
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
def test_abyssal_temperature_diffusivity_physical_bound():
|
|
821
|
+
args = [0.6931471805599453, 1, 4, 1.3862943611198906, 1, 1]
|
|
822
|
+
args[4] = 0
|
|
823
|
+
with pytest.raises(ValueError):
|
|
824
|
+
domain.abyssal_temperature(*args)
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
def test_abyssal_temperature_upwelling_physical_bound():
|
|
828
|
+
args = [0.6931471805599453, 1, 4, 1.3862943611198906, 1, 1]
|
|
829
|
+
args[5] = 0
|
|
830
|
+
with pytest.raises(ValueError):
|
|
831
|
+
domain.abyssal_temperature(*args)
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
def test_simplified_seawater_density_reference():
|
|
835
|
+
result = domain.simplified_seawater_density(*[293.15, 36, 0])
|
|
836
|
+
np.testing.assert_allclose(result, 1026 - 1.655 * (1 + 0.2976) + 0.76554 * (1 - 0.5 * 7.4914e-4) - 0.024341, rtol=1e-11, atol=1e-12)
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
840
|
+
def test_simplified_seawater_density_rejects_invalid(bad):
|
|
841
|
+
args = [293.15, 36, 0]
|
|
842
|
+
args[0] = bad
|
|
843
|
+
with pytest.raises(ValueError):
|
|
844
|
+
domain.simplified_seawater_density(*args)
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
def test_simplified_seawater_density_broadcasting():
|
|
848
|
+
args = [293.15, 36, 0]
|
|
849
|
+
reference = domain.simplified_seawater_density(*args)
|
|
850
|
+
args[0] = np.full((2, 1), args[0])
|
|
851
|
+
result = domain.simplified_seawater_density(*args)
|
|
852
|
+
assert result.shape == (2, 1)
|
|
853
|
+
np.testing.assert_allclose(result, reference)
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
def test_simplified_seawater_density_conservative_temperature_physical_bound():
|
|
857
|
+
args = [293.15, 36, 0]
|
|
858
|
+
args[0] = 0
|
|
859
|
+
with pytest.raises(ValueError):
|
|
860
|
+
domain.simplified_seawater_density(*args)
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
def test_simplified_seawater_density_absolute_salinity_physical_bound():
|
|
864
|
+
args = [293.15, 36, 0]
|
|
865
|
+
args[1] = -1
|
|
866
|
+
with pytest.raises(ValueError):
|
|
867
|
+
domain.simplified_seawater_density(*args)
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
def test_simplified_seawater_density_depth_physical_bound():
|
|
871
|
+
args = [293.15, 36, 0]
|
|
872
|
+
args[2] = -1
|
|
873
|
+
with pytest.raises(ValueError):
|
|
874
|
+
domain.simplified_seawater_density(*args)
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
def test_ekman_spiral_velocity_reference():
|
|
878
|
+
result = domain.ekman_spiral_velocity(*[0, 1, 1, 0.5, 2])
|
|
879
|
+
np.testing.assert_allclose(result, [np.sqrt(0.5), np.sqrt(0.5)], rtol=1e-11, atol=1e-12)
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf, [], "bad", True, 1j])
|
|
883
|
+
def test_ekman_spiral_velocity_rejects_invalid(bad):
|
|
884
|
+
args = [0, 1, 1, 0.5, 2]
|
|
885
|
+
args[0] = bad
|
|
886
|
+
with pytest.raises(ValueError):
|
|
887
|
+
domain.ekman_spiral_velocity(*args)
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
def test_ekman_spiral_velocity_broadcasting():
|
|
891
|
+
result = domain.ekman_spiral_velocity(np.zeros((2, 1)), 1, 1, 0.5, 2)
|
|
892
|
+
assert result.shape == (2, 1, 2)
|
|
893
|
+
np.testing.assert_allclose(result, np.sqrt(0.5))
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
@pytest.mark.parametrize("index,value", [(0, -1), (2, 0), (3, 0), (4, 0)])
|
|
897
|
+
def test_ekman_spiral_velocity_physical_bound(index, value):
|
|
898
|
+
args = [0, 1, 1, 0.5, 2]
|
|
899
|
+
args[index] = value
|
|
900
|
+
with pytest.raises(ValueError):
|
|
901
|
+
domain.ekman_spiral_velocity(*args)
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
@pytest.mark.parametrize(
|
|
905
|
+
"function,args",
|
|
906
|
+
[
|
|
907
|
+
(domain.gerstner_orbit_radius, [0, 2, 1]),
|
|
908
|
+
(domain.stommel_streamfunction, [3, 1, 1, 2, np.pi, 1, 0, 1]),
|
|
909
|
+
(domain.stommel_streamfunction, [1, 4, 1, 2, np.pi, 1, 0, 1]),
|
|
910
|
+
(domain.thermohaline_forcing, [3, 2, 1]),
|
|
911
|
+
(domain.abyssal_temperature, [2, 1, 4, 1, 1, 1]),
|
|
912
|
+
],
|
|
913
|
+
)
|
|
914
|
+
def test_new_model_cross_parameter_rejections(function, args):
|
|
915
|
+
with pytest.raises(ValueError):
|
|
916
|
+
function(*args)
|