Vulnerability models
Programmatic models and configuration
Vulnerability models can either be created in code — these are’programmatic models’ — or specified via lines configuration.
Programmatic models are appropriate when there is complex logic to be captured, best expressed in code. For example assigning damage curves to assets for the modelling of flood hazards may be based on attributes such as the building’s number of storeys and there may be rules about how curves are modified to take account of the height of the first floor.
In other cases it is desirable to assign curves to broad families of assets; a model of productivity loss might specify curves depending on the industrial sector, reflecting of the nature of labour within the sectors. For such cases specificaiton via configuration can be more transparent and convenient.
The principle of configuration is that human-readable lines in a file can be used to relate a hazard indicator value (e.g. flood depth or number of days per year above a certain temperature) to damage or disruption.
Specification of assets
The default behaviour of physrisk is as follows:
Assets can be specified using physrisk asset classes, e.g. RealEstateAsset, ManufacturingAsset, which inherit from Asset or by Open Exposure Data (OED) attributes, e.g. occupancy code.
For assets specified only by OED attributes, physrisk will map these onto physrisk asset classes, potentially with an additional
typeattribute, using a configuration — which users can customize — whilst also retaining the OED attributes. This is done so that vulnerability models can make use of either OED properties or asset class and type. For example, OED occupancy codes from 1050 to 1099 will be used to create instances of RealEstateAsset withtype“Buildings/Residential”. This serves as text that can be matched to vulnerability configuration.Why is this done? Some vulnerability models are fine-grained and make full use of asset attributes, an example being the vulnerability functions for flood which may depend on occupancy, number of storeys elevation of the first finished floor etc. Other vulnerability models are sectorial in nature — that is, the vulnerability depends on the sector to which the asset belongs. An example is a model of change in productivity associated with chronic heat (change in temperature extremes) where the vulnerability is more a function of the sector to which the asset belongs.
Specification of vulnerability models
For any type of asset, e.g. RealEstateAsset, multiple vulnerability models are assigned which are uniquely specified by:
Hazard type, e.g. Wind, RiverineInundation, ChronicHeat etc
Hazard indicator identifier, e.g. ‘flood_depth’, ‘days_wbgt_above’ (number of days with wet bulb globe temperature above different thresholds)
Impact type: ‘damage’ (to asset structure, contents or inventory) or ‘disruption’ (to revenue generation)
Some hazards may have just a single mechanism for loss, e.g. riverine inundation depends on flood depth; others, e.g. chronic heat has multiple mechanisms, with different indicators.
Vulnerability models are defined in two steps: 1) For specific asset types, programmatic vulnerability models are assigned.
Vulnerability models are created and assigned based on the vulnerability configuration.
The rule is that the models of step 2 do not replace those of step 1; if a programmatic model exists for RiverineInundation and RealEstateAssets that models damage based on flood depth, this is not replaced by such a model defined in configuration. The reason for this is that vulnerability configuration can be specified that is generic in that it applies to all asset types.
By default in step 1, programmatic models are assigned to power generating assets and programmatic inundation and wind models are assigned to all other asset types. These select damage curves from FEMA Hazus, based on Open Exposure Data attributes of the asset.
Vulnerability configuration
Types of curve
curve_type:
indicator/piecewise_linear.Threshold curves For chronic risks, this specifies the fractional damage or disruption that occurs for hazard indicator threshold values. This is for hazard indicators that give the mean amount of time per year for which an indicator is greater than a threshold value.
curve_type:threshold/piecewise_linear. e.g. for chronic heat, the indicator might be the number of days per year for which the maximum near-surface air temperature is greater than \(t\) degrees, \(t\) being the threshold values. The curve \(x\) values are the thresholds in degrees Celsius and the curve \(y\) values are the losses in production that occur for each day for which the maximum temperature is at that value.
Identifying assets
Assets are identified by: - Asset class. This is the broad class of asset e.g. real estate assets or power generating assets within which asset vulnerabilities tend to be modelled in a similar way and which tend to have a common set of attributes. The set of valid asset classes is defined within physrisk itself. - A number of asset attributes. Specifying the asset class is optional in that vulnerability curves can be defined for the parent Asset type, in which case only asset attributes
are relevant.
Identifying assets within the configuration
The vulnerability function is associated to an asset by specification of the asset class and by a set of attribute key/value pairs in the form of a comma-separated string: ‘=<attribute1_value,=,…’. The attributes are matched to those of the asset.
Example 1: simple type/location model
We define two special attribute names: type and location. These are particularly suited for sectorial modelling applications or similar where little is known about the asset other than its class, some information about the type within the class and its location. For example, configuration might be provided for real estate assets in the form ‘type=Buildings/Commercial,location=Europe’. For sectorial analyses, type is based around industry classifications (e.g. NACE codes).
Example 2: occupancy identifier and attributes
Occupancy classifications are used to group assets with similar characteristics related to valuation and damage, or disruption characteristics. There are a number of important occupancy schemes, for example Open Exposure Data (OED). Assets can be identified via, occupancy_scheme, occupancy_id and a set of attributes needed to refine the selection, e.g. number of storeys within a particular occupancy identifier.
Example 3: explicit specification of curve
For families of vulnerability functions, we can define a set of curves by, e.g. ‘hazus_flood_curve_id=43’.
In all cases, logic in the code maps an asset’s attributes onto the attributes that define the vulnerability function.
Damage/disruption function specification
The scheme is designed to allow uncertainly in damage/disruption functions to be specified as well as the deterministic case comprising hazard indicator (\(x\)) values and the corresponding impact (damage/disruption) (\(y\)) values. This can be captured by \(x\) and \(y\) fields each containing an array. A third \(z\) field to capture information about the uncertainty in the vulnerability functions.
Case 1: deterministic damage curve provided
The hazard indicator values, \(x_i\), are given, \(i \in [1 \dots n]\) and the corresponding impacts \(y_i\).
Case 2: mean and standard deviation provided
The hazard indicator values, \(x_i\), are given, \(i \in [1 \dots n]\).
The means are given in \(y\) and the standard deviations in \(z\).
Case 3: discrete piece-wise linear cumulative density function (CDF) provided
The hazard indicator values, \(x_i\), are given, \(i \in [1 \dots n]\).
\(F_i(y) = \mathbb{P}(Y \leq y|x_i)\)
The CDF, \(F_i(y)\), is given for points \(y_j\), \(j \in [1 \dots m]\). \(F_{ij} = \mathbb{P}(Y \leq y_j|x_i)\)
Example configuration: displaying
[1]:
# pip install nbformat pandas plotly requests
from io import StringIO
from physrisk.vulnerability_models.config_based_impact_curves import (
config_items_from_csv,
config_items_to_df,
)
import plotly.io
from plotly.subplots import make_subplots
plotly.io.renderers.default = "notebook"
[2]:
# Rainbow CSV is a useful add-in for dealing with vulnerability config as CSV.
# Here we paste in a couple of lines.
config_lines = """
hazard_class,asset_class,asset_identifier,indicator_id,indicator_units,impact_id,impact_units,curve_type,points_x,points_y,cap_of_points_x,cap_of_points_y,activation_of_points_x
"CoastalInundation,PluvialInundation,RiverineInundation,",RealEstateAsset,"type=Buildings/Residential,location=Europe",flood_depth,metres,damage,,indicator/piecewise_linear,"[0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0]","[0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0]",,,
ChronicHeat,ManufacturingAsset,"type=Chemical,location=Generic",days_tas/above/{temp_c}c,days/year,disruption,,threshold/piecewise_linear,"[15.0, 25.0, 35.0, 45.0, 55.0, 65.0]","[0.0, 0.1, 0.25, 0.5, 0.8, 1.0]",,,
"""
[3]:
config_items = config_items_from_csv(StringIO(config_lines))
df = config_items_to_df(config_items)
display(df)
| hazard_class | asset_class | asset_identifier | indicator_id | indicator_units | impact_id | impact_units | curve_type | points_x | points_y | points_z | points_kind | cap_of_points_x | cap_of_points_y | activation_of_points_x | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | ChronicHeat | ManufacturingAsset | type=Chemical,location=Generic | days_tas/above/{temp_c}c | days/year | disruption | None | threshold/piecewise_linear | [15.0, 25.0, 35.0, 45.0, 55.0, 65.0] | [0.0, 0.1, 0.25, 0.5, 0.8, 1.0] | None | None | None | None | None |
| 1 | CoastalInundation | RealEstateAsset | type=Buildings/Residential,location=Europe | flood_depth | metres | damage | None | indicator/piecewise_linear | [0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0] | [0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0] | None | None | None | None | None |
| 2 | PluvialInundation | RealEstateAsset | type=Buildings/Residential,location=Europe | flood_depth | metres | damage | None | indicator/piecewise_linear | [0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0] | [0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0] | None | None | None | None | None |
| 3 | RiverineInundation | RealEstateAsset | type=Buildings/Residential,location=Europe | flood_depth | metres | damage | None | indicator/piecewise_linear | [0.05, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0] | [0.0, 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1.0] | None | None | None | None | None |
[4]:
c1 = next(
c
for c in config_items
if c.asset_class == "RealEstateAsset" and c.indicator_id == "flood_depth"
)
c2 = next(
c
for c in config_items
if c.asset_class == "ManufacturingAsset"
and c.indicator_id == "days_tas/above/{temp_c}c"
)
fig1 = make_subplots(rows=1, cols=2)
fig1.add_scatter(
x=c1.points_x, y=c1.points_y, name="Example damage curve", row=1, col=1
)
fig1.add_scatter(
x=c2.points_x, y=c2.points_y, name="Example threshold curve", row=1, col=2
)
fig1.update_xaxes(title="Flood depth (m)", title_font={"size": 14}, row=1, col=1)
fig1.update_xaxes(title="Threshold (°C)", title_font={"size": 14}, row=1, col=2)
fig1.update_yaxes(title="Damage as fraction of insurable value", row=1, col=1)
fig1.update_yaxes(title="Fractional loss of production", row=1, col=2)
fig1.update_layout(legend=dict(orientation="h", y=-0.15))
# fig1.update_layout(legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01))
fig1.update_layout(margin=dict(l=20, r=20, t=20, b=20))