Skip to content

Commit 7c16a10

Browse files
authored
Merge pull request #9097 from gem/faster_gmfs
Refactored the GMF generation
2 parents 016c411 + bd5cd34 commit 7c16a10

File tree

4 files changed

+34
-39
lines changed

4 files changed

+34
-39
lines changed

openquake/commonlib/calc.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from openquake.baselib import performance, parallel, hdf5, general
2525
from openquake.hazardlib.source import rupture
2626
from openquake.hazardlib import probability_map
27-
from openquake.hazardlib.source.rupture import events_dt, get_eid_rlz
27+
from openquake.hazardlib.source.rupture import get_events
2828
from openquake.commonlib import util
2929

3030
TWO16 = 2 ** 16
@@ -185,8 +185,7 @@ def get_eid_rlz(self, proxies, rlzs_by_gsim, ordinal):
185185
:returns: a composite array with the associations eid->rlz
186186
"""
187187
rlzs = numpy.concatenate(list(rlzs_by_gsim.values()))
188-
eid_rlz = get_eid_rlz(proxies, rlzs, self.scenario)
189-
return {ordinal: numpy.array(eid_rlz, events_dt)}
188+
return {ordinal: get_events(proxies, rlzs, self.scenario)}
190189

191190
def import_rups_events(self, rup_array, get_rupture_getters):
192191
"""

openquake/hazardlib/calc/conditioned_gmfs.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
from openquake.baselib.general import AccumDict
117117
from openquake.baselib.performance import Monitor
118118
from openquake.hazardlib import correlation, cross_correlation
119+
from openquake.hazardlib.source.rupture import get_eid_rlz
119120
from openquake.hazardlib.imt import from_string
120121
from openquake.hazardlib.calc.gmf import GmfComputer, exp
121122
from openquake.hazardlib.const import StdDev
@@ -229,12 +230,11 @@ def compute_all(self, dstore, sig_eps=None, max_iml=None,
229230
"""
230231
min_iml = self.cmaker.min_iml
231232
rlzs_by_gsim = self.cmaker.gsims
232-
eid_rlz = self.ebrupture.get_eid_rlz(rlzs_by_gsim, scenario=True)
233+
rlzs = numpy.concatenate(list(rlzs_by_gsim.values()))
234+
eid_, rlz_ = get_eid_rlz(vars(self.ebrupture), rlzs, scenario=True)
233235
mag = self.ebrupture.rupture.mag
234236
data = AccumDict(accum=[])
235237
rng = numpy.random.default_rng(self.seed)
236-
num_events = self.num_events
237-
assert num_events
238238
# NB: ms is a dictionary gsim -> [imt -> array]
239239
sids = dstore['conditioned/sids'][:]
240240
for g, (gsim, rlzs) in enumerate(rlzs_by_gsim.items()):
@@ -244,7 +244,7 @@ def compute_all(self, dstore, sig_eps=None, max_iml=None,
244244
phi = dstore['conditioned/gsim_%d/phi' % g][:]
245245
with mon2:
246246
array, sig, eps = self.compute(
247-
gsim, num_events, mea, tau, phi, rng)
247+
gsim, self.num_events, mea, tau, phi, rng)
248248
M, N, E = array.shape # sig and eps have shapes (M, E) instead
249249
assert len(sids) == N, (len(sids), N)
250250

@@ -265,7 +265,7 @@ def compute_all(self, dstore, sig_eps=None, max_iml=None,
265265
array = array.transpose(1, 0, 2) # from M, N, E to N, M, E
266266
n = 0
267267
for rlz in rlzs:
268-
eids = eid_rlz[eid_rlz['rlz'] == rlz]['eid']
268+
eids = eid_[rlz_ == rlz]
269269
for ei, eid in enumerate(eids):
270270
gmfa = array[:, :, n + ei] # shape (N, M)
271271
if sig_eps is not None:

openquake/hazardlib/calc/gmf.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from openquake.baselib.general import AccumDict
2727
from openquake.baselib.performance import Monitor
2828
from openquake.hazardlib.const import StdDev
29+
from openquake.hazardlib.source.rupture import get_eid_rlz
2930
from openquake.hazardlib.cross_correlation import NoCrossCorrelation
3031
from openquake.hazardlib.gsim.base import ContextMaker, FarAwayRupture
3132
from openquake.hazardlib.imt import from_string
@@ -138,12 +139,13 @@ def compute_all(self, scenario, sig_eps=None, max_iml=None, mon=Monitor()):
138139
min_iml = self.cmaker.min_iml
139140
rlzs_by_gsim = self.cmaker.gsims
140141
sids = self.ctx.sids
141-
eid_rlz = self.ebrupture.get_eid_rlz(rlzs_by_gsim, scenario)
142+
rlzs = numpy.concatenate(list(rlzs_by_gsim.values()))
143+
eid_, rlz_ = get_eid_rlz(vars(self.ebrupture), rlzs, scenario)
142144
mag = self.ebrupture.rupture.mag
143145
data = AccumDict(accum=[])
144146
mean_stds = self.cmaker.get_mean_stds([self.ctx]) # (4, G, M, N)
145147
for g, (gs, rlzs) in enumerate(rlzs_by_gsim.items()):
146-
num_events = numpy.isin(eid_rlz['rlz'], rlzs).sum()
148+
num_events = numpy.isin(rlz_, rlzs).sum()
147149
if num_events == 0: # it may happen
148150
continue
149151
# NB: the trick for performance is to keep the call to
@@ -171,7 +173,7 @@ def compute_all(self, scenario, sig_eps=None, max_iml=None, mon=Monitor()):
171173
array = array.transpose(1, 0, 2) # from M, N, E to N, M, E
172174
n = 0
173175
for rlz in rlzs:
174-
eids = eid_rlz[eid_rlz['rlz'] == rlz]['eid']
176+
eids = eid_[rlz_ == rlz]
175177
for ei, eid in enumerate(eids):
176178
gmfa = array[:, :, n + ei] # shape (N, M)
177179
if sig_eps is not None:

openquake/hazardlib/source/rupture.py

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -755,25 +755,6 @@ def __init__(self, rupture, source_id, trt_smr, n_occ=1, id=None, e0=0):
755755
def tectonic_region_type(self):
756756
return self.rupture.tectonic_region_type
757757

758-
# TODO: replace with the function get_eid_rlz
759-
def get_eid_rlz(self, rlzs_by_gsim, scenario):
760-
"""
761-
:param rlzs_by_gsim: a dictionary gsims -> rlzs array
762-
:param scenario: if true distribute the rlzs evenly else randomly
763-
:returns: an array with fields (eid, rlz)
764-
"""
765-
out = numpy.zeros(self.n_occ, [('eid', U32), ('rlz', U32)])
766-
rlzs = numpy.concatenate(list(rlzs_by_gsim.values()))
767-
out['eid'] = numpy.arange(self.e0, self.e0 + self.n_occ, dtype=U32)
768-
if scenario:
769-
# the rlzs are distributed evenly
770-
div = self.n_occ // len(rlzs)
771-
out['rlz'] = rlzs[numpy.arange(self.n_occ) // div]
772-
else:
773-
# event_based: the rlzs are distributed randomly
774-
out['rlz'] = general.random_choice(rlzs, self.n_occ, 0, self.seed)
775-
return out
776-
777758
def get_eids(self):
778759
"""
779760
:returns: an array of event IDs
@@ -785,7 +766,25 @@ def __repr__(self):
785766
self.__class__.__name__, self.id, self.n_occ)
786767

787768

788-
def get_eid_rlz(recs, rlzs, scenario):
769+
def get_eid_rlz(rec, rlzs, scenario):
770+
"""
771+
:param rlzs: an array of realization indices
772+
:param scenario: if true distribute the rlzs evenly else randomly
773+
:returns: two arrays (eid, rlz)
774+
"""
775+
e0 = rec['e0']
776+
n = rec['n_occ']
777+
eid = numpy.arange(e0, e0 + n, dtype=U32)
778+
if scenario:
779+
# the rlzs are distributed evenly
780+
rlz = rlzs[numpy.arange(rec['n_occ']) // (n // len(rlzs))]
781+
else:
782+
# event_based: the rlzs are distributed randomly
783+
rlz = general.random_choice(rlzs, n, 0, rec['seed'])
784+
return eid, rlz
785+
786+
787+
def get_events(recs, rlzs, scenario):
789788
"""
790789
Build the associations event_id -> rlz_id for each rup_id.
791790
@@ -798,15 +797,10 @@ def get_eid_rlz(recs, rlzs, scenario):
798797
n = rec['n_occ']
799798
stop = start + n
800799
slc = out[start:stop]
801-
slc['id'] = numpy.arange(rec['e0'], rec['e0'] + n, dtype=U32)
800+
eid, rlz = get_eid_rlz(rec, rlzs, scenario)
801+
slc['id'] = eid
802+
slc['rlz_id'] = rlz
802803
slc['rup_id'] = rec['id']
803-
if scenario:
804-
# the rlzs are distributed evenly
805-
div = n // len(rlzs)
806-
slc['rlz_id'] = rlzs[numpy.arange(n) // div]
807-
else:
808-
# event_based: the rlzs are distributed randomly
809-
slc['rlz_id'] = general.random_choice(rlzs, n, 0, rec['seed'])
810804
start = stop
811805
return out
812806

0 commit comments

Comments
 (0)