diff --git a/openquake/calculators/tests/scenario_damage_test.py b/openquake/calculators/tests/scenario_damage_test.py
index 6b0e80e59dcf..dfb8379d476c 100644
--- a/openquake/calculators/tests/scenario_damage_test.py
+++ b/openquake/calculators/tests/scenario_damage_test.py
@@ -24,7 +24,7 @@
from openquake.qa_tests_data.scenario_damage import (
case_1, case_1c, case_2, case_3, case_4, case_4b, case_5, case_5a,
case_6, case_7, case_8, case_9, case_10, case_11, case_12, case_13,
- case_14, case_16, case_17, case_18, case_19, case_20)
+ case_14, case_16, case_17, case_18, case_19, case_20, case_21)
from openquake.calculators.tests import CalculatorTestCase, strip_calc_id
from openquake.calculators.extract import extract
from openquake.calculators.export import export
@@ -297,6 +297,13 @@ def test_case_20(self):
[fname] = out[('aggrisk', 'csv')]
self.assertEqualFiles('expected/aggrisk.csv', fname)
+ def test_case_21(self):
+ # infrastructure risk for structural and liquefaction loss types
+ out = self.run_calc(case_21.__file__, 'job.ini', exports='csv')
+ [agg_csv, aggparent_csv] = out[('aggrisk', 'csv')]
+ self.assertEqualFiles('expected/aggrisk.csv', agg_csv)
+ self.assertEqualFiles('expected/aggrisk-parent.csv', aggparent_csv)
+
def losses(aid, alt):
E = len(alt.event_id.unique())
diff --git a/openquake/commonlib/oqvalidation.py b/openquake/commonlib/oqvalidation.py
index 64c3bc02a4b0..31bd4603231c 100644
--- a/openquake/commonlib/oqvalidation.py
+++ b/openquake/commonlib/oqvalidation.py
@@ -969,6 +969,8 @@ class OqParam(valid.ParamSet):
'residents_vulnerability',
'area_vulnerability',
'number_vulnerability',
+ 'liquefaction_fragility',
+ 'liquefaction_vulnerability',
'post_loss_amplification',
}
# old name => new name
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/__init__.py b/openquake/qa_tests_data/scenario_damage/case_21/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/expected/aggrisk-parent.csv b/openquake/qa_tests_data/scenario_damage/case_21/expected/aggrisk-parent.csv
new file mode 100644
index 000000000000..4b45254f9998
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/expected/aggrisk-parent.csv
@@ -0,0 +1,14 @@
+#,,,,,,,,,"generated_by='OpenQuake engine 3.22.0-git4588b0bb77', start_date='2024-10-14T10:44:37', checksum=4092734058, investigation_time=None, risk_investigation_time=None"
+loss_type,parent_id,rlz_id,no_damage,slight,moderate,extensive,complete,non_operational_value,non_operational_ratio
+structural,A,0,1.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00
+structural,A,1,1.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00
+liquefaction,A,0,1.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00
+liquefaction,A,1,1.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00
+structural,B,0,1.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00
+structural,B,1,1.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00
+liquefaction,B,0,1.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00
+liquefaction,B,1,1.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00
+structural,E1,0,1.00000E-01,0.00000E+00,0.00000E+00,0.00000E+00,9.00000E-01,9.00000E-01,9.00000E-01
+structural,E1,1,2.00000E-01,0.00000E+00,0.00000E+00,0.00000E+00,8.00000E-01,8.00000E-01,8.00000E-01
+liquefaction,E1,0,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,1.00000E+00,1.00000E+00,1.00000E+00
+liquefaction,E1,1,0.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,1.00000E+00,1.00000E+00,1.00000E+00
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/expected/aggrisk.csv b/openquake/qa_tests_data/scenario_damage/case_21/expected/aggrisk.csv
new file mode 100644
index 000000000000..509cc72518dd
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/expected/aggrisk.csv
@@ -0,0 +1,6 @@
+#,,,,,,,,"generated_by='OpenQuake engine 3.22.0-git4588b0bb77', start_date='2024-10-14T10:44:37', checksum=4092734058, investigation_time=None, risk_investigation_time=None"
+loss_type,rlz_id,no_damage,slight,moderate,extensive,complete,non_operational_value,non_operational_ratio
+structural,0,2.10000E+00,0.00000E+00,0.00000E+00,0.00000E+00,9.00000E-01,9.00000E-01,3.00000E-01
+structural,1,2.20000E+00,0.00000E+00,0.00000E+00,0.00000E+00,8.00000E-01,8.00000E-01,2.66667E-01
+liquefaction,0,2.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,1.00000E+00,1.00000E+00,3.33333E-01
+liquefaction,1,2.00000E+00,0.00000E+00,0.00000E+00,0.00000E+00,1.00000E+00,1.00000E+00,3.33333E-01
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/exposure.xml b/openquake/qa_tests_data/scenario_damage/case_21/exposure.xml
new file mode 100644
index 000000000000..55066fcd31de
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/exposure.xml
@@ -0,0 +1,16 @@
+
+
+
+ Road Network Demo
+
+
+
+
+ type start_node end_node purpose weight parent_id
+
+
+ exposure_demo_nodes.csv
+ exposure_demo_edges.csv
+
+
+
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/exposure_demo_edges.csv b/openquake/qa_tests_data/scenario_damage/case_21/exposure_demo_edges.csv
new file mode 100644
index 000000000000..91ec609890fc
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/exposure_demo_edges.csv
@@ -0,0 +1,2 @@
+id,lon,lat,taxonomy,number,type,start_node,end_node,purpose,weight,parent_id
+E1,89.955,24.615,bridge1,1,edge,A,B,NA,1,E1
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/exposure_demo_nodes.csv b/openquake/qa_tests_data/scenario_damage/case_21/exposure_demo_nodes.csv
new file mode 100644
index 000000000000..bccfb088d3c0
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/exposure_demo_nodes.csv
@@ -0,0 +1,3 @@
+id,lon,lat,taxonomy,number,type,start_node,end_node,purpose,weight,parent_id
+A,89.95,24.61,connection,1,node,NA,NA,connection,1,A
+B,89.96,24.62,connection,1,node,NA,NA,connection,1,B
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/fragility_model_liq.xml b/openquake/qa_tests_data/scenario_damage/case_21/fragility_model_liq.xml
new file mode 100644
index 000000000000..247235b99d2d
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/fragility_model_liq.xml
@@ -0,0 +1,21 @@
+
+
+
+ Road Network
+ slight moderate extensive complete
+
+ 0 0.3 0.6 1
+ 0 1 1 1
+ 0 1 1 1
+ 0 1 1 1
+ 0 1 1 1
+
+
+ 0 0.5 1 1.5
+ 0 0 0 1
+ 0 0 0 1
+ 0 0 0 1
+ 0 0 0 1
+
+
+
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/fragility_model_shaking.xml b/openquake/qa_tests_data/scenario_damage/case_21/fragility_model_shaking.xml
new file mode 100644
index 000000000000..8cdd32478c98
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/fragility_model_shaking.xml
@@ -0,0 +1,21 @@
+
+
+
+ Road Network
+ slight moderate extensive complete
+
+ 0 0.5 1 1.5
+ 0 0 0 1
+ 0 0 0 1
+ 0 0 0 1
+ 0 0 0 1
+
+
+ 0 0.3 0.6 1
+ 0 1 1 1
+ 0 1 1 1
+ 0 1 1 1
+ 0 1 1 1
+
+
+
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/gmpe_logic_tree_ascr.xml b/openquake/qa_tests_data/scenario_damage/case_21/gmpe_logic_tree_ascr.xml
new file mode 100644
index 000000000000..5ddec4f00ac2
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/gmpe_logic_tree_ascr.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+AbrahamsonEtAl2014RegCHN
+
+ 0.50
+
+
+
+ChiouYoungs2014
+
+ 0.50
+
+
+
+
\ No newline at end of file
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/job.ini b/openquake/qa_tests_data/scenario_damage/case_21/job.ini
new file mode 100644
index 000000000000..c6f0a06c8981
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/job.ini
@@ -0,0 +1,39 @@
+[General]
+description = Bangladesh scenario 1885_manikganj - liquefaction
+calculation_mode = scenario_damage
+random_seed = 113
+ses_seed = 1025
+
+[site_params]
+site_model_file = site_model.csv
+
+[rupture]
+rupture_model_file = rupture.xml
+rupture_mesh_spacing = 2.0
+
+[Secondary perils]
+secondary_perils = AllstadtEtAl2022Liquefaction
+
+[Calculation parameters]
+intensity_measure_types = PGA, PGV
+cross_correlation = Bradley2012
+truncation_level = 3
+maximum_distance = 300
+number_of_ground_motion_fields = 10
+gsim_logic_tree_file = gmpe_logic_tree_ascr.xml
+
+
+[exposure]
+exposure_file = exposure.xml
+
+[fragility]
+structural_fragility_file = fragility_model_shaking.xml
+liquefaction_fragility_file = fragility_model_liq.xml
+
+[consequence]
+consequence_file = {'taxonomy': 'non_operational.csv'}
+
+[risk_calculation]
+discrete_damage_distribution = true
+aggregate_by = parent_id
+infrastructure_connectivity_analysis = true
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/non_operational.csv b/openquake/qa_tests_data/scenario_damage/case_21/non_operational.csv
new file mode 100644
index 000000000000..63189dd7224c
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/non_operational.csv
@@ -0,0 +1,5 @@
+taxonomy,consequence,loss_type,slight,moderate,extensive,complete
+bridge1,non_operational,structural,0,0,0,1
+connection,non_operational,structural,0,0,0,1
+bridge1,non_operational,liquefaction,0,0,0,1
+connection,non_operational,liquefaction,0,0,0,1
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/rupture.xml b/openquake/qa_tests_data/scenario_damage/case_21/rupture.xml
new file mode 100644
index 000000000000..90cdf332b746
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/rupture.xml
@@ -0,0 +1,31 @@
+
+
+
+
+ 7.2522481E+00
+
+
+ 9.0000000E+01
+
+
+
+
+
+ 9.0010790E+01 2.3820714E+01 8.9990907E+01 2.3859943E+01 8.9998430E+01 2.3992675E+01 9.0021000E+01 2.4103911E+01 9.0021537E+01 2.4213536E+01 9.0000848E+01 2.4454549E+01 8.9991175E+01 2.4507212E+01 8.9991175E+01 2.4624360E+01
+
+
+
+ 4.5000000E+01
+
+
+ 5.0000000E+00
+
+
+ 2.0000000E+01
+
+
+
+
diff --git a/openquake/qa_tests_data/scenario_damage/case_21/site_model.csv b/openquake/qa_tests_data/scenario_damage/case_21/site_model.csv
new file mode 100644
index 000000000000..dc09e2390dca
--- /dev/null
+++ b/openquake/qa_tests_data/scenario_damage/case_21/site_model.csv
@@ -0,0 +1,4 @@
+site_id,lon,lat,vs30,z1pt0,z2pt5,gwd,precip,dc,dr,dw,slope,cohesion_mid,friction_mid,saturation,dry_density
+0,89.95,24.61,183,513.4083567,3.093638299,0.946059358,1796,187,1.80517065,1.80517065,20,20000,35,2,1500
+1,89.96,24.62,221,502.7851667,2.493037557,2.853437095,1833,183,5.991748144,5.991748144,20,20000,35,2,1500
+2,89.9655,24.615,211,506.1375293,2.628660223,0.076295109,1775,195,2.63670763,2.63670763,20,20000,35,2,1500
diff --git a/openquake/risklib/riskmodels.py b/openquake/risklib/riskmodels.py
index c4341925890b..cb673a1c0709 100644
--- a/openquake/risklib/riskmodels.py
+++ b/openquake/risklib/riskmodels.py
@@ -36,9 +36,8 @@
F32 = numpy.float32
F64 = numpy.float64
-LTYPE_REGEX = '|'.join(valid.cost_type.choices) + '|area|number|residents'
-RISK_TYPE_REGEX = re.compile(r'(%s|occupants|fragility)_([\w_]+)'
- % LTYPE_REGEX)
+LTYPE_REGEX = '|'.join(valid.cost_type.choices) + '|area|number|residents|liquefaction'
+RISK_TYPE_REGEX = re.compile(r'(%s|occupants|fragility)_([\w_]+)' % LTYPE_REGEX)
def _assert_equal(d1, d2):
diff --git a/openquake/risklib/scientific.py b/openquake/risklib/scientific.py
index 7ef46dd2b816..4ecf1c131cf9 100644
--- a/openquake/risklib/scientific.py
+++ b/openquake/risklib/scientific.py
@@ -70,6 +70,7 @@
structural_ins+contents_ins+business_interruption_ins
nonstructural_ins+contents_ins+business_interruption_ins
structural_ins+nonstructural_ins+contents_ins+business_interruption_ins
+liquefaction
'''.split())
TOTLOSSES = [lt for lt in LOSSTYPE if '+' in lt]