Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/mmi shakemaps #6660

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[Nicolas Schmid]
* Improve performance for ShakeMap calculations when spatialcorr and crosscorr
are both set to 'no'
* Add feature to do ShakeMap calculations for vulnerability models using MMI.

[Michele Simionato]
* Supported exposures with generic CSV fields thanks to the `exposureFields`
Expand Down
34 changes: 26 additions & 8 deletions openquake/calculators/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1183,15 +1183,33 @@ def read_shakemap(calc, haz_sitecol, assetcol):
logging.info('Extracted %d assets', len(assetcol))

# assemble dictionary to decide on the calculation method for the gmfs
if oq.spatial_correlation != 'no' or oq.cross_correlation != 'no':
# cross correlation and/or spatial correlation after S&H
gmf_dict = {'kind': 'Silva&Horspool',
'spatialcorr': oq.spatial_correlation,
'crosscorr': oq.cross_correlation,
'cholesky_limit': oq.cholesky_limit}
if 'MMI' in oq.imtls:
# calculations with MMI should be executed
if len(oq.imtls) == 1:
# only MMI intensities
if oq.spatial_correlation != 'no' or oq.cross_correlation != 'no':
logging.warning('Calculations with MMI intensities do not '
'support correlation. No correlations '
'are applied.')

gmf_dict = {'kind': 'mmi'}
else:
# there are also other intensities than MMI
raise RuntimeError(
'There are the following intensities in your model: %s '
'Models mixing MMI and other intensities are not supported. '
% ', '.join(oq.imtls.keys()))
else:
# no correlation required, basic calculation is faster
gmf_dict = {'kind': 'basic'}
# no MMI intensities, calculation with or without correlation
if oq.spatial_correlation != 'no' or oq.cross_correlation != 'no':
# cross correlation and/or spatial correlation after S&H
gmf_dict = {'kind': 'Silva&Horspool',
'spatialcorr': oq.spatial_correlation,
'crosscorr': oq.cross_correlation,
'cholesky_limit': oq.cholesky_limit}
else:
# no correlation required, basic calculation is faster
gmf_dict = {'kind': 'basic'}

logging.info('Building GMFs')
with calc.monitor('building/saving GMFs'):
Expand Down
22 changes: 22 additions & 0 deletions openquake/hazardlib/shakemap/gmfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ def calculate_gmfs_sh(kind, shakemap, imts, Z, mu, spatialcorr,
:param crosscorr: 'no', 'yes' or 'full'
:returns: F(Z, mu) to calculate gmfs
"""
# make sure all imts used have a period, needed for correlation
imts = [im for im in imts if hasattr(im, 'period')]
# checks
N = len(shakemap)
M = len(imts)
Expand Down Expand Up @@ -217,6 +219,26 @@ def calculate_gmfs_basic(kind, shakemap, imts, Z, mu):
return numpy.exp(sig @ Z + numpy.log(mu)) / PCTG


@ calculate_gmfs.add('mmi')
def calculate_gmfs_mmi(kind, shakemap, imts, Z, mu):
"""
Basic calculation method to sample data from shakemap values
given mmi intensities.

:param shakemap: site coordinates with shakemap values
:param imts: list of required imts
:returns: F(Z, mu) to calculate gmfs
"""
try:
# create diag matrix with std values
std = numpy.array(shakemap['std']['MMI'])
sig = numpy.diag(std.flatten()) # shape (M*N, M*N)
except ValueError as e:
raise ValueError('No stds for MMI intensities supplied, only %s' %
', '.join(shakemap['std'].dtype.names)) from e
return sig @ Z + mu


def to_gmfs(shakemap, gmf_dict, site_effects, trunclevel,
num_gmfs, seed, imts=None):
"""
Expand Down
5 changes: 4 additions & 1 deletion openquake/hazardlib/shakemap/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,19 @@
SHAKEMAP_URL = US_GOV + '/fdsnws/event/1/query?eventid={}&format=geojson'
F32 = numpy.float32
SHAKEMAP_FIELDS = set(
'LON LAT SVEL PGA PSA03 PSA10 PSA30 STDPGA STDPSA03 STDPSA10 STDPSA30'
'LON LAT SVEL MMI PGA PSA03 PSA10 PSA30 '
'STDMMI STDPGA STDPSA03 STDPSA10 STDPSA30'
.split())
FIELDMAP = {
'LON': 'lon',
'LAT': 'lat',
'SVEL': 'vs30',
'MMI': ('val', 'MMI'),
'PGA': ('val', 'PGA'),
'PSA03': ('val', 'SA(0.3)'),
'PSA10': ('val', 'SA(1.0)'),
'PSA30': ('val', 'SA(3.0)'),
'STDMMI': ('std', 'MMI'),
'STDPGA': ('std', 'PGA'),
'STDPSA03': ('std', 'SA(0.3)'),
'STDPSA10': ('std', 'SA(1.0)'),
Expand Down
25 changes: 24 additions & 1 deletion openquake/hazardlib/tests/shakemap/shakemap_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def mean_std(shakemap, site_effects):
'spatialcorr': 'yes', 'crosscorr': 'yes'})
_, gmfs = to_gmfs(
shakemap, gmf_dict, site_effects, trunclevel=3,
num_gmfs=1000, seed=42)
num_gmfs=1000, seed=42, imts=['PGA', 'SA(0.3)', 'SA(1.0)', 'SA(3.0)'])
return gmfs.mean(axis=1), numpy.log(gmfs).std(axis=1)


Expand Down Expand Up @@ -159,3 +159,26 @@ def test_from_files(self):
[0.6077153, 0.6661571, 0.6296381, 0.668559],
[0.6146356, 0.6748830, 0.6714424, 0.6613612],
[0.5815353, 0.6460007, 0.6491335, 0.6603457]])

def test_for_mmi(self):
f1 = 'file://' + os.path.join(CDIR, 'ghorka_grid.xml')
f2 = 'file://' + os.path.join(CDIR, 'ghorka_uncertainty.xml')
uridict = dict(kind='usgs_xml', grid_url=f1, uncertainty_url=f2)
sitecol, shakemap, *_ = get_sitecol_shakemap(uridict.pop('kind'),
uridict, imt_dt.names)
n = 4 # number of sites
self.assertEqual(len(sitecol), n)

_, gmfs = to_gmfs(shakemap, {'kind': 'mmi'}, False,
trunclevel=3, num_gmfs=1000, seed=42, imts=['MMI'])

gmf_by_imt = gmfs.mean(axis=1)
std_by_imt = gmfs.std(axis=1)
aae(gmf_by_imt, [[3.80704848],
[3.89791949],
[3.88040454],
[3.93584243]])
aae(std_by_imt, [[0.71068558],
[0.72233552],
[0.72033749],
[0.69906908]])