{ "cells": [ { "cell_type": "markdown", "id": "494085e1", "metadata": {}, "source": [ "# Hazus flood damage functions\n", "\n", "## Hazus vulnerability functions\n", "The [FEMA Hazus](https://www.fema.gov/flood-maps/tools-resources/flood-map-products/hazus/user-technical-manuals) 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.\n", "\n", "There is a point of attention around the use of Hazus flood damage functions. The functions provide damage\n", "for negative flood depths. This is because the functions are based on flood depth *relative to the height\n", "of the first finished floor*. The difference is material in cases where the first finished floor is elevated,\n", "perhaps with a crawl space or basement underneath. The correct way of applying the functions is to calculate\n", "a relative depth, $d_r$ which is the difference between the absolute flood depth $d_a$ and the height\n", "of the first finished floor above grade, $d_f$,\n", "\n", "$$d_r = d_a - d_f$$\n", "\n", "It can also be important to use a minimum relative absolute depth threshold, $d_t$ in applying the\n", "function. To illustrate this, say the finished floor is 1 m above grade and the absolute flood depth\n", "is 0 m. Some curves have non-zero damage at -4 feet (-1.22 m) flood depth. Since $d_r$ is -1.0 m,\n", "we would see a non-zero damage. To avoid this a threshold, $d_t$ can be added to the absolute\n", "flood depth, below which the damage is considered to be zero. The logic is then:\n", "\n", "if $d_a < d_t$ then damage is zero, otherwise damage is $v(d_r)$, $v$ being the Hazus damage function.\n", "\n", "It may be desirable to apply this logic in code, as part of the vulnerability model, so that the calculation\n", "can react to asset-specific information. On the other hand, it may be desirable to calculate a function\n", "based on absolute flood depth, which is applied to categories of assets.\n", "\n", "For this reason, the config builder has an option ```adjust_to_absolute_depth```. If set to False, \n", "the curves will be returned as a function of relative depth:\n", "the same convention as Hazus. Otherwise (and the default is True), the curves will be adjusted to be functions of absolute depth\n", "using the ```min_flood_depth``` (default 5 cm) and ```first_floor_height``` (default 30 cm) parameters provided. A limitation is noted that these\n", "parameters are used across all curves, although clearly some Hazus curves are relevant in the case that a\n", "basement is present: in general a more sophisticated approach is needed to adjust _all_ curves.\n", "\n", "## Identifying the config lines\n", "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." ] }, { "cell_type": "code", "execution_count": 1, "id": "2a07ed74", "metadata": {}, "outputs": [], "source": [ "import plotly.io\n", "from plotly.subplots import make_subplots\n", "from physrisk.vulnerability_models.configuration.hazus_config_builders import (\n", " ConfigBuilderHazusFlood,\n", ")\n", "\n", "plotly.io.renderers.default = \"notebook\"" ] }, { "cell_type": "code", "execution_count": 2, "id": "8bb10b62", "metadata": {}, "outputs": [], "source": [ "# the file is too large to include in the repo; we need to download from S3 before we start as a one-off:\n", "builder = ConfigBuilderHazusFlood()\n", "builder.download_inputs()" ] }, { "cell_type": "code", "execution_count": 3, "id": "34111c12", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1826 vulnerability configuration items created\n", "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 ,\n", " 2.1288, 2.4336, 2.7384, 3.0432, 3.348 , 3.6528, 3.9576, 4.2624,\n", " 4.5672, 4.872 , 5.1768, 5.4816, 5.7864, 6.0912, 6.396 , 6.7008,\n", " 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,\n", " 0.56, 0.56, 0.58, 0.58, 0.58, 0.58, 0.58, 0.58, 0.58, 0.58, 0.58,\n", " 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\n" ] } ], "source": [ "# the building of the configuration items is then done as follows:\n", "builder = ConfigBuilderHazusFlood()\n", "config_items = builder.build_config()\n", "print(f\"{len(config_items)} vulnerability configuration items created\")\n", "print(config_items[38])" ] }, { "cell_type": "code", "execution_count": 4, "id": "36d986d3", "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig1 = make_subplots(rows=1, cols=1)\n", "\n", "\n", "def asset_ids_to_keys(id_str: str):\n", " keys = {}\n", " for key_value in id_str.split(\",\"):\n", " key, value = key_value.split(\"=\")\n", " keys[key] = value\n", " return keys\n", "\n", "\n", "config_subset = [\n", " item\n", " for item in config_items\n", " if int(\n", " asset_ids_to_keys(item.asset_identifier).get(\"hazus_fl_structure_dmg_id\", 9990)\n", " )\n", " < 120\n", "]\n", "for item in config_subset:\n", " fig1.add_scatter(\n", " x=item.points_x, y=item.points_y, row=1, col=1, name=item.asset_identifier\n", " )\n", "# fig1.add_scatter(x=item.points_x / 1.28, y=item.points_y, row=1, col=1, name=item.asset_identifier)\n", "fig1.update_xaxes(title=\"Flood depth (m)\", title_font={\"size\": 14}, row=1, col=1)\n", "fig1.update_yaxes(\n", " title=\"Damage as fraction of TIV\", title_font={\"size\": 14}, row=1, col=1\n", ")\n", "fig1.update_layout(legend=dict(orientation=\"h\", y=-0.1))\n", "fig1.update_layout(margin=dict(l=20, r=20, t=20, b=20))\n", "fig1.update_layout(\n", " height=800,\n", ")" ] } ], "metadata": { "kernelspec": { "display_name": "physrisk-lib", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.13" } }, "nbformat": 4, "nbformat_minor": 5 }