Worked Example in Python¶
10th Aug 2021, Ian Fu
An worked example of sfeprapy.mcs0 module running a built-in exmaple input file.
[1]:
# Dependencies, helper functions
from IPython.display import display, HTML # Used to display DataFrame in notebook
Inputs¶
[2]:
from sfeprapy.mcs0 import EXAMPLE_INPUT_DF # Example input
inputs = EXAMPLE_INPUT_DF.copy() # Make a copy
# Make some changes to the default inputs
inputs.loc['n_simulations'] = 5_000 # limit to 1,000 iterations for each case
inputs.loc['solver_thickness_ubound'] = 0.045 # Change protection max thickness to 0.045 m
display(HTML(inputs.to_html())) # Print in HTML
| Standard Case 1 | Standard Case 2 (with teq_phi) | Standard Case 3 (with timber) | |
|---|---|---|---|
| case_name | |||
| n_simulations | 5000 | 5000 | 5000 |
| fire_time_step | 10 | 10 | 10 |
| fire_time_duration | 18000 | 18000 | 18000 |
| fire_hrr_density:dist | uniform_ | uniform_ | uniform_ |
| fire_hrr_density:lbound | 0.249 | 0.249 | 0.249 |
| fire_hrr_density:ubound | 0.251 | 0.251 | 0.251 |
| fire_load_density:dist | gumbel_r_ | gumbel_r_ | gumbel_r_ |
| fire_load_density:lbound | 10 | 10 | 10 |
| fire_load_density:ubound | 1500 | 1500 | 1500 |
| fire_load_density:mean | 420 | 420 | 420 |
| fire_load_density:sd | 126 | 126 | 126 |
| 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 | constant_ | lognorm_ | constant_ |
| phi_teq:ubound | 1 | 3 | 1 |
| phi_teq:lbound | 1 | 0.00001 | 1 |
| phi_teq:mean | 0 | 1 | 0 |
| phi_teq:sd | 0 | 0.25 | 0 |
| beam_cross_section_area | 0.017 | 0.017 | 0.017 |
| beam_position_horizontal:dist | uniform_ | uniform_ | uniform_ |
| beam_position_horizontal:lbound | 18.75 | 18.75 | 18.75 |
| beam_position_horizontal:ubound | 28.125 | 28.125 | 28.125 |
| 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_breadth | 16 | 16 | 16 |
| room_depth | 31.25 | 31.25 | 31.25 |
| room_height | 3.3 | 3.3 | 3.3 |
| room_wall_thermal_inertia | 720 | 720 | 720 |
| solver_temperature_goal | 823.15 | 823.15 | 823.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_height | 2.8 | 2.8 | 2.8 |
| window_width | 72 | 72 | 72 |
| window_open_fraction_permanent | 0 | 0 | 0 |
| timber_exposed_area | 0 | 0 | 500.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 |
| p1 | 0.0 | 0.0 | 0.0 |
| p2 | 0.1 | 0.1 | 0.1 |
| p3 | 0.25 | 0.25 | 0.25 |
| p4 | 0.09 | 0.09 | 0.09 |
| general_room_floor_area | 500 | 500 | 500 |
Run MCS¶
[3]:
from sfeprapy.mcs0 import MCS0 # MCS0 class, used to take inputs, run simulation etc.
my_mcs = MCS0()
my_mcs.inputs = inputs
my_mcs.n_threads = 4
my_mcs.run_mcs()
CASE : Standard Case 1
NO. OF THREADS : 4
NO. OF SIMULATIONS : 5000
100%|█████████████████| 5000/5000 [00:03<00:00, 1658.70it/s]
fire_type : {0: 92, 1: 4907}
beam_position_horizontal: 18.750 23.438 28.125
window_open_fraction : 0.000 0.811 1.000
fire_combustion_efficien: 0.800 0.900 1.000
fire_hrr_density : 0.249 0.250 0.251
fire_load_density : 10.000 420.059 1500.000
fire_nft_limit : 992.583 1312.528 1473.150
fire_spread_speed : 0.004 0.011 0.019
phi_teq : 1.000 1.000 1.000
timber_fire_load : 0.000 0.000 0.000
CASE : Standard Case 2 (with teq_phi)
NO. OF THREADS : 4
NO. OF SIMULATIONS : 5000
100%|█████████████████| 5000/5000 [00:03<00:00, 1657.37it/s]
fire_type : {1: 4896, 0: 100}
beam_position_horizontal: 18.750 23.438 28.125
window_open_fraction : 0.000 0.812 1.000
fire_combustion_efficien: 0.800 0.900 1.000
fire_hrr_density : 0.249 0.250 0.251
fire_load_density : 10.000 419.923 1500.000
fire_nft_limit : 992.583 1312.503 1473.150
fire_spread_speed : 0.004 0.011 0.019
phi_teq : 0.000 1.000 3.000
timber_fire_load : 0.000 0.000 0.000
CASE : Standard Case 3 (with timber)
NO. OF THREADS : 4
NO. OF SIMULATIONS : 5000
100%|██████████████████| 5000/5000 [00:25<00:00, 199.23it/s]
fire_type : {0: 232, 1: 3257}
beam_position_horizontal: 18.750 23.249 28.123
window_open_fraction : 0.000 0.818 1.000
fire_combustion_efficien: 0.800 0.898 1.000
fire_hrr_density : 0.249 0.250 0.251
fire_load_density : 228.671 663.885 1607.459
fire_nft_limit : 992.583 1308.322 1472.988
fire_spread_speed : 0.004 0.012 0.019
phi_teq : 1.000 1.000 1.000
timber_fire_load : 50634.284 125581.062 309776.473
All results¶
[4]:
results = my_mcs.mcs_out
results
[4]:
| case_name | n_simulations | index | beam_cross_section_area | beam_position_vertical | beam_position_horizontal | beam_rho | fire_time_duration | fire_time_step | fire_combustion_efficiency | ... | solver_steel_temperature_solved | solver_time_critical_temp_solved | solver_protection_thickness | solver_iter_count | solver_time_equivalence_solved | timber_exposed_duration | timber_solver_iter_count | timber_fire_load | timber_charred_mass | timber_charred_volume | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2664 | Standard Case 1 | 5000.0 | 2664 | 0.017 | 3.2 | 22.356346 | 7850.0 | 18000.0 | 10.0 | 0.983557 | ... | 618.737664 | 3990.0 | -inf | 0.0 | -inf | 0.0 | 0 | 0.000000 | 0.000000 | 0.000000 |
| 1685 | Standard Case 1 | 5000.0 | 1685 | 0.017 | 3.2 | 25.411332 | 7850.0 | 18000.0 | 10.0 | 0.813443 | ... | 822.647299 | 810.0 | 0.006103 | 7.0 | 1678.944357 | 0.0 | 0 | 0.000000 | 0.000000 | 0.000000 |
| 2986 | Standard Case 1 | 5000.0 | 2986 | 0.017 | 3.2 | 24.059187 | 7850.0 | 18000.0 | 10.0 | 0.968234 | ... | 822.307370 | 800.0 | 0.006141 | 8.0 | 1687.044809 | 0.0 | 0 | 0.000000 | 0.000000 | 0.000000 |
| 3621 | Standard Case 1 | 5000.0 | 3621 | 0.017 | 3.2 | 19.824590 | 7850.0 | 18000.0 | 10.0 | 0.942348 | ... | 823.591300 | 810.0 | 0.006141 | 5.0 | 1687.169770 | 0.0 | 0 | 0.000000 | 0.000000 | 0.000000 |
| 2568 | Standard Case 1 | 5000.0 | 2568 | 0.017 | 3.2 | 23.982296 | 7850.0 | 18000.0 | 10.0 | 0.838248 | ... | 823.744601 | 820.0 | 0.006246 | 8.0 | 1709.515038 | 0.0 | 0 | 0.000000 | 0.000000 | 0.000000 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4991 | Standard Case 3 (with timber) | 5000.0 | 4991 | 0.017 | 3.2 | 27.888703 | 7850.0 | 18000.0 | 10.0 | 0.890338 | ... | NaN | NaN | NaN | NaN | NaN | NaN | 20 | 164870.112663 | 12490.160050 | 31.225400 |
| 4992 | Standard Case 3 (with timber) | 5000.0 | 4992 | 0.017 | 3.2 | 22.701415 | 7850.0 | 18000.0 | 10.0 | 0.864813 | ... | NaN | NaN | NaN | NaN | NaN | NaN | 20 | 136270.215830 | 10323.501199 | 25.808753 |
| 4993 | Standard Case 3 (with timber) | 5000.0 | 4993 | 0.017 | 3.2 | 20.420959 | 7850.0 | 18000.0 | 10.0 | 0.907702 | ... | NaN | NaN | NaN | NaN | NaN | NaN | 20 | 111248.304573 | 8427.901862 | 21.069755 |
| 4995 | Standard Case 3 (with timber) | 5000.0 | 4995 | 0.017 | 3.2 | 21.148605 | 7850.0 | 18000.0 | 10.0 | 0.868454 | ... | NaN | NaN | NaN | NaN | NaN | NaN | 20 | 197247.050619 | 14942.958380 | 37.357396 |
| 4997 | Standard Case 3 (with timber) | 5000.0 | 4997 | 0.017 | 3.2 | 26.688463 | 7850.0 | 18000.0 | 10.0 | 0.961832 | ... | NaN | NaN | NaN | NaN | NaN | NaN | 20 | 128566.224690 | 9739.865507 | 24.349664 |
15000 rows × 60 columns
Time equivalence results¶
[5]:
# Get time equivalence results to a dictionary
import numpy as np
dict_teq = dict()
for case in inputs.columns:
teq = results.loc[results['case_name']==case]['solver_time_equivalence_solved']
teq = teq[~np.isnan(teq)] # Remove np.nan values
teq[teq==-np.inf] = np.amin(teq[teq>-np.inf]) # Replace -np.inf values
teq[teq==np.inf] = np.amax(teq[teq<np.inf]) # Replace np.inf values
dict_teq[case] = teq / 60. # seconds to minutes
[6]:
# Make time equivalence CDF plots
import matplotlib.pyplot as plt
%matplotlib inline
fig, ax = plt.subplots(dpi=100)
for case in inputs.columns:
n, bins, patches = ax.hist(dict_teq[case], 1000, density=True, histtype='step', cumulative=True, label=case)
ax.set_xlim(0, 120); ax.set_ylim(0, 1);
ax.set_xlabel('Equivlance of time exposure [$min$]'); ax.set_ylabel('CDF');
ax.legend(loc=4, fontsize='small').set_visible(True)