Show code cell content
# import numpy as np
# import matplotlib.pyplot as plt
# import fdsreader
# # Set the matplotlib output to svg
# from IPython.display import set_matplotlib_formats
# set_matplotlib_formats('svg')
import matplotlib.pyplot as plt
# params = {'mathtext.default': 'regular' }
# params = {'text.usetex': True, 'font.family': 'sans-serif', 'figure.dpi': 400}
# params = {'text.usetex': True, 'figure.dpi': 400}
# plt.rcParams.update(params)
import matplotlib as mpl
mpl.rcParams['svg.hashsalt'] = 'seed'
svg_metadata={'Date':None}
# plt.rcParams['text.latex.preamble'] = [
# r'\usepackage{siunitx}', # i need upright \micro symbols, but you need...
# r'\sisetup{detect-all}', # ...this to force siunitx to actually use your fonts
# r'\usepackage{helvet}', # set the normal font here
# r'\usepackage{sansmath}', # load up the sansmath so that math -> helvet
# r'\sansmath' # <- tricky! -- gotta actually tell tex to use!
# ]
import numpy as np
import seaborn as sns
sns.set()
#sns.set(style="whitegrid")
sns.set_style('ticks')
sns.set_context("notebook", font_scale=1.0, rc={"lines.linewidth": 1.5})
import os
# check for set environment variable JB_NOSHOW
show = True
if 'JB_NOSHOW' in os.environ:
show = False
import fdsreader
3.2. Example – Pool Fire#
Introduction#
Pool fires are interesting for studying fire development, because they are relatively easy to handle. One needs a fireproof pan, for example made out of steel sheets, and fill in a combustible liquid. Shortly after ignition, it reaches a quasi steady-state, due to the evaporation of the liquid. One of the shortcomings of pool fires is their limited fuel supply. This is one of the reasons why gas burners are often used in fire experiments. That, and the good reproducibility associated with gas burners as ignition source. Also in FDS, most pool fire simulations are modelled as gas burners (see Section “11.4 Simple Pyrolysis Models” in the FDS User’s Guide).
This example illustrates the setup and analysis of a minimalist FDS simulation. Starting from a simple pool fire with a fixed heat release rate, the model is extended by various parameters. The results are then validated by comparison with simple analytical methods.
Simulation of a Purely Buoyant Diffusion Flame#
In this section, we discuss the simulation of buoyant diffusion flames. Focus is on the campaign of gas burner experiments conducted by McCaffrey in 1979 [McC79]. The experimental setup is described in the report: Purely Buoyant Diffusion Flames: Some Experimental Results. Purely bouyant diffusion flames can be defined as those which take place over combustible gases leaving the surface of a solid or liquid fuel with negligible velocity. In such cases, the fire is said to be dominated by buoyancy. This is a common characteristic of fires that develop freely over a pool of liquid fuel, or over a solid polymeric material.
The main purpose of the experiments described in the report is to measure the temperature and the velocity magnitude in the near field of the flame, with probes and thermocouples. Flames of five different heat release rates of \(\small\sf 14.4~kW\), \(\small\sf 21.7~kW\), \(\small\sf 33.3~kW\), \(\small\sf 44.9~kW\), \(\small\sf 57.5~kW\) are considered, and the measurements are taken at the central line of the flame. A burner of natural gas injects fuel at a controlled rate, so as to obtain the desired heat release. For a complete description of the experiment, please visit the reference in the previous paragraph.
Please consult the Basic Examples and the FDS User Guide when you get stuck.
Task I – Building the setup#
The simulation setup is built, based on the dimensions presented in the report referenced above. A methane burner with a heat release rate of \(\small\sf 33.0~kW\) can be considered as a start. The burner dimensions are \(\small\sf 0.30 \times 0.30~m\) and its surface is positioned at \(\small\sf 0.72~m\) above the floor. The lateral and top boundaries of the simulation domain are open. The extension of the domain is
with a grid resolution of \(\small\sf 0.06~m\).
Necessary steps:
Create a folder to collect the simulation results
Define a
MESH
Apply mesh boundaries
Create a base for the burner
Set a heat release
Define an appropriate combustion reaction
Check if the heat release is correct
Tip
When adding new diagnostics or other elements, it is useful to reduce the simulation time (T_END) to allow for a fast turn-over-time. This way debugging or adjusting your setup will be more efficient. For pure geometrical checks, the simulation time can also be set to zero.
In total, five different simulations need to be run, one for each heat release rate indicated above.
Task II – Confirm that the Simulation is Set Up Correctly#
During the simulation, the recorded data can be collected from the output files created. This information can already investigated while the simulation is running. The CHID_hrr.csv
contains information about the heat and mass releases.
Create a plot, to assess that the heat release rate (HRR) is set up correctly. The plot should contain a horizontal line indicating the target that is to be reached and the HRR data from the simulation.
Task III – Assess the Effect of Closed Off Boundaries#
Change the MESH
boundaries to be closed. Plot the HRR, what do you observe?
Continue the next task with open boundaries again.
Task IV – Record Data on Slices Through the Domain#
FDS can record many quantities on planes slicing through the domain (SLCF
). Set up the data recording in an x-z plane, located at y = 0m.
Record the following quantities in your simulation:
Gas temperature
Gas temperature, cell centered
Gas velocity
Gas velocity with vectors
Heat release per unit volume
Tip
Check the FDS User Guide for the SLCF quantities.
Task V – Assess the Temperatures on the Plume Axis#
A set of measuring devices (DEVC
) of temperature and velocity are positioned along the central line of the flame.
Start positioning devices at z = - 0.1 (x = 0, y = 0). Position them with a vertical distance of 2 cm apart.
Tip
Check the FDS User Guide for the quantities TEMPERATURE and THERMOCOUPLE. Check also for how devices can be positioned along a line.
Plot the recorded temperature data from the devices.
What can you observe?
When does the simulation setup reach a steady-state?
How do you determine the stedy-state?
The data recorded from the devices is stored in the CHID_devc.csv
output files.
Task VI – Compare Plume Temperatures of the Simulation and Analytical Methods#
In this task, plume temperatures are to be computed with analytical methods. This allows to validate the results of a numerical simulation. Analytical models from McCaffrey and Heskestad are used in this comparison, together with your simulation results.
For more detailed information on the theory and application of the plume formulas, please refer to the literature, e.g. Enclosure Fire Dynamics by B. Karlsson and J. Quintiere [KQ99].
McCaffrey
\(\small\sf \Delta T \) indicates the temperature rise in the plume centerline axis above ambient temperature:
where \(\small\sf \dot{Q}\) is the total heat release rate, \(\small\sf T_\infty = 293~K\) is the ambient temperature, \(\small\sf g = 9.81~ms^{-1}\) is the gravitational constant, z is the height above the fuel source in m. The constants \(\small\sf \eta\) and \(\small\sf \kappa\) vary depending on the plume regions and can be obtained from the following table.
Region |
\( \small\sf \frac{z}{\dot{Q}^{2/5}}\) |
\(\small\sf \eta\) |
\(\small\sf \kappa\) |
---|---|---|---|
Continuous |
< 0.08 |
1/2 |
\(\small\sf 6.8~[m^{1/2}/s]\) |
Intermittent |
0.08-0.2 |
0 |
\(\small\sf 1.9~[m/(kW^{1/5}s)]\) |
Plume |
> 0.2 |
-1/3 |
\(\small\sf 1.1~[m^{4/4}/(kW^{1/3}s)]\) |
Heskestad
\(\small\sf \Delta T \) indicates the temperature rise in the plume centerline axis above ambient temperature:
where \(\sf \dot{Q}_c\) is the convective heat release rate, \(\small\sf T_\infty = 293~K\) is the ambient temperature, \(\small\sf g = 9.81~ms^{-1}\) is the gravitational constant, \(\small\sf \rho_\infty = 1.2 kg/m^3\) is the density of air at ambient temperature, \(\small\sf c_p = 1.0~kJ/(kg K)\) is the specific heat capacity and z is the height above the fuel source in m.
The virtual origin \(\small\sf z_0\) depends on the (equivalent) diameter D of the fire source and the total heat release rate and is given by:
The calculation of the plume temperature according to Heskestad is defined exclusively for the area above the flame. The flame height is calculated by the following expression:
Task:
Calculate the temperatures of the plume within the respective application limits using the analytical approaches of the Heskestad and McCaffrey Plumes with an HRR of \(\small\sf 33.0~kW\) at heights of about \(\small\sf z = 0.15~m, 0.5~m, 0.9~m, 1.2~m, 1.5~m, 2.2~m\). Assume that the radiative fraction of the plume is \(\small\sf 20.0~\%\) and \( \small\sf A_{fire}=1~m^2\) . Compare the results and discuss the reasons for the deviations.
Compare the results from the analytical calculations to the results of an FDS simulation using temperature devices. Smooth the output by a moving average to reduce noise. Refer to section 20.1 of the FDS User’s Guide for further information on how to place Devices in the computational domain.
Add the following lines to your FDS file to open the lateral and top boundaries of the sealed domain which provides a better depiction of the boundary conditions of the empirically determined plume formulas:
&VENT MB = 'XMIN' SURF_ID = 'OPEN' / &VENT MB = 'XMAX' SURF_ID = 'OPEN' / &VENT MB = 'YMIN' SURF_ID = 'OPEN' / &VENT MB = 'YMAX' SURF_ID = 'OPEN' / &VENT MB = 'ZMAX' SURF_ID = 'OPEN' /
Tip
To reduce noise, temperatures calculated with FDS can be smoothed using a simple moving average (SMA). The SMA of a time series \(\small\sf x(t)\) is the sequence of arithmetic averages of \(\small\sf n\) consecutive data points. \(\small\sf m_{SMA}(t) = \frac{1}{n}\sum_{i=0}^{n-1}x(t-i)\)
Example of a plot comparing plume temperatures at different heights.
Show code cell content
import matplotlib.patches as mpatches
from matplotlib.lines import Line2D
def sma (values, window):
weights = np.repeat(1.0, window)/window
sma = np.convolve(values, weights, 'valid')
return sma
d_t_hesk_dict = {3.0:379, 4.0:229, 5.0:156, 6:114}
d_t_mcf_dict = {1.0:852, 2.0:527, 3.0:352, 4.0:221, 5.0:152, 6.0:112}
color_list = ['b', 'c', 'g', 'r', 'y', 'm']
data_root = root + 'data/pool_fire/1mw_open'
sim = fdsreader.Simulation(data_root)
height_list = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
window = 100
for z, c in zip(height_list, color_list):
time = sim.devices['Time'].data
temperature = sim.devices[f'T_{z}'].data
# plt.scatter(time, temperature, s=1, alpha=0.1, color=c)
plt.plot(sma(time, window), sma(temperature, window), label=f"z = {z}", color=c)
if z in d_t_hesk_dict:
plt.axhline(y=d_t_hesk_dict[z]+20, color=c, linestyle='dashed')
if z in d_t_mcf_dict:
plt.axhline(y=d_t_mcf_dict[z]+20, color=c, linestyle='dotted')
plt.annotate(f"$\sf z={z}~m$", xy=(30, d_t_mcf_dict[z]-50), color=c, annotation_clip=False)
plt.grid(True, linestyle='--', alpha=0.5)
plt.legend(loc='best')
plt.xlabel("Time / s")
plt.ylabel("Temperature / $\sf ^\circ C$")
line_fds = Line2D([0], [0], color='black', linestyle='-')
line_hesk = Line2D([0], [0], color='black', linestyle='dashed')
line_mcf = Line2D([0], [0], color='black', linestyle='dotted')
plt.legend([line_fds, line_hesk, line_mcf], ["FDS", "Heskestad", "MCCaffrey"])
plt.savefig('figs/pool_fire_1mw_open_temperatures_devc.svg', bbox_inches='tight')
plt.close()
2. Solution
Time-dependent Heat Release Rate#
This task deals with the different possibilities to define the heat release rate (HRR) of a design fire and to model it in FDS. The total heat release \(\small\sf \dot{Q}\) of a burning area \(\small\sf A_{fire}\) depends on the heat release rate per unit area \(\small\sf \dot{q}''\):
In FDS a burning area is defined by a VENT
with a certain surface property that can be assigned by a SURF_ID
. A fixed heat release rate per unit area can be set to a SURF
by the attribute HRRPUA
. Please refer to section 10.2.1 “Basics” of the FDS User’s Guide for further information.
Tip
Create an automation in Python or Excel that outputs the strings of the RAMP lines for the FDS input file.
Task:
Model the HRR progression for a radially spreading fire with a maximum power of 1 MW in FDS assuming a fixed burning area (task 1.1) and a radial propagation from the center of the burning area (task 1.2).
The HRR according to the ‘t-square’ model can be described by:
\[\small\sf \dot Q = \alpha \cdot t^2\]where t is the burning time after ignition and \(\small\sf \alpha\) is the fire growth factor.Assume a fast fire propagation by \(\small\sf \alpha = 0.04689~kW/s^2\) and a constant heat release rate per unit area of \(\small\sf \dot{q}'' = 0.25~MW/m^2\). The maximum burning area is \(\small\sf A_{fire} = 1~m^2\). First calculate the time until the fire has spread to the entire area. This corresponds to the time at which the maximum HRR is reached. For simplicity, assume a perfect radial fire spread and a round fire area. Then model the temporal evolution of the HRR in FDS via a
RAMP
function (See section 20.6 “Controlling a Ramp” of the FDS User’s Guide ).Model the fire propagation directly in FDS by defining the spread rate. The
SPREAD
attribute denotes a constant radial propagation speed from a specified point.For instructions on how to model a radial fire spread in FDS, please refer to the FDS User’s Guide Section 11.4.2 “Special Topic: A Radially-Spreading Fire”. The radial propagation speed v can be obtained from the fire area \(\small\sf A_{Fire}\) and the corresponding burning period t.
\[\small\sf v = \frac{\sqrt{A_{fire}/\pi}}{t}\]Compare the HRR curves calculated by FDS with each other and discuss the limitations and inaccuracies associated with each approach.
Given is the fictional mass loss of a heptane fire. Calculate the heat release of the fire over the entire burning period with an assumed effective heat of combustion \(\small\sf \Delta h_{c,eff} = 44,590~kJ / kg\). Model the HRR in FDS by using the RAMP function. Check if the simulated curve matches the prescribed HRR. The effective heat of combustion indicates the heat release per unit of weight of a material burned in combustion. For simplicity, assume that the averaged mass loss between two time steps applies to the end of each time interval. The mass loss caused by the burn-up can be described by the following time-dependent correlation:
time_index = [0, 25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275 ] # [s] total_mass = [4000, 4000, 3600, 3040, 2880, 2400, 1800, 1120, 600, 160, 0, 0] # [g]
1. Solution
The burning period for the fire to reach the maximum heat release is:
By setting the time and fraction parameters T
and F
, the RAMP
function is obtained as follows:
&SURF ID = 'BURNER', HRRPUA = 250, RAMP_Q = 'fireramp', COLOR = 'RASPBERRY' /
&VENT XB = -0.5,0.5, -0.5,0.5, 0.0, 0.0, SURF_ID='BURNER' /
&RAMP ID='fireramp', T=0, F=0.00
.
.
.
&RAMP ID='fireramp', T=73, F=1.00
The spread rate corresponds to the propagation speed in m/s:
Starting from the center of the vent, the radial propagation of the fire in FDS can be described as follows:
&SURF ID = 'BURNER', HRRPUA = 250, COLOR = 'RASPBERRY' /
&VENT XB = -0.5,0.5, -0.5,0.5, 0.0, 0.0, SURF_ID='BURNER', SPREAD_RATE = 0.00773 /
Show code cell content
alpha = 0.04689
Qdot_max = 250
t = (Qdot_max / alpha)**(1/2)
print(t)
print(f"&SURF ID = 'BURNER', HRRPUA = {Qdot_max}, RAMP_Q = 'fireramp', COLOR = 'RASPBERRY' /")
for t in range(0, 74):
Qdot = alpha * t **2
print(f"&RAMP ID='fireramp', T={t}, F={Qdot / Qdot_max:.2f}")
73.01799238972059
&SURF ID = 'BURNER', HRRPUA = 250, RAMP_Q = 'fireramp', COLOR = 'RASPBERRY' /
&RAMP ID='fireramp', T=0, F=0.00
&RAMP ID='fireramp', T=1, F=0.00
&RAMP ID='fireramp', T=2, F=0.00
&RAMP ID='fireramp', T=3, F=0.00
&RAMP ID='fireramp', T=4, F=0.00
&RAMP ID='fireramp', T=5, F=0.00
&RAMP ID='fireramp', T=6, F=0.01
&RAMP ID='fireramp', T=7, F=0.01
&RAMP ID='fireramp', T=8, F=0.01
&RAMP ID='fireramp', T=9, F=0.02
&RAMP ID='fireramp', T=10, F=0.02
&RAMP ID='fireramp', T=11, F=0.02
&RAMP ID='fireramp', T=12, F=0.03
&RAMP ID='fireramp', T=13, F=0.03
&RAMP ID='fireramp', T=14, F=0.04
&RAMP ID='fireramp', T=15, F=0.04
&RAMP ID='fireramp', T=16, F=0.05
&RAMP ID='fireramp', T=17, F=0.05
&RAMP ID='fireramp', T=18, F=0.06
&RAMP ID='fireramp', T=19, F=0.07
&RAMP ID='fireramp', T=20, F=0.08
&RAMP ID='fireramp', T=21, F=0.08
&RAMP ID='fireramp', T=22, F=0.09
&RAMP ID='fireramp', T=23, F=0.10
&RAMP ID='fireramp', T=24, F=0.11
&RAMP ID='fireramp', T=25, F=0.12
&RAMP ID='fireramp', T=26, F=0.13
&RAMP ID='fireramp', T=27, F=0.14
&RAMP ID='fireramp', T=28, F=0.15
&RAMP ID='fireramp', T=29, F=0.16
&RAMP ID='fireramp', T=30, F=0.17
&RAMP ID='fireramp', T=31, F=0.18
&RAMP ID='fireramp', T=32, F=0.19
&RAMP ID='fireramp', T=33, F=0.20
&RAMP ID='fireramp', T=34, F=0.22
&RAMP ID='fireramp', T=35, F=0.23
&RAMP ID='fireramp', T=36, F=0.24
&RAMP ID='fireramp', T=37, F=0.26
&RAMP ID='fireramp', T=38, F=0.27
&RAMP ID='fireramp', T=39, F=0.29
&RAMP ID='fireramp', T=40, F=0.30
&RAMP ID='fireramp', T=41, F=0.32
&RAMP ID='fireramp', T=42, F=0.33
&RAMP ID='fireramp', T=43, F=0.35
&RAMP ID='fireramp', T=44, F=0.36
&RAMP ID='fireramp', T=45, F=0.38
&RAMP ID='fireramp', T=46, F=0.40
&RAMP ID='fireramp', T=47, F=0.41
&RAMP ID='fireramp', T=48, F=0.43
&RAMP ID='fireramp', T=49, F=0.45
&RAMP ID='fireramp', T=50, F=0.47
&RAMP ID='fireramp', T=51, F=0.49
&RAMP ID='fireramp', T=52, F=0.51
&RAMP ID='fireramp', T=53, F=0.53
&RAMP ID='fireramp', T=54, F=0.55
&RAMP ID='fireramp', T=55, F=0.57
&RAMP ID='fireramp', T=56, F=0.59
&RAMP ID='fireramp', T=57, F=0.61
&RAMP ID='fireramp', T=58, F=0.63
&RAMP ID='fireramp', T=59, F=0.65
&RAMP ID='fireramp', T=60, F=0.68
&RAMP ID='fireramp', T=61, F=0.70
&RAMP ID='fireramp', T=62, F=0.72
&RAMP ID='fireramp', T=63, F=0.74
&RAMP ID='fireramp', T=64, F=0.77
&RAMP ID='fireramp', T=65, F=0.79
&RAMP ID='fireramp', T=66, F=0.82
&RAMP ID='fireramp', T=67, F=0.84
&RAMP ID='fireramp', T=68, F=0.87
&RAMP ID='fireramp', T=69, F=0.89
&RAMP ID='fireramp', T=70, F=0.92
&RAMP ID='fireramp', T=71, F=0.95
&RAMP ID='fireramp', T=72, F=0.97
&RAMP ID='fireramp', T=73, F=1.00
Show code cell content
data_root = root + 'data/pool_fire/ramp_spread/rundir'
sim = fdsreader.Simulation(data_root)
plt.plot(sim.hrr["Time"], sim.hrr["HRR"], label='FDS SPREAD')
t_min_max = [sim.hrr["Time"][0], sim.hrr["Time"][-1]]
data_root = root + 'data/pool_fire/ramp_tsquare'
sim = fdsreader.Simulation(data_root)
plt.plot(sim.hrr["Time"], sim.hrr["HRR"], label='FDS RAMP')
t_min_max = [sim.hrr["Time"][0], sim.hrr["Time"][-1]]
plt.grid(True, linestyle='--', alpha=0.5)
plt.legend(loc='best')
plt.xlabel("Time / s")
plt.ylabel("HRR / kW")
plt.savefig('figs/pool_fire_10mw_sealed_hrr_spread.svg', bbox_inches='tight')
plt.close()
2. Solution
The HRR can be obtained from the mass loss \(\small\sf \dot{m_{fuel}}\) by the following expression: $\(\small\sf \dot{Q} = \Delta h_{c,eff} \dot{m_{fuel}}\)$
The maximum
&SURF ID = 'BURNER', HRRPUA = 1212.85, RAMP_Q = 'fireramp', COLOR = 'RASPBERRY' /
&RAMP ID='fireramp', T=0, F=0.00 /
&RAMP ID='fireramp', T=25, F=0.15 /
&RAMP ID='fireramp', T=50, F=0.59 /
&RAMP ID='fireramp', T=75, F=0.68 /
&RAMP ID='fireramp', T=100, F=0.35 /
&RAMP ID='fireramp', T=125, F=0.59 /
&RAMP ID='fireramp', T=150, F=0.88 /
&RAMP ID='fireramp', T=175, F=1.00 /
&RAMP ID='fireramp', T=200, F=0.76 /
&RAMP ID='fireramp', T=225, F=0.65 /
&RAMP ID='fireramp', T=250, F=0.24 /
&RAMP ID='fireramp', T=275, F=0.00 /
Show code cell content
time_list = [0, 25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275 ]
mass_list = [4000, 3900, 3500, 3040, 2800, 2400, 1800, 1120, 600, 160, 0, 0]
mlr_list = np.diff(mass_list)/np.diff(time_list) # mass loss rate
huc = 44590 # Effective heat of combustion huc = 44590 KJ / kg
hrr_list =abs(mlr_list/1000*huc) # calculate HRR from mass loss
hrr_list = np.concatenate(([0], hrr_list)) # add 0 mass at first timestep
print(hrr_list)
print(f"&SURF ID = 'BURNER', HRRPUA = {max(hrr_list):.2f}, RAMP_Q = 'fireramp', COLOR = 'RASPBERRY' /")
for time, hrr in zip(time_list, hrr_list):
print(f"&RAMP ID='fireramp', T={time}, F={hrr/max(hrr_list):.2f} /")
[ 0. 178.36 713.44 820.456 428.064 713.44 1070.16 1212.848
927.472 784.784 285.376 0. ]
&SURF ID = 'BURNER', HRRPUA = 1212.85, RAMP_Q = 'fireramp', COLOR = 'RASPBERRY' /
&RAMP ID='fireramp', T=0, F=0.00 /
&RAMP ID='fireramp', T=25, F=0.15 /
&RAMP ID='fireramp', T=50, F=0.59 /
&RAMP ID='fireramp', T=75, F=0.68 /
&RAMP ID='fireramp', T=100, F=0.35 /
&RAMP ID='fireramp', T=125, F=0.59 /
&RAMP ID='fireramp', T=150, F=0.88 /
&RAMP ID='fireramp', T=175, F=1.00 /
&RAMP ID='fireramp', T=200, F=0.76 /
&RAMP ID='fireramp', T=225, F=0.65 /
&RAMP ID='fireramp', T=250, F=0.24 /
&RAMP ID='fireramp', T=275, F=0.00 /
Show code cell content
# Plot HRR from Simulation
data_root = root + 'data/pool_fire/ramp_heptane/rundir'
sim = fdsreader.Simulation(data_root)
plt.plot(sim.hrr["Time"], sim.hrr["HRR"], label='simulation')
plt.grid(True, linestyle='--', alpha=0.5)
plt.xlabel("Time / s")
plt.ylabel("HRR / kW")
# Plot prescribed data
plt.plot(time_list, hrr_list, label = 'prescribed')
plt.legend(loc='best')
plt.savefig('figs/pool_fire_hrr_heptane_ramp.svg', bbox_inches='tight')
# plt.close()
Grid Convergence / HPC computing / Benchmarking#
This task deals with the monitoring of simulation parameters such as computation time and the convergence of numerical solutions.
Task:
Increase / decrease the grid resolution by factors of 0.4 and 2. Monitor the computing time by evaluating the .out file.
Extend the examination by refining the grid by a factor of 4 and 8, using resources of parallel computing. For this purpose subdivide the computational domain into several meshes.
Analyze the computation time for assigning multiple cores to a single OpenMP process. Split the computational domain into different meshes and assign individual MPI processes to each of them. Try to combine MPI and OpenMP and evaluate the increase in performance.
Check grid convergence for the respective resolutions of the domain based on temperature and velocity criteria
Solution:
Show code cell content
import pandas as pd
data_root = root + 'data/pool_fire/gc_3_1/rundir'
caselist = ['gc_1_1', 'gc_1_2', 'gc_1_3', 'gc_2_1', 'gc_2_2', 'gc_2_3', 'gc_3_1', 'gc_3_2', 'gc_3_3' ]
bm_dict = {}
for case in caselist:
case_dict = {}
data_root = root + f'data/pool_fire/{case}/rundir'
sim = fdsreader.Simulation(data_root)
case_dict['devc_temp'] = sim.devices[f'T_{1.0}'].data
case_dict['sim_time'] = sim.devices['Time'].data
case_dict['total_time'] = sim.cpu['Total T_USED (s)\n'][0]
out_file = sim.out_file_path
with open(out_file, 'r') as file:
for line in file:
if 'Total Number of Grid Cells' in line:
case_dict['n_cells'] = int(line.split('Cells')[-1])
if 'Number of OpenMP Threads:' in line:
case_dict['n_open_mp'] = int(line.split('Number of OpenMP Threads:')[-1])
if 'Number of MPI Processes:' in line:
case_dict['n_mpi']= int(line.split('Number of MPI Processes:')[-1])
bm_dict[case] = case_dict
bm_df = pd.DataFrame(bm_dict).T
for n_open_mp in [1,2,4]:
df = bm_df[bm_df['n_open_mp']==n_open_mp]
plt.plot(df['n_cells'], df['total_time'], label=f"$\sf N_{{openMP}}$ = {n_open_mp}")
plt.xscale('log')
# plt.yscale('log')
plt.xlabel("$\sf N_{{cells}}$ / -")
plt.ylabel("Time / s")
plt.grid(True, which="both", linestyle='--', alpha=0.5)
plt.legend(loc='best')
plt.savefig('figs/pool_fire_benchmarking.svg', bbox_inches='tight')
Show code cell content
window = 10
for n_cells in [2000, 31250, 250000]:
time = bm_df[bm_df['n_cells']==n_cells].iloc[0]['sim_time']
temp = bm_df[bm_df['n_cells']==n_cells].iloc[0]['devc_temp']
plt.plot(sma(time, window), sma(temp, window), label=f"$\sf N_{{cells}}$ = {n_cells}")
plt.grid(True, which="both", linestyle='--', alpha=0.5)
plt.legend(loc='lower right')
plt.xlabel("Time / s")
plt.ylabel("Temperature / $\sf ^\circ C$")
plt.savefig('figs/pool_fire_grid_convergence.svg', bbox_inches='tight')
plt.close()