Hazus flood damage functions

Hazus vulnerability functions

The FEMA Hazus team have provided an extract of the damage functions used in the Hazus 6.1 Flood in an Excel file HazusFloodDamageFunctions_Hazus61.xlsx. This is a highly granular, albeit US-specific, set of damage functions.

There is a point of attention around the use of Hazus flood damage functions. The functions provide damage for negative flood depths. This is because the functions are based on flood depth relative to the height of the first finished floor. The difference is material in cases where the first finished floor is elevated, perhaps with a crawl space or basement underneath. The correct way of applying the functions is to calculate a relative depth, \(d_r\) which is the difference between the absolute flood depth \(d_a\) and the height of the first finished floor above grade, \(d_f\),

\[d_r = d_a - d_f\]

It can also be important to use a minimum relative absolute depth threshold, \(d_t\) in applying the function. To illustrate this, say the finished floor is 1 m above grade and the absolute flood depth is 0 m. Some curves have non-zero damage at -4 feet (-1.22 m) flood depth. Since \(d_r\) is -1.0 m, we would see a non-zero damage. To avoid this a threshold, \(d_t\) can be added to the absolute flood depth, below which the damage is considered to be zero. The logic is then:

if \(d_a < d_t\) then damage is zero, otherwise damage is \(v(d_r)\), \(v\) being the Hazus damage function.

It may be desirable to apply this logic in code, as part of the vulnerability model, so that the calculation can react to asset-specific information. On the other hand, it may be desirable to calculate a function based on absolute flood depth, which is applied to categories of assets.

For this reason, the config builder has an option adjust_to_absolute_depth. If set to False, the curves will be returned as a function of relative depth: the same convention as Hazus. Otherwise (and the default is True), the curves will be adjusted to be functions of absolute depth using the min_flood_depth (default 5 cm) and first_floor_height (default 30 cm) parameters provided. A limitation is noted that these parameters are used across all curves, although clearly some Hazus curves are relevant in the case that a basement is present: in general a more sophisticated approach is needed to adjust all curves.

Identifying the config lines

For wind, config lines were produced of the form hazus_wind_structure_spec_build_type=MLRI,damage_type=structure, which identifies the structural damage curve for the Hazus Specific Building Type ‘MLRI’. For flood these are combined into a single identifier, e.g. hazus_fl_structure_dmg_id=800. The reason for this is that Hazus 6.1 defines different identifiers for structural damage, contents and inventory and the intent is to align with these conventions.

[1]:
import plotly.io
from plotly.subplots import make_subplots
from physrisk.vulnerability_models.configuration.hazus_config_builders import (
    ConfigBuilderHazusFlood,
)

plotly.io.renderers.default = "notebook"
[2]:
# the file is too large to include in the repo; we need to download from S3 before we start as a one-off:
builder = ConfigBuilderHazusFlood()
builder.download_inputs()
[3]:
# the building of the configuration items is then done as follows:
builder = ConfigBuilderHazusFlood()
config_items = builder.build_config()
print(f"{len(config_items)} vulnerability configuration items created")
print(config_items[38])
1826 vulnerability configuration items created
hazard_class='CoastalInundation,PluvialInundation,RiverineInundation' asset_class='Asset' asset_identifier='hazus_fl_structure_dmg_id=143' indicator_id='flood_depth' indicator_units='metres' impact_id='damage' impact_units=None curve_type='indicator/piecewise_linear' points_x=array([0.    , 0.05  , 0.3   , 0.6048, 0.9096, 1.2144, 1.5192, 1.824 ,
       2.1288, 2.4336, 2.7384, 3.0432, 3.348 , 3.6528, 3.9576, 4.2624,
       4.5672, 4.872 , 5.1768, 5.4816, 5.7864, 6.0912, 6.396 , 6.7008,
       7.0056, 7.3104, 7.6152]) points_y=array([0.  , 0.  , 0.01, 0.22, 0.28, 0.31, 0.33, 0.48, 0.48, 0.48, 0.48,
       0.56, 0.56, 0.58, 0.58, 0.58, 0.58, 0.58, 0.58, 0.58, 0.58, 0.58,
       0.58, 0.58, 0.58, 0.58, 0.58]) points_z=None points_kind=None cap_of_points_x=None cap_of_points_y=None activation_of_points_x=None
[4]:
fig1 = make_subplots(rows=1, cols=1)


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


config_subset = [
    item
    for item in config_items
    if int(
        asset_ids_to_keys(item.asset_identifier).get("hazus_fl_structure_dmg_id", 9990)
    )
    < 120
]
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="Flood depth (m)", 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.1))
fig1.update_layout(margin=dict(l=20, r=20, t=20, b=20))
fig1.update_layout(
    height=800,
)