Skip to content
Draft
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
2 changes: 2 additions & 0 deletions openquake/commonlib/oqvalidation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,8 @@ class OqParam(valid.ParamSet):
'liquefaction_vulnerability',
'landslide_fragility',
'landslide_vulnerability',
'tsunami_fragility',
'tsunami_vulnerability',
'post_loss_amplification',
} | {vtype + '_vulnerability' for vtype in VULN_TYPES}
# old name => new name
Expand Down
24 changes: 23 additions & 1 deletion openquake/hazardlib/imt.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ def JMA():
# secondary IMTs
sec_imts = '''ASH LAVA LAHAR PYRO
Disp DispProb LiqProb LiqOccur LSE PGDMax PGDGeomMean LsProb
FlowDepth FlowVel Flux
'''.split()
for sec in sec_imts:
assert '_' not in sec, sec
Expand Down Expand Up @@ -353,7 +354,7 @@ def PYRO():
return IMT('PYRO')


# Liquefaction IMTs
# Liquefaction and Landslide IMTs

def Disp():
"""
Expand Down Expand Up @@ -417,3 +418,24 @@ def LsProb():
Probability of landsliding.
"""
return IMT('LsProb')


# Tsunami IMTs

def FlowDepth():
"""
Flow depth in meters.
"""
return IMT('FlowDepth')

def FlowVel():
"""
Flow velocity in m/s.
"""
return IMT('FlowVel')

def Flux():
"""
Flow flux in m^3/s.
"""
return IMT('Flux')
16 changes: 11 additions & 5 deletions openquake/risklib/riskmodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,10 @@ def __getitem__(self, lt):
if isinstance(lt, tuple):
return dict.__getitem__(self, lt)
else: # assume lt is a loss_type string
return dict.__getitem__(self, ('groundshaking', lt))
for key in self:
if key[1] == lt:
return dict.__getitem__(self, key)
raise KeyError(('groundshaking', lt))


class RiskModel(object):
Expand Down Expand Up @@ -285,7 +288,9 @@ def loss_types(self):
The list of loss types in the underlying vulnerability functions,
in lexicographic order
"""
return sorted(self.risk_functions['groundshaking'])
for peril in self.risk_functions:
return sorted(self.risk_functions[peril])
return []

def __call__(self, assets, gmf_df, rndgen=None):
meth = getattr(self, self.calcmode)
Expand All @@ -299,7 +304,7 @@ def __toh5__(self):

def __fromh5__(self, dic, attrs):
vars(self).update(attrs)
assert 'groundshaking' in dic, list(dic)
assert len(dic) > 0, list(dic)
self.risk_functions = dic

def __repr__(self):
Expand Down Expand Up @@ -782,8 +787,9 @@ def init(self):
iml = collections.defaultdict(list)
# ._riskmodels is empty if read from the hazard calculation
for riskid, rm in self._riskmodels.items():
for lt, rf in rm.risk_functions['groundshaking'].items():
iml[rf.imt].append(rf.imls[0])
for peril in rm.risk_functions:
for lt, rf in rm.risk_functions[peril].items():
iml[rf.imt].append(rf.imls[0])

if oq.impact:
pass # don't set minimum_intensity
Expand Down
5 changes: 3 additions & 2 deletions openquake/risklib/scientific.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
'losses', 'collapsed',
'injured', 'fatalities', 'homeless', 'non_operational']

PERILTYPE = numpy.array(['groundshaking', 'liquefaction', 'landslide'])
PERILTYPE = numpy.array(['groundshaking', 'liquefaction', 'landslide', 'tsunami'])
LOSSTYPE = numpy.array('''\
business_interruption contents nonstructural structural
occupants occupants_day occupants_night occupants_transit
Expand Down Expand Up @@ -1687,7 +1687,8 @@ def output(self, asset_df, haz, sec_losses=(), rndgen=None):
"""
dic = collections.defaultdict(list) # peril, lt -> outs
weights = collections.defaultdict(list) # peril, lt -> weights
perils = {'groundshaking'}
# perils = {'groundshaking'}
perils = {peril for _, peril in self.wdic} or {'groundshaking'}
for riskid, rm in self.items():
for (peril, lt), res in rm(asset_df, haz, rndgen).items():
# res is an array of fractions of shape (A, E, D)
Expand Down
44 changes: 44 additions & 0 deletions openquake/sep/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,48 @@ def compute(self, mag, imt_gmf, sites):
return []


class Tsunami(SecondaryPeril):
"""
Import FlowDepth, FlowVel, Flux from CSV files
"""
peril = 'tsunami'
inputs = []
outputs = ["FlowDepth", "FlowVel", "Flux"]

def prepare(self, sites=None):
"""
Import the CSV files for tsunami subperils.
"""
if sites is None:
return
if 'multi_peril' not in self.oq.inputs:
return
for peril in self.oq.inputs['multi_peril']:
assert peril in self.outputs, peril
self.fname_by_peril = self.oq.inputs['multi_peril']
N = len(sites)
self.data = {'sid': sites.sids, 'eid': numpy.zeros(N, numpy.uint32)}
names = []
for name, fname in self.fname_by_peril.items():
fname = os.path.join(self.oq.base_path, fname)
tofloat = valid.positivefloat
with open(fname) as f:
header = next(f)
if 'geom' in header:
peril = wkt2peril(fname, name, sites)
else:
peril = csv2peril(fname, name, sites, tofloat,
self.oq.asset_hazard_distance)
if peril.sum() == 0:
logging.warning('No sites were affected by %s' % name)
self.data[f'{self.__class__.__name__}_{name}'] = peril
names.append(name)

def compute(self, mag, imt_gmf, sites):
# doing nothing, since all the work is in the `prepare` method
return []


LIQUEFACTION_MODELS = {cls.__name__ for cls in SecondaryPeril.__subclasses__()
if cls.peril == 'liquefaction'}
LANDSLIDE_MODELS = {cls.__name__ for cls in SecondaryPeril.__subclasses__()
Expand All @@ -1035,6 +1077,8 @@ def corresponds(col, peril, imt):
return False
if peril == 'groundshaking':
return True
if peril == 'tsunami':
return True
name, _ = col.split('_')
if peril == 'liquefaction':
return name in LIQUEFACTION_MODELS
Expand Down