ASFE21 Part 2: Failure Probability Based Approach

Part 1 of the analysis carried out for the conference paper submitted to ASFE21, “An Improved Reliability-Based Approach to Sepcifying Fire Resistance Periods For Buildings in England”

2021 May, Ian F.

Structural failure probability

Prepare MCS inputs

[5]:
print_df(df_inputs_2)
Residential Office Retail
case_name
n_simulations 10000 10000 10000
fire_time_step 10 10 10
fire_time_duration 18000 18000 18000
fire_hrr_density:dist uniform_ uniform_ uniform_
fire_hrr_density:lbound 0.32 0.15 0.27
fire_hrr_density:ubound 0.57 0.65 1.0
fire_load_density:dist gumbel_r_ gumbel_r_ gumbel_r_
fire_load_density:lbound 10 10 10.0
fire_load_density:ubound 1200 1200 2000.0
fire_load_density:mean 780 420 600.0
fire_load_density:sd 234 126 180.0
fire_spread_speed:dist uniform_ uniform_ uniform_
fire_spread_speed:lbound 0.0035 0.0035 0.0035
fire_spread_speed:ubound 0.019 0.019 0.019
fire_nft_limit:dist norm_ norm_ norm_
fire_nft_limit:lbound 623.15 623.15 623.15
fire_nft_limit:ubound 1473.15 1473.15 1473.15
fire_nft_limit:mean 1323.15 1323.15 1323.15
fire_nft_limit:sd 93 93 93
fire_combustion_efficiency:dist uniform_ uniform_ uniform_
fire_combustion_efficiency:lbound 0.8 0.8 0.8
fire_combustion_efficiency:ubound 1.0 1.0 1.0
window_open_fraction:dist lognorm_mod_ lognorm_mod_ lognorm_mod_
window_open_fraction:ubound 0.9999 0.9999 0.9999
window_open_fraction:lbound 0.0001 0.0001 0.0001
window_open_fraction:mean 0.2 0.2 0.2
window_open_fraction:sd 0.2 0.2 0.2
phi_teq:dist lognorm_ lognorm_ lognorm_
phi_teq:mean 1 1 1
phi_teq:sd 0.25 0.25 0.25
phi_teq:ubound 3 3 3
phi_teq:lbound 0.0001 0.0001 0.0001
beam_cross_section_area 0.017 0.017 0.017
beam_position_vertical 3.2 3.2 3.2
beam_rho 7850 7850 7850
fire_mode 3 3 3
fire_gamma_fi_q 1 1 1
fire_t_alpha 300 300 300
fire_tlim 0.333 0.333 0.333
protection_c 1700 1700 1700
protection_k 0.2 0.2 0.2
protection_protected_perimeter 2.14 2.14 2.14
protection_rho 800 800 800
room_height:dist constant_ uniform_ constant_
room_height:lbound 2.4 2.8 4.5
room_height:ubound 2.4 4.5 7.0
room_wall_thermal_inertia 720 720 720
solver_temperature_goal 893.15 893.15 893.15
solver_max_iter 20 20 20
solver_thickness_lbound 0.0001 0.0001 0.0001
solver_thickness_ubound 0.045 0.045 0.045
solver_tol 1.0 1.0 1.0
window_open_fraction_permanent 0 0 0
timber_exposed_area 0 0 0
timber_charring_rate 0.7 0.7 0.7
timber_hc 13.2 13.2 13.2
timber_density 400 400 400
timber_solver_ilim 20 20 20
timber_solver_tol 1 1 1
beam_position_horizontal_ratio:dist uniform_ uniform_ uniform_
beam_position_horizontal_ratio:lbound 0.6 0.6 0.6
beam_position_horizontal_ratio:ubound 0.9 0.9 0.9
room_floor_area:dist uniform_ uniform_ constant_
room_floor_area:lbound 9.0 50.0 400.0
room_floor_area:ubound 30.0 1000.0 400.0
room_breadth_depth_ratio:dist uniform_ uniform_ uniform_
room_breadth_depth_ratio:lbound 0.4 0.4 0.4
room_breadth_depth_ratio:ubound 0.6 0.6 0.6
window_height_room_height_ratio:dist uniform_ uniform_ uniform_
window_height_room_height_ratio:lbound 0.3 0.3 0.5
window_height_room_height_ratio:ubound 0.9 0.9 1.0
window_area_floor_ratio:dist uniform_ uniform_ uniform_
window_area_floor_ratio:lbound 0.05 0.05 0.05
window_area_floor_ratio:ubound 0.2 0.4 0.4

Run MCS

[6]:
# Run MCS
cases_to_run=['Residential', 'Office', 'Retail']
mcs = MCS2(print_stats=False)
mcs.inputs = df_inputs_2
mcs.n_threads = 6
mcs.run_mcs(cases_to_run=cases_to_run)
CASE                    : Residential
NO. OF THREADS          : 6
NO. OF SIMULATIONS      : 10000
100%|███████████████| 10000/10000 [00:05<00:00, 1968.03it/s]
CASE                    : Office
NO. OF THREADS          : 6
NO. OF SIMULATIONS      : 10000
100%|███████████████| 10000/10000 [00:04<00:00, 2452.21it/s]
CASE                    : Retail
NO. OF THREADS          : 6
NO. OF SIMULATIONS      : 10000
100%|███████████████| 10000/10000 [00:04<00:00, 2459.49it/s]

Time equivalence results

[8]:
fig, ax = plt.subplots(figsize=(2.5,2.5), dpi=100);
lss = ['-', '-.', 'dotted']
FRs = np.linspace(30, 180, 100)
for i, case in enumerate(cases_to_run):
    ax.plot(FRs, dict_func_teq2cdf[case](FRs), label=case, ls=lss[i], c='k')
format_ax(ax=ax, xlabel='Equivalent of time exposure, $x$ [$min$]', xlabel_fontsize='x-small', xlim=(30, 180), ylabel=r'CDF or $P(t_{eq,i}\leq x)$', ylim=(0, 1), xticks=np.arange(30, 181, 15,), yticks=np.arange(0, 1.1, 0.1))

savefig(fig, 'teq_2.png')
../../_images/user_guide_mcs2_asfe21_02_11_0.png

Comparing against Kirby et al

[9]:
kirby = pd.concat([
    pd.DataFrame({'Residential': [0.169, 0.193, 0.361, 0.629, 0.844, 0.953, 0.991]}, index=[30, 45, 60, 75, 90, 105, 120]),
    pd.DataFrame({'Office':      [0.464, 0.647, 0.800, 0.896, 0.928, 0.973, 0.982]}, index=[30, 45, 60, 75, 90, 105, 120]),
    pd.DataFrame({'Retail':      [0.404,        0.734,        0.912,        0.968]}, index=[30,     60,     90,      120]),
], axis=1)
kirby.index.name = 'teq'

# Compare against Kirby
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(2.1*3, 2.5), sharex=True, sharey=True, dpi=100)

for i, case in enumerate(cases_to_run):
    ax = axes[i]
    ax.scatter(kirby.index.values, kirby[case].values, label='Kirby et al', marker='o', facecolors='none', edgecolors='k', linewidths=.8)
    ax.plot(kirby.index.values[~np.isnan(kirby[case].values)], kirby[case].values[~np.isnan(kirby[case].values)], ls='--', c='k', lw=.5)
    ax.scatter(kirby.index.values, dict_func_teq2cdf[case](kirby.index.values), label='SFEPRAPY', marker='^', facecolors='none', edgecolors='k', linewidths=.8)
    ax.plot(kirby.index.values, dict_func_teq2cdf[case](kirby.index.values), ls='-.', c='k', lw=.5)
    format_ax(ax=ax, xlabel='Equivalent of time exposure [$min$]', xlabel_fontsize='x-small', xticks=np.arange(30, 121, 30), xticks_minor=np.arange(30, 121, 15), ylim=(0, 1), yticks=np.arange(0, 1.1, 0.1), legend_title=case, legend_loc=4, legend_fontsize='xx-small', legend_title_fontsize='xx-small')
axes[0].set_ylabel('CDF', fontsize='x-small')

savefig(fig, 'benchmark_2.png')
../../_images/user_guide_mcs2_asfe21_02_13_0.png

\(P_{f,fi}\) Failure probabilies due to structurally signification fire

[10]:
dict_p_i = {
    "Residential": dict(p_1=6.5e-7, p_2=0.2, p_3=0.0625, p_4=1),
    "Office": dict(p_1=3.0e-7, p_2=0.2, p_3=0.25, p_4=1),
    "Retail": dict(p_1=4.0e-7, p_2=0.2, p_3=0.25, p_4=1),
}

fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(2.3*3, 2.5), sharex=True, sharey=True, dpi=100)
lss = ['-', (0, (5, 1)), '--', '-.', (0, (3, 1, 1, 1)), ':', (0, (5, 10))]
for i, case in enumerate(dict_teq.keys()):
    ax = axes[i]
    t = np.linspace(0, 180, 200)  # x-axis, time
    P_f_fi = 1 - dict_func_teq2cdf[case](t)  # failure probability due to structurally significant fires
    p_fi = np.prod(list(dict_p_i[case].values()))  # probability of structural significant fire occurance

    S_and_A = ((4, 800), (15, 800), (4, 1600), (15, 1600)) if case == 'Residential' else ((4, 1000), (15, 1000), (4, 2000), (15, 2000))

    for j, (S_, A_) in enumerate(S_and_A):
        ax.plot(t, p_fi * P_f_fi * (S_ * A_), label=f'S={S_:.0f}, $A_i$={A_*1e-3:.0f}k $m^2$', c='k', ls=lss[j], lw=1)
    format_ax(ax=ax, xlabel='Equivalent of time exposure [$min$]', xlim=(30, 180), xticks=np.arange(30, 181, 15), yscale='log', legend_title=case, legend_ncol=1, legend_loc=3, legend_fontsize='xx-small', legend_borderpad=0.1, legend_labelspacing=0.1)

ax = axes[0]
ax.set_ylabel('$P_{f,fi}$, failure probability due to\nstructurally significant fire [${year}^{-1}$]', fontsize='x-small')

savefig(fig, 'P_f_fi_vs_A.png')
../../_images/user_guide_mcs2_asfe21_02_15_0.png