Skip to content

Commit aff4adc

Browse files
authored
Merge pull request #9100 from gem/faster
Made the GmfComputer a bit faster
2 parents 7f06339 + 728f458 commit aff4adc

File tree

2 files changed

+47
-38
lines changed

2 files changed

+47
-38
lines changed

openquake/hazardlib/calc/conditioned_gmfs.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@
123123
from openquake.hazardlib.geo.geodetic import geodetic_distance
124124
from openquake.hazardlib.gsim.base import ContextMaker
125125

126+
U32 = numpy.uint32
126127
F32 = numpy.float32
128+
129+
127130
class NoInterIntraStdDevs(Exception):
128131
def __init__(self, gsim):
129132
self.gsim = gsim
@@ -245,6 +248,11 @@ def compute_all(self, dstore, sig_eps=None, max_iml=None,
245248
self.update(data, array, sig, eps, eid_, rlz_, rlzs,
246249
[mea, tau+phi, tau, phi], sig_eps, max_iml)
247250

251+
for key, val in sorted(data.items()):
252+
if key in 'eid sid rlz':
253+
data[key] = numpy.concatenate(data[key], dtype=U32)
254+
else:
255+
data[key] = numpy.concatenate(data[key], dtype=F32)
248256
return pandas.DataFrame(data)
249257

250258
def compute(self, gsim, num_events, mea, tau, phi, rng):

openquake/hazardlib/calc/gmf.py

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,22 @@ def exp(vals, imt):
5858
return numpy.exp(vals)
5959

6060

61+
def set_max_min(array, mean, max_iml, min_iml, imts):
62+
M, N, E = array.shape
63+
64+
# manage max_iml
65+
for m, im in enumerate(imts):
66+
if (array[m] > max_iml[m]).any():
67+
for n in range(N):
68+
bad = array[m, n] > max_iml[m] # shape E
69+
array[m, n, bad] = exp(mean[m, n], im)
70+
71+
# manage min_iml
72+
for n in range(N):
73+
for e in range(E):
74+
if (array[:, n, e] < min_iml).all():
75+
array[:, n, e] = 0
76+
6177

6278
class GmfComputer(object):
6379
"""
@@ -132,58 +148,40 @@ def __init__(self, rupture, sitecol, cmaker, correlation_model=None,
132148
self.sites = sitecol.complete.filtered(self.ctx.sids)
133149
self.cross_correl = cross_correl or NoCrossCorrelation(
134150
cmaker.truncation_level)
151+
self.gmv_fields = [f'gmv_{m}' for m in range(len(cmaker.imts))]
135152

136153
def update(self, data, array, sig, eps, eid_, rlz_, rlzs,
137154
mean_stds, sig_eps, max_iml):
138155
sids = self.ctx.sids
139156
min_iml = self.cmaker.min_iml
140157
mag = self.ebrupture.rupture.mag
141-
M, N, E = array.shape # sig and eps have shapes (M, E) instead
142-
143-
# manage max_iml
144-
if max_iml is not None:
145-
for m, im in enumerate(self.cmaker.imtls):
146-
if (array[m] > max_iml[m]).any():
147-
for n in range(N):
148-
bad = array[m, n] > max_iml[m] # shape E
149-
mean = mean_stds[0][m, n]
150-
if len(mean.shape) == 2: # conditioned GMFs
151-
mean = mean[:, 0] # shape (N, 1)
152-
array[m, n, bad] = exp(mean, im)
153-
154-
# manage min_iml
155-
for n in range(N):
156-
for e in range(E):
157-
if (array[:, n, e] < min_iml).all():
158-
array[:, n, e] = 0
159-
158+
mean = mean_stds[0]
159+
if len(mean.shape) == 3: # shape (M, N, 1) for conditioned gmfs
160+
mean = mean[:, :, 0]
161+
set_max_min(array, mean, max_iml, min_iml, self.cmaker.imts)
160162
array = array.transpose(1, 0, 2) # from M, N, E to N, M, E
163+
N = len(array)
161164
n = 0
162165
for rlz in rlzs:
163166
eids = eid_[rlz_ == rlz]
164-
for ei, eid in enumerate(eids):
165-
gmfa = array[:, :, n + ei] # shape (N, M)
166-
if sig_eps is not None:
167+
if sig_eps is not None:
168+
for ei, eid in enumerate(eids):
167169
tup = tuple([eid, rlz] + list(sig[:, n + ei]) +
168170
list(eps[:, n + ei]))
169171
sig_eps.append(tup)
170-
items = []
172+
for ei, eid in enumerate(eids):
173+
gmfa = array[:, :, n + ei] # shape (N, M)
174+
# gmv can be zero due to the minimum_intensity, coming
175+
# from the job.ini or from the vulnerability functions
176+
data['sid'].append(sids)
177+
data['eid'].append(numpy.full(N, eid, U32))
178+
data['rlz'].append(numpy.full(N, rlz, U32))
171179
for sp in self.sec_perils:
172180
o = sp.compute(mag, zip(self.imts, gmfa.T), self.ctx)
173181
for outkey, outarr in zip(sp.outputs, o):
174-
items.append((outkey, outarr))
175-
for i, gmv in enumerate(gmfa):
176-
if gmv.sum() == 0:
177-
continue
178-
data['sid'].append(sids[i])
179-
data['eid'].append(eid)
180-
data['rlz'].append(rlz) # used in compute_gmfs_curves
181-
for m in range(M):
182-
data[f'gmv_{m}'].append(gmv[m])
183-
for outkey, outarr in items:
184-
data[outkey].append(outarr[i])
185-
# gmv can be zero due to the minimum_intensity, coming
186-
# from the job.ini or from the vulnerability functions
182+
data[outkey].append(outarr)
183+
for m, gmv_field in enumerate(self.gmv_fields):
184+
data[gmv_field].append(gmfa[:, m])
187185
n += len(eids)
188186

189187
def compute_all(self, scenario, sig_eps=None, max_iml=None, mon=Monitor()):
@@ -196,6 +194,9 @@ def compute_all(self, scenario, sig_eps=None, max_iml=None, mon=Monitor()):
196194
data = AccumDict(accum=[])
197195
mean_stds = self.cmaker.get_mean_stds([self.ctx]) # (4, G, M, N)
198196
rng = numpy.random.default_rng(self.seed)
197+
if max_iml is None:
198+
M = len(self.cmaker.imts)
199+
max_iml = numpy.full(M, numpy.inf, float)
199200
for g, (gs, rlzs) in enumerate(rlzs_by_gsim.items()):
200201
num_events = numpy.isin(rlz_, rlzs).sum()
201202
if num_events == 0: # it may happen
@@ -211,9 +212,9 @@ def compute_all(self, scenario, sig_eps=None, max_iml=None, mon=Monitor()):
211212

212213
for key, val in sorted(data.items()):
213214
if key in 'eid sid rlz':
214-
data[key] = U32(data[key])
215+
data[key] = numpy.concatenate(data[key], dtype=U32)
215216
else:
216-
data[key] = F32(data[key])
217+
data[key] = numpy.concatenate(data[key], dtype=F32)
217218
return pandas.DataFrame(data)
218219

219220
def compute(self, gsim, num_events, mean_stds, rng):

0 commit comments

Comments
 (0)