14 Commits

Author SHA1 Message Date
ff3af6a769 Update src/seismic_hazard_forecasting.py 2025-09-19 11:50:08 +02:00
b6375203b5 Update src/seismic_hazard_forecasting.py 2025-09-19 11:42:20 +02:00
02c9537ef9 Update src/seismic_hazard_forecasting.py 2025-09-19 09:51:10 +02:00
47d6d39d91 Update src/seismic_hazard_forecasting.py 2025-09-18 14:20:33 +02:00
2efa92f59c Update src/seismic_hazard_forecasting.py 2025-08-27 12:35:15 +02:00
5eea239f3d Update src/seismic_hazard_forecasting.py 2025-08-27 12:27:20 +02:00
30f6cdcbe2 Update src/seismic_hazard_forecasting.py 2025-08-26 16:35:25 +02:00
6cb4f7210d Update src/seismic_hazard_forecasting.py 2025-08-26 16:22:47 +02:00
a4b4a552fe Update src/seismic_hazard_forecasting.py 2025-08-19 12:54:50 +02:00
a8233950e1 Merge pull request 'Fixes issue related to use of Cython' (!21) from EPOSDEV-68 into master
Reviewed-on: #21
2025-08-12 12:56:15 +02:00
86da5c3246 Update src/seismic_hazard_forecasting.py 2025-08-08 18:28:34 +02:00
9e75e0e768 Merge pull request 'upload Lasocki2013 ground motion model' (!20) from lasocki2013_gmm into master
Reviewed-on: #20
2025-07-11 11:28:58 +02:00
a73f17fc35 upload Lasocki2013 ground motion model 2025-07-10 11:05:36 +02:00
2fbca21917 Merge pull request 'enable cython' (!19) from ftong-patch-cython into master
Reviewed-on: #19
Reviewed-by: asia <asia@noreply.example.org>
2025-07-10 09:36:22 +02:00
2 changed files with 172 additions and 6 deletions

142
gsim/lasocki_2013.py Normal file
View File

@@ -0,0 +1,142 @@
# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2013-2023 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.
"""
Module exports :class:`Lasocki2013`.
"""
import numpy as np
from scipy.constants import g
from openquake.hazardlib.gsim.base import GMPE, CoeffsTable
from openquake.hazardlib import const
from openquake.hazardlib.imt import PGA, PGV, SA
def get_magnitude_energy(mag):
"""
Converts magnitude to energy-based magnitude term.
"""
return 1.15 + 1.96 * mag
def get_distance_term(coeffs, repi):
"""
Computes the distance term using the given GMPE coefficients.
"""
R_h = np.sqrt(repi ** 2 + coeffs["c7"] ** 2)
return np.log10(R_h)
def get_standard_deviation(coeffs, coeffs_cov, magE, repi):
"""
Computes the standard deviation term.
"""
Cb = np.array(list(coeffs_cov)).reshape(3,3)
R_h = np.sqrt(repi ** 2 + coeffs["c7"] ** 2)
X0 = np.array([1, magE[0], np.log10(R_h[0]**2)])
variance_term = np.sqrt(X0 @ Cb @ X0 + coeffs["sigma"]**2)
return variance_term
class Lasocki2013(GMPE):
"""
Implement equation developed by Lasocki in "REPORT ON THE ATTENUATION
RELATIONS OF PEAK GROUND ACCELERATION AND SPECTRAL ORDINATES OF GROUND
MOTION FOR MINING-INDUCED SEISMIC EVENTS IN THE REGION OF THE ŻELAZNY
MOST REPOSITORY", 2009.
Equation coefficients provided for the random horizontal component
"""
#: Supported tectonic region type is induced, given
#: that the equations have been derived for the LGCD mining area
DEFINED_FOR_TECTONIC_REGION_TYPE = const.TRT.INDUCED
#: Supported intensity measure types are spectral acceleration,
#: and peak ground acceleration
DEFINED_FOR_INTENSITY_MEASURE_TYPES = {PGA, SA}
#: Supported intensity measure component is random horizontal
#: :attr:`~openquake.hazardlib.const.IMC.RANDOM_HORIZONTAL`,
DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = const.IMC.RANDOM_HORIZONTAL
# DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = const.IMC.VERTICAL
#: Supported standard deviation type is total
DEFINED_FOR_STANDARD_DEVIATION_TYPES = {const.StdDev.TOTAL}
#: site params are not required
REQUIRES_SITES_PARAMETERS = set()
#: Required rupture parameter is magnitude
REQUIRES_RUPTURE_PARAMETERS = {'mag'}
#: Required distance measure is epicentral distance
#: see paragraph 'Predictor Variables', page 6.
REQUIRES_DISTANCES = {'repi'}
def compute(self, ctx: np.recarray, imts, mean, sig, tau, phi):
"""
Computes mean ground motion values and standard deviations for Lasocki (2013) GMPE.
Parameters:
repi (float): Epicentral distance (m)
mag (float): Earthquake magnitude
imts (list of str): List of intensity measure types (e.g., 'PHA', 'PVA')
mean (np.array): Array to store computed mean values
sig (np.array): Array to store computed standard deviations
"""
# Loop through each IMT and compute values
for i, imt in enumerate(imts):
C = self.COEFFS[imt]
C_cov = self.COEFFS_COV[imt]
mag = ctx.mag
repi = ctx.repi*1000.0 # Convert distance from km to m
# Compute magnitude energy term
magE = get_magnitude_energy(mag)
# Compute GMPE terms
mag_term = C['c1'] + C['c2'] * magE
dist_term = C['c5'] * get_distance_term(C, repi)
# Compute mean ground motion
imean = mag_term + dist_term
mean_value = np.log((10 ** imean) / g) # Convert to natural log scale and divide by g
mean[i] = mean_value
# Compute standard deviation
sigma = get_standard_deviation(C, C_cov, magE, repi)
sig[i] = sigma
#: coefficient table provided by report
COEFFS = CoeffsTable(sa_damping=5, table="""\
IMT c1 c2 c5 c7 sigma N
pga 1.25 0.31 -1.34 558 0.196 1196
0.6 -3.86 0.55 -0.65 183 0.242 1194
1.0 -3.94 0.62 -0.66 308 0.262 1197
2.0 -1.14 0.47 -1.02 741 0.235 1195
5.0 0.99 0.31 -1.15 690 0.234 1206
10.0 3.06 0.27 -1.65 906 0.203 1192
20.0 2.62 0.27 -1.60 435 0.196 1191
50.0 2.09 0.27 -1.48 375 0.204 1191
""")
COEFFS_COV = CoeffsTable(sa_damping=5, table="""\
IMT Cb00 Cb01 Cb02 Cb10 Cb11 Cb12 Cb20 Cb21 Cb22
pga 0.005586 -0.000376 -0.000752 -0.000376 0.000103 -0.000111 -0.000752 -0.000111 0.000440
0.6 0.007509 -0.000662 -0.000688 -0.000662 0.000161 -0.000154 -0.000688 -0.000154 0.000516
1.0 0.009119 -0.00075 -0.000948 -0.00075 0.000189 -0.000187 -0.000948 -0.000187 0.000657
2.0 0.008563 -0.000514 -0.001282 -0.000514 0.000147 -0.000164 -0.001282 -0.000164 0.000696
5.0 0.008283 -0.000516 -0.001202 -0.000516 0.000145 -0.000161 -0.001202 -0.000161 0.000668
10.0 0.006904 -0.00036 -0.001145 -0.00036 0.000108 -0.000126 -0.001145 -0.000126 0.000578
20.0 0.005389 -0.000396 -0.000658 -0.000396 0.000104 -0.000107 -0.000658 -0.000107 0.000408
50.0 0.005874 -0.000449 -0.000678 -0.000449 0.000114 -0.000114 -0.000678 -0.000114 0.000428
""")

View File

@@ -4,6 +4,27 @@
def main(catalog_file, mc_file, pdf_file, m_file, m_select, mag_label, mc, m_max, def main(catalog_file, mc_file, pdf_file, m_file, m_select, mag_label, mc, m_max,
m_kde_method, xy_select, grid_dim, xy_win_method, rate_select, time_win_duration, m_kde_method, xy_select, grid_dim, xy_win_method, rate_select, time_win_duration,
forecast_select, custom_rate, forecast_len, time_unit, model, products_string, verbose): forecast_select, custom_rate, forecast_len, time_unit, model, products_string, verbose):
#catalog_file = 'LGCD_catalog_2024.mat'
mc_file = None
pdf_file = None
m_file = None
m_select = True
mag_label = 'Mw'
mc = 1.8
m_max = 4.5
m_kde_method = 'arviz-silverman'
xy_select = True
grid_dim = 5000
xy_win_method = False
rate_select = True
time_win_duration = 100
forecast_select = True
custom_rate = None
forecast_len = 100
time_unit = 'days'
model = 'Lasocki2013'
products_string = 'PGA'
verbose = True
""" """
Python application that reads an earthquake catalog and performs seismic hazard forecasting. Python application that reads an earthquake catalog and performs seismic hazard forecasting.
Arguments: Arguments:
@@ -52,7 +73,7 @@ def main(catalog_file, mc_file, pdf_file, m_file, m_select, mag_label, mc, m_max
from math import ceil, floor, isnan from math import ceil, floor, isnan
import numpy as np import numpy as np
import dask import dask
from dask.diagnostics import ProgressBar # use Dask progress bar # from dask.diagnostics import ProgressBar # use Dask progress bar
import kalepy as kale import kalepy as kale
import utm import utm
from skimage.transform import resize from skimage.transform import resize
@@ -69,6 +90,7 @@ def main(catalog_file, mc_file, pdf_file, m_file, m_select, mag_label, mc, m_max
from matplotlib.contour import ContourSet from matplotlib.contour import ContourSet
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
import json import json
from concurrent.futures import ThreadPoolExecutor
logger = getDefaultLogger('igfash') logger = getDefaultLogger('igfash')
@@ -111,7 +133,7 @@ verbose: {verbose}")
logger.debug(f"Rbeast version {version('rbeast')}") logger.debug(f"Rbeast version {version('rbeast')}")
logger.debug(f"Dask version {version('dask')}") logger.debug(f"Dask version {version('dask')}")
dask.config.set(scheduler='processes') dask.config.set(scheduler='threads', pool=ThreadPoolExecutor(16))
# run magnitude distribution modeling if selected by user and no magnitude pdf file provided # run magnitude distribution modeling if selected by user and no magnitude pdf file provided
if m_select and m_range[0] == None and m_pdf[0] == None: if m_select and m_range[0] == None and m_pdf[0] == None:
@@ -366,7 +388,9 @@ verbose: {verbose}")
# Assign probabilities # Assign probabilities
lambdas, lambdas_perc = lambda_probs(act_rate, dates_calc, bin_edges) lambdas, lambdas_perc = lambda_probs(act_rate, dates_calc, bin_edges)
lambdas = np.array(lambdas, dtype='d')
lambdas_perc = np.array(lambdas_perc, dtype='d')
# print("Forecasted activity rates: ", lambdas, "events per", time_unit[:-1]) # print("Forecasted activity rates: ", lambdas, "events per", time_unit[:-1])
logger.info(f"Forecasted activity rates: {lambdas} events per {time_unit} with percentages {lambdas_perc}") logger.info(f"Forecasted activity rates: {lambdas} events per {time_unit} with percentages {lambdas_perc}")
np.savetxt('activity_rate.csv', np.vstack((lambdas, lambdas_perc)).T, header="lambda, percentage", np.savetxt('activity_rate.csv', np.vstack((lambdas, lambdas_perc)).T, header="lambda, percentage",
@@ -452,11 +476,11 @@ verbose: {verbose}")
start = timer() start = timer()
use_pp = False use_pp = True
if use_pp: # use dask parallel computing if use_pp: # use dask parallel computing
pbar = ProgressBar() # pbar = ProgressBar()
pbar.register() # pbar.register()
# iter = range(0,len(distances)) # iter = range(0,len(distances))
iter = indices iter = indices
iml_grid_raw = [] # raw ground motion grids iml_grid_raw = [] # raw ground motion grids