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,157 @@
|
|
|
1
|
+
"""Isostasy and flexure: Airy roots and the bending of an elastic lithosphere under loads.
|
|
2
|
+
|
|
3
|
+
SI units unless stated otherwise.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from earthsciencekit._validation import model, quantity, require
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"airy_root",
|
|
12
|
+
"flexural_rigidity",
|
|
13
|
+
"flexural_parameter",
|
|
14
|
+
"flexural_deflection",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@model
|
|
19
|
+
def airy_root(elevation, crust_density, mantle_density):
|
|
20
|
+
"""Airy crustal compensation.
|
|
21
|
+
|
|
22
|
+
Crustal buoyancy provides a baseline for mountain-root support.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
elevation : float or array_like
|
|
27
|
+
m; constraint: nonnegative.
|
|
28
|
+
crust_density : float or array_like
|
|
29
|
+
kg/m^3; constraint: positive.
|
|
30
|
+
mantle_density : float or array_like
|
|
31
|
+
kg/m^3; constraint: positive.
|
|
32
|
+
|
|
33
|
+
Returns
|
|
34
|
+
-------
|
|
35
|
+
numpy scalar or ndarray
|
|
36
|
+
Model value [rad/s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
37
|
+
|
|
38
|
+
Notes
|
|
39
|
+
-----
|
|
40
|
+
Local compensation without plate flexure; mantle must be denser than crust.
|
|
41
|
+
Equation: ``elevation * crust_density / (mantle_density - crust_density)``.
|
|
42
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
43
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
44
|
+
"""
|
|
45
|
+
elevation = quantity("elevation", elevation, lower=0)
|
|
46
|
+
crust_density = quantity("crust_density", crust_density, lower=0, strict_lower=True)
|
|
47
|
+
mantle_density = quantity("mantle_density", mantle_density, lower=0, strict_lower=True)
|
|
48
|
+
require(mantle_density > crust_density, "mantle must be denser than crust")
|
|
49
|
+
return elevation * crust_density / (mantle_density - crust_density)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@model
|
|
53
|
+
def flexural_rigidity(young_modulus, elastic_thickness, poisson_ratio):
|
|
54
|
+
"""Elastic lithosphere rigidity.
|
|
55
|
+
|
|
56
|
+
Elastic thickness turns lithospheric strength into a bending resistance.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
young_modulus : float or array_like
|
|
61
|
+
Pa; constraint: positive.
|
|
62
|
+
elastic_thickness : float or array_like
|
|
63
|
+
m; constraint: positive.
|
|
64
|
+
poisson_ratio : float or array_like
|
|
65
|
+
1; constraint: poisson.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
numpy scalar or ndarray
|
|
70
|
+
Model value [rad/s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
71
|
+
|
|
72
|
+
Notes
|
|
73
|
+
-----
|
|
74
|
+
Thin isotropic elastic plate with stable Poisson ratio, not a yielding viscoelastic lithosphere.
|
|
75
|
+
Equation: ``young_modulus * elastic_thickness**3 / (12 * (1 - poisson_ratio**2))``.
|
|
76
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
77
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
78
|
+
"""
|
|
79
|
+
young_modulus = quantity("young_modulus", young_modulus, lower=0, strict_lower=True)
|
|
80
|
+
elastic_thickness = quantity("elastic_thickness", elastic_thickness, lower=0, strict_lower=True)
|
|
81
|
+
poisson_ratio = quantity("poisson_ratio", poisson_ratio, lower=-1, upper=0.5, strict_lower=True, strict_upper=True)
|
|
82
|
+
return young_modulus * elastic_thickness**3 / (12 * (1 - poisson_ratio**2))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@model
|
|
86
|
+
def flexural_parameter(rigidity, density_contrast, gravity):
|
|
87
|
+
"""Lithosphere flexural length.
|
|
88
|
+
|
|
89
|
+
Bending and buoyancy jointly set the scale of load compensation.
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
rigidity : float or array_like
|
|
94
|
+
N m; constraint: positive.
|
|
95
|
+
density_contrast : float or array_like
|
|
96
|
+
kg/m^3; constraint: positive.
|
|
97
|
+
gravity : float or array_like
|
|
98
|
+
m/s^2; constraint: positive.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
numpy scalar or ndarray
|
|
103
|
+
Model value [rad/s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
104
|
+
|
|
105
|
+
Notes
|
|
106
|
+
-----
|
|
107
|
+
Infinite beam-like plate convention alpha to the fourth equals 4D over density contrast times g.
|
|
108
|
+
Equation: ``(4 * rigidity / (density_contrast * gravity))**0.25``.
|
|
109
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
110
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
111
|
+
"""
|
|
112
|
+
rigidity = quantity("rigidity", rigidity, lower=0, strict_lower=True)
|
|
113
|
+
density_contrast = quantity("density_contrast", density_contrast, lower=0, strict_lower=True)
|
|
114
|
+
gravity = quantity("gravity", gravity, lower=0, strict_lower=True)
|
|
115
|
+
return (4 * rigidity / (density_contrast * gravity)) ** 0.25
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@model
|
|
119
|
+
def flexural_deflection(distance, line_load, rigidity, density_contrast, gravity):
|
|
120
|
+
"""Elastic plate deflection under a line load.
|
|
121
|
+
|
|
122
|
+
A load bends the lithosphere into a moat flanked by a peripheral bulge.
|
|
123
|
+
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
distance : float or array_like
|
|
127
|
+
m; constraint: real.
|
|
128
|
+
line_load : float or array_like
|
|
129
|
+
N/m; constraint: nonnegative.
|
|
130
|
+
rigidity : float or array_like
|
|
131
|
+
N m; constraint: positive.
|
|
132
|
+
density_contrast : float or array_like
|
|
133
|
+
kg/m^3; constraint: positive.
|
|
134
|
+
gravity : float or array_like
|
|
135
|
+
m/s^2; constraint: positive.
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
numpy scalar or ndarray
|
|
140
|
+
Model value [m]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
141
|
+
|
|
142
|
+
Notes
|
|
143
|
+
-----
|
|
144
|
+
Unbroken infinite thin elastic plate, deflection positive downward; density contrast is mantle minus infill.
|
|
145
|
+
Equation: ``line_load * alpha**3 / (8 * rigidity) * np.exp(-x) * (np.cos(x) + np.sin(x))``
|
|
146
|
+
with ``x = abs(distance) / alpha`` and ``alpha = (4 * rigidity / (density_contrast * gravity))**0.25``.
|
|
147
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
148
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
149
|
+
"""
|
|
150
|
+
distance = quantity("distance", distance)
|
|
151
|
+
line_load = quantity("line_load", line_load, lower=0)
|
|
152
|
+
rigidity = quantity("rigidity", rigidity, lower=0, strict_lower=True)
|
|
153
|
+
density_contrast = quantity("density_contrast", density_contrast, lower=0, strict_lower=True)
|
|
154
|
+
gravity = quantity("gravity", gravity, lower=0, strict_lower=True)
|
|
155
|
+
alpha = (4 * rigidity / (density_contrast * gravity)) ** 0.25
|
|
156
|
+
scaled = np.abs(distance) / alpha
|
|
157
|
+
return line_load * alpha**3 / (8 * rigidity) * np.exp(-scaled) * (np.cos(scaled) + np.sin(scaled))
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"""Rigid-plate kinematics: Euler rotation, plate speed and displacement, relative Euler vectors and hotspot tracks.
|
|
2
|
+
|
|
3
|
+
SI units unless stated otherwise.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from earthsciencekit._validation import model, quantity, require
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"angular_speed",
|
|
12
|
+
"plate_speed",
|
|
13
|
+
"euler_velocity_x",
|
|
14
|
+
"euler_velocity_y",
|
|
15
|
+
"euler_velocity_z",
|
|
16
|
+
"plate_displacement",
|
|
17
|
+
"hotspot_age",
|
|
18
|
+
"compose_euler_vectors",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@model
|
|
23
|
+
def angular_speed(rotation_angle, time):
|
|
24
|
+
"""Euler-pole angular speed.
|
|
25
|
+
|
|
26
|
+
Rigid plate motion is rotation about an Euler pole.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
rotation_angle : float or array_like
|
|
31
|
+
rad; constraint: real.
|
|
32
|
+
time : float or array_like
|
|
33
|
+
s; constraint: positive.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
numpy scalar or ndarray
|
|
38
|
+
Model value [rad/s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
39
|
+
|
|
40
|
+
Notes
|
|
41
|
+
-----
|
|
42
|
+
Constant angular rate; angular input is radians and output radians per second.
|
|
43
|
+
Equation: ``rotation_angle / time``.
|
|
44
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
45
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
46
|
+
"""
|
|
47
|
+
rotation_angle = quantity("rotation_angle", rotation_angle)
|
|
48
|
+
time = quantity("time", time, lower=0, strict_lower=True)
|
|
49
|
+
return rotation_angle / time
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@model
|
|
53
|
+
def plate_speed(angular_speed, radius, angular_distance):
|
|
54
|
+
"""Rigid plate speed about an Euler pole.
|
|
55
|
+
|
|
56
|
+
Distance from the rotation axis controls surface plate speed.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
angular_speed : float or array_like
|
|
61
|
+
rad/s; constraint: nonnegative.
|
|
62
|
+
radius : float or array_like
|
|
63
|
+
m; constraint: positive.
|
|
64
|
+
angular_distance : float or array_like
|
|
65
|
+
rad; constraint: width.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
numpy scalar or ndarray
|
|
70
|
+
Model value [rad/s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
71
|
+
|
|
72
|
+
Notes
|
|
73
|
+
-----
|
|
74
|
+
Spherical rigid plate, magnitude only; angular distance must be at most pi.
|
|
75
|
+
Equation: ``angular_speed * radius * np.sin(angular_distance)``.
|
|
76
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
77
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
78
|
+
"""
|
|
79
|
+
angular_speed = quantity("angular_speed", angular_speed, lower=0)
|
|
80
|
+
radius = quantity("radius", radius, lower=0, strict_lower=True)
|
|
81
|
+
angular_distance = quantity("angular_distance", angular_distance, lower=0, upper=2 * np.pi)
|
|
82
|
+
require(angular_distance <= np.pi, "angular distance exceeds pi")
|
|
83
|
+
return angular_speed * radius * np.sin(angular_distance)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@model
|
|
87
|
+
def euler_velocity_x(omega_y, omega_z, position_y, position_z):
|
|
88
|
+
"""Euler rotation east-fixed x velocity.
|
|
89
|
+
|
|
90
|
+
The cross product of rotation and position gives Cartesian plate velocity.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
omega_y : float or array_like
|
|
95
|
+
rad/s; constraint: real.
|
|
96
|
+
omega_z : float or array_like
|
|
97
|
+
rad/s; constraint: real.
|
|
98
|
+
position_y : float or array_like
|
|
99
|
+
m; constraint: real.
|
|
100
|
+
position_z : float or array_like
|
|
101
|
+
m; constraint: real.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
numpy scalar or ndarray
|
|
106
|
+
Model value [rad/s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
107
|
+
|
|
108
|
+
Notes
|
|
109
|
+
-----
|
|
110
|
+
Earth-fixed Cartesian axes; x is not the local east component.
|
|
111
|
+
Equation: ``omega_y * position_z - omega_z * position_y``.
|
|
112
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
113
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
114
|
+
"""
|
|
115
|
+
omega_y = quantity("omega_y", omega_y)
|
|
116
|
+
omega_z = quantity("omega_z", omega_z)
|
|
117
|
+
position_y = quantity("position_y", position_y)
|
|
118
|
+
position_z = quantity("position_z", position_z)
|
|
119
|
+
return omega_y * position_z - omega_z * position_y
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@model
|
|
123
|
+
def euler_velocity_y(omega_z, omega_x, position_z, position_x):
|
|
124
|
+
"""Euler rotation y velocity.
|
|
125
|
+
|
|
126
|
+
A rigid plate velocity field is tangent to its spherical path.
|
|
127
|
+
|
|
128
|
+
Parameters
|
|
129
|
+
----------
|
|
130
|
+
omega_z : float or array_like
|
|
131
|
+
rad/s; constraint: real.
|
|
132
|
+
omega_x : float or array_like
|
|
133
|
+
rad/s; constraint: real.
|
|
134
|
+
position_z : float or array_like
|
|
135
|
+
m; constraint: real.
|
|
136
|
+
position_x : float or array_like
|
|
137
|
+
m; constraint: real.
|
|
138
|
+
|
|
139
|
+
Returns
|
|
140
|
+
-------
|
|
141
|
+
numpy scalar or ndarray
|
|
142
|
+
Model value [rad/s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
143
|
+
|
|
144
|
+
Notes
|
|
145
|
+
-----
|
|
146
|
+
Same Earth-fixed Cartesian convention as euler_velocity_x.
|
|
147
|
+
Equation: ``omega_z * position_x - omega_x * position_z``.
|
|
148
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
149
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
150
|
+
"""
|
|
151
|
+
omega_z = quantity("omega_z", omega_z)
|
|
152
|
+
omega_x = quantity("omega_x", omega_x)
|
|
153
|
+
position_z = quantity("position_z", position_z)
|
|
154
|
+
position_x = quantity("position_x", position_x)
|
|
155
|
+
return omega_z * position_x - omega_x * position_z
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@model
|
|
159
|
+
def euler_velocity_z(omega_x, omega_y, position_x, position_y):
|
|
160
|
+
"""Euler rotation polar velocity.
|
|
161
|
+
|
|
162
|
+
The polar velocity component completes the Euler-vector cross product.
|
|
163
|
+
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
omega_x : float or array_like
|
|
167
|
+
rad/s; constraint: real.
|
|
168
|
+
omega_y : float or array_like
|
|
169
|
+
rad/s; constraint: real.
|
|
170
|
+
position_x : float or array_like
|
|
171
|
+
m; constraint: real.
|
|
172
|
+
position_y : float or array_like
|
|
173
|
+
m; constraint: real.
|
|
174
|
+
|
|
175
|
+
Returns
|
|
176
|
+
-------
|
|
177
|
+
numpy scalar or ndarray
|
|
178
|
+
Model value [rad/s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
179
|
+
|
|
180
|
+
Notes
|
|
181
|
+
-----
|
|
182
|
+
Earth-fixed components, not local vertical motion or deformation.
|
|
183
|
+
Equation: ``omega_x * position_y - omega_y * position_x``.
|
|
184
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
185
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
186
|
+
"""
|
|
187
|
+
omega_x = quantity("omega_x", omega_x)
|
|
188
|
+
omega_y = quantity("omega_y", omega_y)
|
|
189
|
+
position_x = quantity("position_x", position_x)
|
|
190
|
+
position_y = quantity("position_y", position_y)
|
|
191
|
+
return omega_x * position_y - omega_y * position_x
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@model
|
|
195
|
+
def plate_displacement(speed, time):
|
|
196
|
+
"""Plate kinematic displacement.
|
|
197
|
+
|
|
198
|
+
Velocity connects short instrumental records with geological displacement.
|
|
199
|
+
|
|
200
|
+
Parameters
|
|
201
|
+
----------
|
|
202
|
+
speed : float or array_like
|
|
203
|
+
m/s; constraint: real.
|
|
204
|
+
time : float or array_like
|
|
205
|
+
s; constraint: nonnegative.
|
|
206
|
+
|
|
207
|
+
Returns
|
|
208
|
+
-------
|
|
209
|
+
numpy scalar or ndarray
|
|
210
|
+
Model value [rad/s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
211
|
+
|
|
212
|
+
Notes
|
|
213
|
+
-----
|
|
214
|
+
Constant signed speed along a local coordinate; not a finite Euler rotation.
|
|
215
|
+
Equation: ``speed * time``.
|
|
216
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
217
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
218
|
+
"""
|
|
219
|
+
speed = quantity("speed", speed)
|
|
220
|
+
time = quantity("time", time, lower=0)
|
|
221
|
+
return speed * time
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@model
|
|
225
|
+
def compose_euler_vectors(omega_ab, omega_bc):
|
|
226
|
+
"""Composition of relative Euler vectors around a plate circuit.
|
|
227
|
+
|
|
228
|
+
Angular velocities of rigid plates add, so two relative motions predict the third.
|
|
229
|
+
|
|
230
|
+
Parameters
|
|
231
|
+
----------
|
|
232
|
+
omega_ab : array_like, shape (..., 3)
|
|
233
|
+
rad/s; constraint: real. Earth-fixed Cartesian Euler vector of plate A relative to plate B.
|
|
234
|
+
omega_bc : array_like, shape (..., 3)
|
|
235
|
+
rad/s; constraint: real. Euler vector of plate B relative to plate C.
|
|
236
|
+
|
|
237
|
+
Returns
|
|
238
|
+
-------
|
|
239
|
+
ndarray, shape (..., 3)
|
|
240
|
+
Model value [rad/s]: the Euler vector of plate A relative to plate C. Leading axes broadcast.
|
|
241
|
+
|
|
242
|
+
Notes
|
|
243
|
+
-----
|
|
244
|
+
Instantaneous (infinitesimal) rotations only; finite rotations do not commute and do not add.
|
|
245
|
+
Closure of the circuit A-B-C means ``omega_ab + omega_bc + omega_ca = 0``.
|
|
246
|
+
Equation: ``omega_ab + omega_bc``.
|
|
247
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
248
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
249
|
+
"""
|
|
250
|
+
omega_ab = quantity("omega_ab", omega_ab)
|
|
251
|
+
omega_bc = quantity("omega_bc", omega_bc)
|
|
252
|
+
require(omega_ab.ndim >= 1 and omega_ab.shape[-1] == 3, "omega_ab must have three Cartesian components on its last axis")
|
|
253
|
+
require(omega_bc.ndim >= 1 and omega_bc.shape[-1] == 3, "omega_bc must have three Cartesian components on its last axis")
|
|
254
|
+
return omega_ab + omega_bc
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
@model
|
|
258
|
+
def hotspot_age(track_length, angular_speed, radius, pole_distance):
|
|
259
|
+
"""Age progression along a hotspot track.
|
|
260
|
+
|
|
261
|
+
A plate moving over a fixed plume leaves volcanoes that age with distance along a small circle.
|
|
262
|
+
|
|
263
|
+
Parameters
|
|
264
|
+
----------
|
|
265
|
+
track_length : float or array_like
|
|
266
|
+
m; constraint: nonnegative.
|
|
267
|
+
angular_speed : float or array_like
|
|
268
|
+
rad/s; constraint: positive.
|
|
269
|
+
radius : float or array_like
|
|
270
|
+
m; constraint: positive.
|
|
271
|
+
pole_distance : float or array_like
|
|
272
|
+
rad; constraint: open interval (0, pi).
|
|
273
|
+
|
|
274
|
+
Returns
|
|
275
|
+
-------
|
|
276
|
+
numpy scalar or ndarray
|
|
277
|
+
Model value [s]. Scalar input returns a NumPy scalar; arrays broadcast.
|
|
278
|
+
|
|
279
|
+
Notes
|
|
280
|
+
-----
|
|
281
|
+
Fixed hotspot and constant Euler rotation of the plate over it; track length is measured along the small circle.
|
|
282
|
+
Equation: ``track_length / (angular_speed * radius * np.sin(pole_distance))``.
|
|
283
|
+
Invalid, empty, nonreal or nonfinite inputs raise ValueError.
|
|
284
|
+
NumPy broadcasting applies; singular and overflowing outputs raise ValueError.
|
|
285
|
+
"""
|
|
286
|
+
track_length = quantity("track_length", track_length, lower=0)
|
|
287
|
+
angular_speed = quantity("angular_speed", angular_speed, lower=0, strict_lower=True)
|
|
288
|
+
radius = quantity("radius", radius, lower=0, strict_lower=True)
|
|
289
|
+
pole_distance = quantity("pole_distance", pole_distance, lower=0, upper=np.pi, strict_lower=True, strict_upper=True)
|
|
290
|
+
return track_length / (angular_speed * radius * np.sin(pole_distance))
|
|
File without changes
|