Skip to content

Commit

Permalink
Merge pull request #10077 from gem/losses
Browse files Browse the repository at this point in the history
Added total_losses
  • Loading branch information
micheles authored Oct 22, 2024
2 parents 1ff0758 + 2e1bcda commit c414a1a
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 24 deletions.
9 changes: 5 additions & 4 deletions openquake/calculators/event_based_damage.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ def _gen_d4(asset_df, gmf_df, crmodel, dparam):
else:
d4[lti, a, :, d] *= dprobs

csq = crmodel.compute_csq(
assets, d4[lti, :, :, :D], lt, oq.time_event)
for name, values in csq.items():
d4[lti, :, :, dparam.csqidx[name]] = values
df = crmodel.tmap_df[crmodel.tmap_df.taxi == assets[0]['taxonomy']]
csq = crmodel.compute_csq(
assets, d4[:, :, :, :D], df, oq.loss_types, oq.time_event)
for name, values in csq.items():
d4[:, :, :, dparam.csqidx[name]] = values
yield aids, d4 # d4 has shape (L, A, E, Dc)


Expand Down
13 changes: 7 additions & 6 deletions openquake/calculators/multi_risk.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,19 @@ def get_dmg_csq(crm, assets_by_site, gmf, time_event):
peril_df = pandas.DataFrame(dict(peril=[gmv]))
group = general.group_array(assets, 'taxonomy')
for taxonomy, assets in group.items():
fracs = numpy.zeros((L, len(assets), 1, D), F32)
for li, loss_type in enumerate(crm.loss_types):
# NB: assuming trivial taxonomy mapping for multi_risk
df = crm.tmap_df[crm.tmap_df.taxi == taxonomy]
[rm] = [crm._riskmodels[k]
for k, w in zip(df.risk_id, df.weight)]
# NB: risk logic trees are not yet supported in multi_risk
fracs = rm.scenario_damage(loss_type, assets, peril_df, 'peril')
csq = crm.compute_csq(assets, fracs, loss_type, time_event)
number = assets['value-number']
for a, o in enumerate(assets['ordinal']):
out[o, li, 0, :D] = number[a] * fracs[a]
out[o, li, 0, [D]] = csq['losses'][a]
fracs[li] = rm.scenario_damage(loss_type, assets, peril_df, 'peril')
csq = crm.compute_csq(assets, fracs, df, crm.loss_types, time_event)
number = assets['value-number']
for a, o in enumerate(assets['ordinal']):
out[o, :, 0, :D] = number[a] * fracs[:, a]
out[o, :, 0, [D]] = csq['losses'][:, a]
return out


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ asset_hazard_distance = 20.0
structural_fragility_file = structural_fragility_model.xml
nonstructural_fragility_file = nonstructural_fragility_model.xml
contents_fragility_file = contents_fragility_model.xml
total_losses = structural+nonstructural+contents

[consequence]
consequence_file = {'taxonomy': 'consequence_model.csv'}
Expand Down
1 change: 1 addition & 0 deletions openquake/qa_tests_data/scenario_damage/case_7/job_r.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ asset_hazard_distance = 20.0
structural_fragility_file = structural_fragility_model.xml
nonstructural_fragility_file = nonstructural_fragility_model.xml
contents_fragility_file = contents_fragility_model.xml
total_losses = structural+nonstructural+contents

[export]
export_dir = ./
29 changes: 16 additions & 13 deletions openquake/risklib/riskmodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,27 +610,30 @@ def check_risk_ids(self, inputs):
raise InvalidFile(
'%s: missing %s' % (fname, ' '.join(ids)))

def compute_csq(self, assets, fractions, loss_type, time_event):
def compute_csq(self, assets, fractions, tmap_df, loss_types, time_event):
"""
:param assets: asset array
:param fractions: array of probabilies of shape (A, E, D)
:param loss_type: loss type as a string
:returns: a dict consequence_name -> array of length A, E
:param fractions: array of probabilies of shape (L, A, E, D)
:param tmap_df: DataFrame corresponding to the given taxonomy
:param loss_types: loss types as a strings
:returns: a dict consequence_name -> array of shape (L, A, E)
"""
A, E, _D = fractions.shape
csq = AccumDict(accum=numpy.zeros((A, E)))
L, A, E, _D = fractions.shape
csq = AccumDict(accum=numpy.zeros((L, A, E)))
for byname, coeffs in self.consdict.items():
# ex. byname = "losses_by_taxonomy"
if len(coeffs):
consequence, _tagname = byname.split('_by_')
# by construction all assets have the same taxonomy
df = self.tmap_df[self.tmap_df.taxi == assets[0]['taxonomy']]
for lt, risk_id, weight in zip(df.loss_type, df.risk_id, df.weight):
if lt == '*' or lt == loss_type:
# for instance risk_id = 'W_LFM-DUM_H6'
cs = fractions[:, :, 1:] @ coeffs[risk_id][loss_type] #(A,E)
csq[consequence] += scientific.consequence(
consequence, assets, cs, loss_type, time_event) * weight
for li, loss_type in enumerate(loss_types):
for lt, risk_id, weight in zip(
tmap_df.loss_type, tmap_df.risk_id, tmap_df.weight):
if lt == '*' or lt == loss_type:
# for instance risk_id = 'W_LFM-DUM_H6'
cs = fractions[li, :, :, 1:] @ coeffs[risk_id][loss_type]
csq[consequence][li] += scientific.consequence(
consequence, assets, cs, loss_type, time_event
) * weight
return csq

def init(self):
Expand Down
2 changes: 1 addition & 1 deletion openquake/risklib/scientific.py
Original file line number Diff line number Diff line change
Expand Up @@ -1720,7 +1720,7 @@ def consequence(consequence, assets, coeffs, loss_type, time_event):
"""
if consequence not in KNOWN_CONSEQUENCES:
raise NotImplementedError(consequence)
if consequence.startswith(('loss', 'losses')):
if consequence.startswith('losses'):
try:
values = assets['value-' + loss_type] / assets['value-number']
except ValueError: # landslide, liquefaction
Expand Down

0 comments on commit c414a1a

Please sign in to comment.