Skip to content

Commit 2ad40e3

Browse files
authored
Merge pull request #10093 from gem/read_sections
Added functionality to read multi fault sources
2 parents d199967 + e82cb37 commit 2ad40e3

File tree

7 files changed

+63
-19
lines changed

7 files changed

+63
-19
lines changed

debian/changelog

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
[Michele Simionato]
2+
* Internal: added utility function readinput.read_source_models
3+
14
[Manuela Villani]
25
* Improved the "Governing MCE" plot
36

openquake/calculators/preclassical.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
from openquake.hazardlib import pmf, geo, source_reader
2727
from openquake.baselib.general import AccumDict, groupby, block_splitter
2828
from openquake.hazardlib.contexts import read_cmakers
29-
from openquake.hazardlib.geo.surface.multi import build_secparams
3029
from openquake.hazardlib.source.point import grid_point_sources
3130
from openquake.hazardlib.source.base import get_code2cls
3231
from openquake.hazardlib.sourceconverter import SourceGroup
@@ -278,9 +277,8 @@ def populate_csm(self):
278277
else:
279278
normal_sources.extend(sg)
280279
if multifaults:
281-
# this is ultra-fast
282-
sections = multifaults[0].get_sections()
283-
secparams = build_secparams(sections)
280+
with hdf5.File(multifaults[0].hdf5path, 'r') as h5:
281+
secparams = h5['secparams'][:]
284282
logging.warning(
285283
'There are %d multiFaultSources (secparams=%s)',
286284
len(multifaults), general.humansize(secparams.nbytes))

openquake/commonlib/readinput.py

+21
Original file line numberDiff line numberDiff line change
@@ -1638,3 +1638,24 @@ def read_countries_df(buffer=0.1):
16381638
fname = os.path.join(os.path.dirname(global_risk.__file__),
16391639
'geoBoundariesCGAZ_ADM0.shp')
16401640
return read_geometries(fname, 'shapeGroup', buffer)
1641+
1642+
1643+
def read_source_models(fnames, hdf5path='', **converterparams):
1644+
"""
1645+
:param fnames: a list of source model files
1646+
:param hdf5path: auxiliary .hdf5 file used to store the multifault sources
1647+
:param converterparams: a dictionary of parameters like rupture_mesh_spacing
1648+
:returns: a list of SourceModel instances
1649+
"""
1650+
converter = sourceconverter.SourceConverter()
1651+
vars(converter).update(converterparams)
1652+
smodels = list(nrml.read_source_models(fnames, converter))
1653+
smdict = dict(zip(fnames, smodels))
1654+
src_groups = [sg for sm in smdict.values() for sg in sm.src_groups]
1655+
secparams = source_reader.fix_geometry_sections(smdict, src_groups, hdf5path)
1656+
for smodel in smodels:
1657+
for sg in smodel.src_groups:
1658+
for src in sg:
1659+
if src.code == b'F': # multifault
1660+
src.set_msparams(secparams)
1661+
return smodels

openquake/commonlib/tests/readinput_test.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from openquake.risklib import asset
3232
from openquake.commonlib import readinput, datastore
3333
from openquake.qa_tests_data.logictree import case_02, case_15, case_21
34-
from openquake.qa_tests_data.classical import case_34
34+
from openquake.qa_tests_data.classical import case_34, case_65
3535
from openquake.qa_tests_data.event_based import case_16
3636
from openquake.qa_tests_data.event_based_risk import case_2, case_caracas
3737
from openquake.qa_tests_data import mosaic
@@ -564,3 +564,18 @@ def test_read_station_data(self):
564564
readinput.get_station_data(oq, sitecol)
565565
self.assertIn("Stations_NIED.csv: has duplicate sites ['GIF001', 'GIF013']",
566566
str(ctx.exception))
567+
568+
569+
class ReadSourceModelsTestCase(unittest.TestCase):
570+
def test(self):
571+
base = os.path.dirname(case_65.__file__)
572+
hdf5path = general.gettemp(suffix='.hdf5')
573+
fnames = [os.path.join(base, 'ssm.xml'), os.path.join(base, 'sections.xml')]
574+
smodels = readinput.read_source_models(fnames, hdf5path, investigation_time=1.)
575+
nrups = 0
576+
for smodel in smodels:
577+
for sg in smodel.src_groups:
578+
for src in sg:
579+
for rup in src.iter_ruptures():
580+
nrups += 1
581+
self.assertEqual(nrups, 3)

openquake/hazardlib/contexts.py

+1
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ class Oq(object):
198198
"""
199199
mea_tau_phi = False
200200
split_sources = True
201+
use_rates = False
201202

202203
def __init__(self, **hparams):
203204
vars(self).update(hparams)

openquake/hazardlib/source/multi_fault.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
NonParametricSeismicSource as NP)
3232
from openquake.hazardlib.geo.surface.kite_fault import (
3333
geom_to_kite, kite_to_geom)
34-
from openquake.hazardlib.geo.surface.multi import MultiSurface, build_msparams
34+
from openquake.hazardlib.geo.surface.multi import (
35+
MultiSurface, build_msparams, build_secparams)
3536
from openquake.hazardlib.geo.utils import (
3637
angular_distance, KM_TO_DEGREES, get_spherical_bounding_box)
3738
from openquake.hazardlib.source.base import BaseSeismicSource
@@ -335,6 +336,7 @@ def save_and_split(mfsources, sectiondict, hdf5path, site1=None,
335336
split_dic[src.source_id].append(split)
336337
h5.save_vlen('multi_fault_sections',
337338
[kite_to_geom(sec) for sec in sectiondict.values()])
339+
h5['secparams'] = build_secparams(src.get_sections())
338340

339341
return split_dic
340342

@@ -346,7 +348,7 @@ def load(hdf5path):
346348
srcs = []
347349
with hdf5.File(hdf5path, 'r') as h5:
348350
for key in list(h5):
349-
if key == 'multi_fault_sections':
351+
if key in ('multi_fault_sections', 'secparams'):
350352
continue
351353
data = h5[key]
352354
name = data.attrs['name']

openquake/hazardlib/source_reader.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,13 @@ def get_csm(oq, full_lt, dstore=None):
310310
fillvalue=None)
311311

312312
# must be called *after* _fix_dupl_ids
313-
fix_geometry_sections(smdict, csm, dstore)
313+
if oq.sites and len(oq.sites) == 1 and oq.use_rates:
314+
lon, lat, _dep = oq.sites[0]
315+
site1 = site.SiteCollection.from_points([lon], [lat])
316+
else:
317+
site1 = None
318+
hdf5path = dstore.tempname if dstore else ''
319+
fix_geometry_sections(smdict, csm.src_groups, hdf5path, site1)
314320
return csm
315321

316322

@@ -377,7 +383,7 @@ def replace(lst, splitdic, key):
377383
lst[:] = new
378384

379385

380-
def fix_geometry_sections(smdict, csm, dstore):
386+
def fix_geometry_sections(smdict, src_groups, hdf5path='', site1=None):
381387
"""
382388
If there are MultiFaultSources, fix the sections according to the
383389
GeometryModels (if any).
@@ -399,22 +405,20 @@ def fix_geometry_sections(smdict, csm, dstore):
399405

400406
if sections:
401407
# save in the temporary file
402-
assert dstore, ('You forgot to pass the dstore to '
408+
assert hdf5path, ('You forgot to pass the dstore to '
403409
'get_composite_source_model')
404-
oq = dstore['oqparam']
410+
405411
mfsources = []
406-
for sg in csm.src_groups:
412+
for sg in src_groups:
407413
for src in sg:
408414
if src.code == b'F':
409415
mfsources.append(src)
410-
if oq.sites and len(oq.sites) == 1 and oq.use_rates:
411-
lon, lat, _dep = oq.sites[0]
412-
site1 = site.SiteCollection.from_points([lon], [lat])
413-
else:
414-
site1 = None
415-
split_dic = save_and_split(mfsources, sections, dstore.tempname, site1)
416-
for sg in csm.src_groups:
416+
split_dic = save_and_split(mfsources, sections, hdf5path, site1)
417+
for sg in src_groups:
417418
replace(sg.sources, split_dic, 'source_id')
419+
with hdf5.File(hdf5path, 'r') as h5:
420+
return h5['secparams'][:]
421+
return ()
418422

419423

420424
def _groups_ids(smlt_dir, smdict, fnames):

0 commit comments

Comments
 (0)