From 32ae207b9b0ac7bdd2e9f2f8de18b284c44514a0 Mon Sep 17 00:00:00 2001 From: Adam Zsarnoczay <33822153+zsarnoczay@users.noreply.github.com> Date: Tue, 4 Feb 2025 13:20:24 -0800 Subject: [PATCH 1/6] Add wind demands to list of recognized EDPs --- pelicun/base.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pelicun/base.py b/pelicun/base.py index d26341fb..50c10684 100644 --- a/pelicun/base.py +++ b/pelicun/base.py @@ -1323,6 +1323,11 @@ def dedupe_index(dataframe: pd.DataFrame, dtype: type = str) -> pd.DataFrame: 'Peak Link Beam Chord Rotation': 'LBR', # Wind Intensity 'Peak Gust Wind Speed': 'PWS', + # Wind Demands + 'Peak Wind Force': 'PWF', + 'Peak Internal Force': 'PIF', + 'Peak Line Force': 'PLF', + 'Peak Wind Pressure': 'PWP', # Inundation Intensity 'Peak Inundation Height': 'PIH', # Shaking Intensity From 5cd8fe2ae59b6b97b4446f0dfce9ff0a64e8e928 Mon Sep 17 00:00:00 2001 From: Adam Zsarnoczay <33822153+zsarnoczay@users.noreply.github.com> Date: Tue, 4 Feb 2025 13:36:40 -0800 Subject: [PATCH 2/6] Extend default units to handle line forces --- pelicun/settings/default_units.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pelicun/settings/default_units.json b/pelicun/settings/default_units.json index 1b387b4a..3931968f 100644 --- a/pelicun/settings/default_units.json +++ b/pelicun/settings/default_units.json @@ -56,6 +56,13 @@ "kip": 4448.2179868, "kips": 4448.2179868 }, + "line_force": { + "Npm": 1.0, + "kNpm": 1000.0, + "lbpft": 14.5939, + "kippft": 14593.9, + "kipspft": 14593.9 + }, "pressure": { "Pa": 1.0, "kPa": 1000.0, From 698affd4b20dc3abb952e6ccb8ccea023e25a7d4 Mon Sep 17 00:00:00 2001 From: Adam Zsarnoczay <33822153+zsarnoczay@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:30:21 -0800 Subject: [PATCH 3/6] bugfix: make sure no component losses are counted on top of replacement when the damage is irreparable --- pelicun/assessment.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pelicun/assessment.py b/pelicun/assessment.py index 1df62c5d..b1d9a7a4 100644 --- a/pelicun/assessment.py +++ b/pelicun/assessment.py @@ -83,6 +83,9 @@ '1_excessive.coll.DEM': {'DS1': 'collapse_DS1'}, '2_collapse': {'DS1': 'ALL_NA'}, '3_excessiveRID': {'DS1': 'irreparable_DS1'}, + '4_irreparable': {'DS1': 'ALL_NA'}, + '5_irreparable': {'DS1': 'collapse_DS0'}, + }, # TODO(AZ): expand with ground failure logic 'Hazus Earthquake': { From e853eed70f7c3bb755ec9b09abe5c65096de59d4 Mon Sep 17 00:00:00 2001 From: Adam Zsarnoczay <33822153+zsarnoczay@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:32:31 -0800 Subject: [PATCH 4/6] Add more flexibility by allowing the `Distribution` and `Theta_1` to be missing for CollapseFragility and Replacement consequences when validating inputs. Using sensible defaults was already taken care of for replacements. For collapse fragility, I added the corresponding defaults to DL_Calculation. --- pelicun/settings/input_schema.json | 20 +++++--------------- pelicun/tools/DL_calculation.py | 5 +++++ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/pelicun/settings/input_schema.json b/pelicun/settings/input_schema.json index 19f54ce6..346a9b05 100644 --- a/pelicun/settings/input_schema.json +++ b/pelicun/settings/input_schema.json @@ -213,9 +213,7 @@ }, "required": [ "DemandType", - "CapacityDistribution", - "CapacityMedian", - "Theta_1" + "CapacityMedian" ] }, "DamageProcess": { @@ -322,9 +320,7 @@ }, "required": [ "Unit", - "Median", - "Distribution", - "Theta_1" + "Median" ] }, "ReplacementCarbon": { @@ -359,9 +355,7 @@ }, "required": [ "Unit", - "Median", - "Distribution", - "Theta_1" + "Median" ] }, "ReplacementTime": { @@ -396,9 +390,7 @@ }, "required": [ "Unit", - "Median", - "Distribution", - "Theta_1" + "Median" ] }, "ReplacementCost": { @@ -433,9 +425,7 @@ }, "required": [ "Unit", - "Median", - "Distribution", - "Theta_1" + "Median" ] } } diff --git a/pelicun/tools/DL_calculation.py b/pelicun/tools/DL_calculation.py index 95df82cd..c8be494a 100644 --- a/pelicun/tools/DL_calculation.py +++ b/pelicun/tools/DL_calculation.py @@ -839,6 +839,10 @@ def _parse_config_file( # noqa: C901 # Ensure `DL/Damage/CollapseFragility` contains all required keys. if is_specified(config, 'DL/Damage/CollapseFragility'): + if is_unspecified(config,'DL/Damage/CollapseFragility/CapacityDistribution'): + config['DL']['Damage']['CollapseFragility']['CapacityDistribution'] = 'deterministic' + config['DL']['Damage']['CollapseFragility']['Theta_1'] = 'N/A' + for thing in ('CapacityDistribution', 'CapacityMedian', 'Theta_1'): if is_unspecified(config, f'DL/Damage/CollapseFragility/{thing}'): msg = ( @@ -846,6 +850,7 @@ def _parse_config_file( # noqa: C901 f' in the configuration file.' ) raise PelicunInvalidConfigError(msg) + # Ensure `DL/Damage/IrreparableDamage` contains all required keys. if is_specified(config, 'DL/Damage/IrreparableDamage'): From 7a741446204d281f4b9dcc88634487cae7c6aea3 Mon Sep 17 00:00:00 2001 From: Adam Zsarnoczay <33822153+zsarnoczay@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:33:12 -0800 Subject: [PATCH 5/6] bugfix: only check for `custom_model_dir` if the user actually specified that they plan to use such a folder. --- pelicun/assessment.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/pelicun/assessment.py b/pelicun/assessment.py index b1d9a7a4..358facaa 100644 --- a/pelicun/assessment.py +++ b/pelicun/assessment.py @@ -985,14 +985,16 @@ def calculate_damage( # noqa: C901 component_db = [] if component_database_path is not None: - if custom_model_dir is None: - msg = ( - '`custom_model_dir` needs to be specified ' - 'when `component_database_path` is not None.' - ) - raise ValueError(msg) if 'CustomDLDataFolder' in component_database_path: + + if custom_model_dir is None: + msg = ( + '`custom_model_dir` needs to be specified ' + 'when `component_database_path` includes CustomDLDataFolder.' + ) + raise ValueError(msg) + component_database_path = component_database_path.replace( 'CustomDLDataFolder', custom_model_dir ) @@ -1504,14 +1506,16 @@ def load_consequence_info( conseq_df = pd.DataFrame() if consequence_database_path is not None: - if custom_model_dir is None: - msg = ( - 'When `consequence_database_path` is specified, ' - '`custom_model_dir` needs to be specified as well.' - ) - raise ValueError(msg) if 'CustomDLDataFolder' in consequence_database_path: + + if custom_model_dir is None: + msg = ( + 'When `consequence_database_path` includes CustomDLDataFolder, ' + '`custom_model_dir` needs to be specified as well.' + ) + raise ValueError(msg) + consequence_database_path = consequence_database_path.replace( 'CustomDLDataFolder', custom_model_dir ) From 372e1de30e8331a3555567bbf6c968ead663fb5d Mon Sep 17 00:00:00 2001 From: Adam Zsarnoczay <33822153+zsarnoczay@users.noreply.github.com> Date: Tue, 4 Feb 2025 15:46:15 -0800 Subject: [PATCH 6/6] fix a unit test and some ruff formatting issues --- pelicun/assessment.py | 5 ----- pelicun/tests/basic/test_base.py | 5 +++++ pelicun/tools/DL_calculation.py | 9 ++++++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pelicun/assessment.py b/pelicun/assessment.py index 358facaa..6e7f2f7d 100644 --- a/pelicun/assessment.py +++ b/pelicun/assessment.py @@ -85,7 +85,6 @@ '3_excessiveRID': {'DS1': 'irreparable_DS1'}, '4_irreparable': {'DS1': 'ALL_NA'}, '5_irreparable': {'DS1': 'collapse_DS0'}, - }, # TODO(AZ): expand with ground failure logic 'Hazus Earthquake': { @@ -985,9 +984,7 @@ def calculate_damage( # noqa: C901 component_db = [] if component_database_path is not None: - if 'CustomDLDataFolder' in component_database_path: - if custom_model_dir is None: msg = ( '`custom_model_dir` needs to be specified ' @@ -1506,9 +1503,7 @@ def load_consequence_info( conseq_df = pd.DataFrame() if consequence_database_path is not None: - if 'CustomDLDataFolder' in consequence_database_path: - if custom_model_dir is None: msg = ( 'When `consequence_database_path` includes CustomDLDataFolder, ' diff --git a/pelicun/tests/basic/test_base.py b/pelicun/tests/basic/test_base.py index 327ef9c3..11f8e2de 100644 --- a/pelicun/tests/basic/test_base.py +++ b/pelicun/tests/basic/test_base.py @@ -864,6 +864,11 @@ def test_parse_units() -> None: 'lbf': 4.4482179868, 'kip': 4448.2179868, 'kips': 4448.2179868, + 'Npm': 1.0, + 'kNpm': 1000.0, + 'lbpft': 14.5939, + 'kippft': 14593.9, + 'kipspft': 14593.9, 'Pa': 1.0, 'kPa': 1000.0, 'MPa': 1000000.0, diff --git a/pelicun/tools/DL_calculation.py b/pelicun/tools/DL_calculation.py index c8be494a..74f3fd44 100644 --- a/pelicun/tools/DL_calculation.py +++ b/pelicun/tools/DL_calculation.py @@ -839,8 +839,12 @@ def _parse_config_file( # noqa: C901 # Ensure `DL/Damage/CollapseFragility` contains all required keys. if is_specified(config, 'DL/Damage/CollapseFragility'): - if is_unspecified(config,'DL/Damage/CollapseFragility/CapacityDistribution'): - config['DL']['Damage']['CollapseFragility']['CapacityDistribution'] = 'deterministic' + if is_unspecified( + config, 'DL/Damage/CollapseFragility/CapacityDistribution' + ): + config['DL']['Damage']['CollapseFragility']['CapacityDistribution'] = ( + 'deterministic' + ) config['DL']['Damage']['CollapseFragility']['Theta_1'] = 'N/A' for thing in ('CapacityDistribution', 'CapacityMedian', 'Theta_1'): @@ -850,7 +854,6 @@ def _parse_config_file( # noqa: C901 f' in the configuration file.' ) raise PelicunInvalidConfigError(msg) - # Ensure `DL/Damage/IrreparableDamage` contains all required keys. if is_specified(config, 'DL/Damage/IrreparableDamage'):