ground_motion_lib/
gmm.rs

1//! Ground Motion Prediction Equation (GMPE) definitions and traits.
2//!
3//! This module provides fundamental data structures and traits for representing
4//! seismic input points, earthquake parameters, and ground motion model outputs.
5//! It also defines the core trait for implementing specific GMPE models.
6
7use serde::{Deserialize, Serialize};
8
9/// Input point definition for which GMPE will be calculated.
10#[derive(Debug, Serialize, Deserialize)]
11pub struct Vs30Point {
12    /// Longitude in decimal degrees. Example: `142.23567`
13    pub lon: f64,
14    /// Latitude in decimal degrees. Example: `50.35927`
15    pub lat: f64,
16    /// Average shear-wave velocity (Vs, in m/s) in the top 30 meters of soil.
17    pub vs30: f64,
18    /// Depth (in meters) to the subsurface layer where Vs reaches 1400 m/s at the site.
19    #[serde(default)]
20    pub dl: Option<f64>,
21    /// Binary variable (0 or 1) indicating the site's position relative to the volcanic front
22    /// (specific to Japan).
23    #[serde(default)]
24    pub xvf: Option<u8>,
25}
26
27/// Magnitude type used in GMPE calculations.
28#[derive(Debug)]
29pub enum Magnitude {
30    /// Moment magnitude (Mw)
31    Mw,
32    /// Local magnitude (Ml)
33    Ml,
34}
35
36/// Represents an earthquake event with its source parameters.
37#[derive(Debug)]
38pub struct Earthquake {
39    /// Longitude in decimal degrees.
40    pub lon: f64,
41    /// Latitude in decimal degrees.
42    pub lat: f64,
43    /// Earthquake focal depth in kilometers.
44    pub depth: f64,
45    /// Magnitude value.
46    pub magnitude: f64,
47    /// Type of magnitude scale (Mw, Ml, etc.)
48    pub magnitude_kind: Magnitude,
49}
50
51/// Available GMPE output types.
52#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
53pub enum GmpePointKind {
54    /// Peak Ground Acceleration, expressed as a percentage of gravity (%g)
55    Pga,
56    /// Peak Spectral Acceleration, expressed as a percentage of gravity (%g)
57    Psa,
58    /// Peak Ground Velocity, expressed in cm/s
59    Pgv,
60}
61
62/// Struct representing a point with a computed GMPE value.
63#[derive(Debug, Serialize, Deserialize)]
64pub struct GmpePoint {
65    /// Longitude in decimal degrees.
66    pub lon: f64,
67    /// Latitude in decimal degrees.
68    pub lat: f64,
69    /// Computed ground motion value.
70    pub value: f64,
71    /// Type of GMPE output value.
72    pub kind: GmpePointKind,
73}
74
75/// Trait representing a Ground Motion Prediction Equation (GMPE).
76///
77/// Implementors of this trait can compute ground motion values at a site
78/// for a given earthquake scenario.
79pub trait GroundMotionModeling {
80    /// Compute ground motion value for a given input point and earthquake.
81    ///
82    /// # Arguments
83    ///
84    /// * `point` - Input site point parameters.
85    /// * `eq` - Earthquake source parameters.
86    ///
87    /// # Returns
88    ///
89    /// A `GmpePoint` containing the computed value and its location.
90    fn calc_from_point(&self, point: &Vs30Point, eq: &Earthquake) -> GmpePoint;
91}
92
93impl Vs30Point {
94    /// Create a new Vs30Point instance.
95    ///
96    /// # Arguments
97    ///
98    /// * `lon` - Longitude in decimal degrees.
99    /// * `lat` - Latitude in decimal degrees.
100    /// * `vs30` - Average Vs in the top 30 meters.
101    /// * `dl` - Depth to Vs=1400 m/s layer (optional).
102    /// * `xvf` - Binary volcanic front position indicator (optional).
103    ///
104    /// # Example
105    ///
106    /// ```
107    /// use ground_motion_lib::gmm::Vs30Point;
108    /// let vs30_point = Vs30Point::new(142.523, 52.913, 300., Some(250.), Some(1));
109    /// println!("Point is {vs30_point:?}");
110    /// ```
111    pub fn new(lon: f64, lat: f64, vs30: f64, dl: Option<f64>, xvf: Option<u8>) -> Self {
112        Self {
113            lon,
114            lat,
115            vs30,
116            dl,
117            xvf,
118        }
119    }
120
121    /// Calculate ground motion value for this point and given earthquake, using a GMPE.
122    ///
123    /// # Arguments
124    ///
125    /// * `gmpe` - Reference to a type implementing `GroundMotionModeling`.
126    /// * `eq` - Earthquake source parameters.
127    ///
128    /// # Returns
129    ///
130    /// A `GmpePoint` with the computed value.
131    pub fn get_gm<T: GroundMotionModeling>(&self, gmpe: &T, eq: &Earthquake) -> GmpePoint {
132        gmpe.calc_from_point(self, eq)
133    }
134}
135
136impl Earthquake {
137    /// Create a new Earthquake instance.
138    ///
139    /// # Arguments
140    ///
141    /// * `lon` - Longitude in decimal degrees.
142    /// * `lat` - Latitude in decimal degrees.
143    /// * `depth` - Focal depth in kilometers.
144    /// * `magnitude` - Magnitude value.
145    /// * `magnitude_kind` - Type of magnitude scale.
146    pub fn new(lon: f64, lat: f64, depth: f64, magnitude: f64, magnitude_kind: Magnitude) -> Self {
147        Self {
148            lon,
149            lat,
150            depth,
151            magnitude,
152            magnitude_kind,
153        }
154    }
155
156    /// Convenience constructor for Local magnitude (Ml).
157    pub fn new_ml(lon: f64, lat: f64, depth: f64, magnitude: f64) -> Self {
158        Self::new(lon, lat, depth, magnitude, Magnitude::Ml)
159    }
160
161    /// Convenience constructor for Moment magnitude (Mw).
162    pub fn new_mw(lon: f64, lat: f64, depth: f64, magnitude: f64) -> Self {
163        Self::new(lon, lat, depth, magnitude, Magnitude::Mw)
164    }
165}
166
167impl GmpePoint {
168    /// Create a new GmpePoint instance.
169    pub fn new(lon: f64, lat: f64, value: f64, kind: GmpePointKind) -> Self {
170        Self {
171            lon,
172            lat,
173            value,
174            kind,
175        }
176    }
177
178    /// Create a new Peak Ground Acceleration (PGA) point.
179    pub fn new_pga(lon: f64, lat: f64, value: f64) -> Self {
180        Self::new(lon, lat, value, GmpePointKind::Pga)
181    }
182
183    /// Create a new Peak Ground Velocity (PGV) point.
184    pub fn new_pgv(lon: f64, lat: f64, value: f64) -> Self {
185        Self::new(lon, lat, value, GmpePointKind::Pgv)
186    }
187
188    /// Create a new Peak Spectral Acceleration (PSA) point.
189    pub fn new_psa(lon: f64, lat: f64, value: f64) -> Self {
190        Self::new(lon, lat, value, GmpePointKind::Psa)
191    }
192}