Hazus wind damage functions#
Hazus vulnerability functions#
The FEMA Hazus team have provided an extract of the damage functions used in the Hazus 6.1 Hurricane Model in an Excel file HazusWindDamFunctions_Hazus61.xlsx. This is a highly granular, albeit US-specific, set of damage functions. Hazus includes a sophisticated model of hurricane impact, capable of modelling the specifics of different assets. In the following, the motivation is to combine Hazus damage functions with wind models, such as the IRIS model tropical cyclone model, which can be used for estimating the impact of physical climate change for a portfolio of assets for example for, but certainly not limited to, climate attribution use-cases. In a recent climate attribution study, the authors combined the IRIS hazard model with a generic parametric damage model. Both types of damage functions, the specific and the generic, are useful and it is interesting to consider how the Hazus model relates to the parametric approach.
Defining wind speed#
In their 2009 review paper, :cite:`eberenz2020regional` split wind field modelling into three steps. In the first step, mean wind speed at gradient height, i.e. at a height where surface friction has negligible effect, is obtained (aka gradient wind speed); in the second step, the gradient wind speed is adjusted to a surface level value, and in the third step this surface level wind is adjusted for terrain and averaging time. It is therefore important to ensure that the definition of wind speed in the hazard model is clear because it could be: 1) Gradient wind speed; 2) Sustained surface wind speed, usually by convention the 1 minute average wind speed at 10 metre height for open terrain; 3) Peak gust wind speed adjusted to the local terrain.
Put another way, wind speed requires the specification of: - Height (physrisk default 10 m) - Reference averaging period (physrisk default 1 minute) - Surface roughness (physrisk default ‘open terrain’ / 0.03 m)
In principle a high-resolution wind model needs no specification of surface roughness, it being understood that local conditions are already captured. However a 10 km or 1 km resolution model is unlikely to capture this.
Gust speed / surface roughness#
Common choices of reference averaging period are 3 seconds (sometimes called ‘gust’ wind speed), 1 minute, 3 minutes or 1 hour. In physrisk, wind speed hazard indicators are 1 minute speed unless specified otherwise. As noted in the technical manual 4.4.7, “In Hazus, all damage and loss functions are given as a function of peak gust wind speed, not the one-minute wind speed.” It is therefore necessary to convert the damage functions to match the indicators; moreover it is appropriate that damage functions are specified in terms of the peak gust wind speed since this drives the damage.
Conversion between 1 minute, open-terrain wind speed at 10 metres height to local terrain and 3 second gust speed involves two conversion factors which are both material (although offsetting). As an example, the Engineering Sciences Data Unit (ESDU, 1982) boundary transition model gives a gust factor of 1.28 for converting 1 minute to 3 second wind speed assuming a 0.03 m terrain roughness. Section 4.4.7 (see e.g. Figure 4-72) of the Hazus 5.1 technical manual deals with the impact of surface roughness on wind speed. It provides an example of its model: 3 second gust wind speed is reduced by 18% for suburban terrain (0.35 m) relative to the open terrain value. In this example it can be seen that the factors largely offset, which perhaps justifies why some models approximate the combined gust speed/surface roughness conversion as unity. Of note are also the World Meteorological Organization guidelines of :cite:`harper2010guidelines`. See Table 1.1; for example a gust factor of 1.49 applies when inferring 3 second gust speed from a 60 s reference period wind speed. The ‘Durst curve’ (from the original paper :cite:`durst1960wind`) is used by the ASCE7-05 standard. Review articles such as :cite:`holmes2014gust` give an overview of the standards.
The focus in this section is on vulnerability functions and we do not discuss the gust/terrain adjustment beyond noting that this is material and would require relatively high resolution adjustment factors. The implication for vulnerability functions is that these should be a function of local 3 second gust speed; it is rather for the hazard model to apply the appropriate conversion. Slightly confusingly, Hazus damage curves also depend on surface roughness, however as explained by Section 8 of the Hazus 5.1 technical manual, this relates rather to the impact of wind-driven missiles.
Hazus vulnerability functions and parametric damage functions#
Hazus defines a set of 39 Specific Building Types (SBTs) and defines damage functions within each type for a number of different combinations of Wind Building Characteristics (WBCs) and terrains. As mentioned above, the terrain dimension relates to wind-driven missiles and not to surface roughness conversion. The mapping of assets to a specific curve is one of the challenges addressed by the Hazus tool (there are around 31,000 curves for the combinations of types and terrains for structural damage, for example).
The parameters of the parametric model introduced above originate from :cite:`eberenz2020regional`, which specifies parameters for the model:
Here \(d\) is the damage, expressed as a fraction of the asset value, a function of wind speed, \(v\). The parameters are \(v_t\), the threshold wind value and \(v_h\), the wind speed such that fractional damage is 0.5 (i.e. half asset value). The origin of the default parameters of \(v_h = 74.7 \text{m}\text{s}^{−1}\), \(v_t = 25.7 \text{m}\text{s}^{−1}\) are described in :cite:`sealy2017hurricane`. The authors took Hazus damage curves ‘pertaining to houses with masonry walls’. They found, based on the threshold, \(v_t\), that ‘corresponding wind speed associated with 50 percent of loss ranged between 240 and 320 km/h (67 and 89 m/s) for single masonry units and between 225 and 290 km/h (63 and 81 m/s) for multi and business masonry units’. The value of 74.7 m/s corresponds to the mean of the two mid-points of these ranges, i.e., 280 and 258 km/h. We revisit that analysis below to verify this correspondence of the parameters to the 3 second gust speed.
Mapping asset characteristics to Hazus vulnerability functions#
It is desirable that vulnerability functions can be constructed from assets characterized by the Open Exposure Data (OED) standard. OasisLMF/ODS_OpenExposureData In particular, the following ‘Loc’ input fields are relevant (case changed from Pascal to snake-case): - occupancy_code - construction_code - number_of_storeys
The priority of physrisk is first to cover the cases: 1) Asset-specifics known: OED occupancy_code, construction_code and number_of_storeys is known for the asset; 2) Sectorial model: asset-class, asset type and location are provided.
To reiterate, in the following, a particular aim is to address the case where only approximate building characteristics are known and also estimate the uncertainty around that. We construct a set of average curves for the 39 SBTs and create vulnerability configuration entries for these. For each SBT, the combination of Wind Building Characteristics (WBCs) used in the mapping is tracked. We then construct mappings for 1 and 2. In the case of 2, these are additional vulnerability configuration entries. In the case of 1, the logic that performs the mapping to specific building type is done in code.
[1]:
import numpy as np
import pandas as pd
import plotly.graph_objs as go
import plotly.io
from plotly.subplots import make_subplots
from physrisk.vulnerability_models.configuration.hazus_config_builders import ConfigBuilderHazusWind
plotly.io.renderers.default = "notebook"
[ ]:
# the file is too large to include in the repo; we need to download from S3 before we start as a one-off:
builder = ConfigBuilderHazusWind()
builder.download_inputs()
[2]:
# the building of the configuration items is then done as follows:
builder = ConfigBuilderHazusWind()
config_items = builder.build_config()
print(f"{len(config_items)} vulnerability configuration items created")
print(config_items[38])
234 vulnerability configuration items created
hazard_class='Wind' asset_class='Asset' asset_identifier='hazus_wind_spec_build_type=WSF2' indicator_id='max_speed' indicator_units='m/s' impact_id='damage' impact_units=None curve_type='indicator/piecewise_linear' points_x=array([ 22.352 , 24.5872, 26.8224, 29.0576, 31.2928, 33.528 ,
35.7632, 37.9984, 40.2336, 42.4688, 44.704 , 46.9392,
49.1744, 51.4096, 53.6448, 55.88 , 58.1152, 60.3504,
62.5856, 64.8208, 67.056 , 69.2912, 71.5264, 73.7616,
75.9968, 78.232 , 80.4672, 82.7024, 84.9376, 87.1728,
89.408 , 91.6432, 93.8784, 96.1136, 98.3488, 100.584 ,
102.8192, 105.0544, 107.2896, 109.5248, 111.76 ]) points_y=[0.00034260057159298245, 0.0007429426981390351, 0.0011147235203558335, 0.002243378113413509, 0.0034221181199175876, 0.004351478191238465, 0.006517317764510745, 0.009232639297106623, 0.014230333948337018, 0.02493005067886842, 0.04151441243863597, 0.06772924764486843, 0.10849328012846492, 0.15916405067149123, 0.21714102188377193, 0.2814459969596491, 0.3534032306403509, 0.43021161932017543, 0.4926716189473684, 0.5579136604385965, 0.6198331651754386, 0.6811571389035088, 0.7343256307894737, 0.7749667311842106, 0.8141876436842106, 0.8499647245614035, 0.8789985162280701, 0.9007577017543859, 0.918772457017544, 0.9332439504385964, 0.9445526092105263, 0.9547554504385966, 0.9606896815789475, 0.9695472653508771, 0.9742614425438596, 0.9781663859649123, 0.9823094798245614, 0.9857074245614036, 0.9899214438596491, 0.9912027526315789, 0.9931104864035087] points_z=None cap_of_points_x=None cap_of_points_y=None activation_of_points_x=None
[3]:
# how to extract key values from the comma-separated asset_identifiers:
def asset_ids_to_keys(id_str: str):
keys = {}
for key_value in id_str.split(","):
key, value = key_value.split("=")
keys[key] = value
return keys
[4]:
# here we plot out the masonry specific building type curves, each averaged over all terrain types:
fig1 = make_subplots(rows=1, cols=1)
masonry = ["MSF1", "MSF2", "MMUH1", "MMUH2", "MMUH3", "MLRM1", "MLRM2", "MLRI", "MERBL", "MERBM", "MERBH", "MECBL", "MECBM", "MECBH"]
config_subset = [item for item in config_items if "terrain_id" not in item.asset_identifier and any("hazus_wind_spec_build_type=" + m in item.asset_identifier for m in masonry)]
for item in config_subset:
fig1.add_scatter(x=item.points_x, y=item.points_y, row=1, col=1, name=item.asset_identifier)
#fig1.add_scatter(x=item.points_x / 1.28, y=item.points_y, row=1, col=1, name=item.asset_identifier)
fig1.update_xaxes(title="Wind speed (m/s)", title_font={"size": 14}, row=1, col=1)
fig1.update_yaxes(title="Damage as fraction of TIV", title_font={"size": 14}, row=1, col=1)
fig1.update_layout(legend=dict(orientation="h", y=-0.25))
fig1.update_layout(margin=dict(l=20, r=20, t=20, b=20))
fig1.update_layout(
height=800,
)
def vul(v, v_half):
v_thresh = 25.7
# v_half = 135.6 # wp4 74.7 135.6 190.5
vn = np.where(v > v_thresh, v - v_thresh, 0) / (v_half - v_thresh)
f = vn**3 / (1 + vn**3)
return f
fig1.add_scatter(x=item.points_x, y=vul(item.points_x, 74.7), row=1, col=1, name="Eberenz")
[28]:
file_path = (
"HazusWindDamFunctions_Hazus61.xlsx"
)
# wind building types
wbt_df = pd.read_excel(io=str(file_path), sheet_name="huGBSMapping")
col_mapping = {col:col[:-1] for col in wbt_df.columns if col.endswith("p")}
df_renamed = wbt_df.rename(columns=col_mapping)
sbts = list(col_mapping.values())
sbt_weights = df_renamed.groupby(["Occupancy"])[sbts].mean()
print(sbt_weights[sbts].sum(axis=1))