While designing fire safety systems, a fire engineer needs to determine the expected fire size based on the project details. In Australia, Alpert’s correlation and Heskestad equations are typically used to determine the fire size at which a sprinkler head activates.
In this blog, I have written a Python script to calculate the time and fire size at sprinkler activation.
Heskestad equation
This section provides the equation developed to determine the sprinkler response time. Refer to ‘Quantification of thermal responsiveness of automatic sprinklers including conduction effects’ by Gunnar Heskestad and Robert G.Bill, JR, published in Fire Safety Journal, 14 (1988) 113–125
Equation 15:
Where,
The above equation can be re-written as,
Alpert Equations
This section provides equations related to gas velocity and temperature at the ceiling level with the plume. These equations are published by R.L. Alpert in ‘ Calculation of response time of ceiling-mounted fire detectors ‘.
Where,
Step 1. Import relevant Python packages
import pandas as pd
import plotly.express as px
Step 2. Enter user inputs
while True:
try:
amb_temp = float(input('Enter ambient room temperature (°C): '))
rad_distance = float(input('Enter the horizontal distance between the fire and sprinkler head (m): '))
height_above_fire = float(input('Enter the vertical distance between the fire and sprinkler head (m): '))
RTI = float(input('Enter RTI value of the sprinkler head: '))
c = float(input('Enter conduction value of the sprinkler head: '))
activation = float(input('Enter sprinkler activation temperature (°C): '))
break
except ValueError as e:
print('Error: Enter a valid number')
Step 3. Select fire growth rate
t_sq_list = ["slow", "medium", "fast", "ultra-fast"]
t_sq = Nonewhile t_sq not in t_sq_list:
t_sq = input('Enter fire t² growth rate. Select from the list [slow, medium, fast, ultra-fast]: ').lower().strip()if t_sq == 'slow':
growth = 0.00293
elif t_sq == 'medium':
growth = 0.01172
elif t_sq == 'fast':
growth = 0.0469
else:
growth = 0.1876
print('Fire growth rate coefficient is: ' + str(growth))
Step 4. Create a DataFrame
Step 4.1. Create an empty DataFrame and assign column names
index = pd.RangeIndex(0, 1308, 1) # a slow t² fire will take 1307 seconds to reach 5 MW
columns = ['Time', 'HRR', 'Gas Temp 1', 'Gas Temp 2', 'Gas Vel 1', 'Gas Vel 2', 'Gas Temp', 'Temp Sprinkler']df = pd.DataFrame(index=index, columns=columns)
df = df.fillna(0) # with 0s rather than NaNs
df.head()
Step 4.2. Populate HRR column
df['Time'] = df.index
df['HRR'] = df['Time']*df['Time']*growth
df.head()
Step 4.3. Determine gas temperature
if rad_distance/height_above_fire > 0.18:
df['Gas Temp 1'] = (5.38*(df['HRR']/rad_distance)**(2/3))/(height_above_fire)
df['Gas Temp'] = df['Gas Temp 1'] + amb_temp
a = 'one'
else:
df['Gas Temp 2'] = (16.9*(df['HRR'])**(1/3))/height_above_fire**(5/3)
df['Gas Temp'] = df['Gas Temp 2'] + amb_temp
a = 'two'df.head()
Step 4.4. Determine gas velocity
if rad_distance/height_above_fire <= 0.15:
df['Gas Vel 1'] = (0.2*df['HRR']**(1/3)*height_above_fire**(1/2))/(rad_distance**(5/6))
b = 'one'
else:
df['Gas Vel 2'] = 0.95*((df['HRR']/height_above_fire)**(1/3))
b= 'two'df.head()
Step 5. Generate the DataFrame
x = 2
# initialise row 0
df.loc[0, 'Temp Sprinkler'] = amb_temp
if (a == 'one') & (b == 'one'):
# initialise row 1
df.loc[1, 'Temp Sprinkler'] = amb_temp + ((df.loc[1,'Gas Vel 1']**0.5)/RTI)*((df.loc[1,'Gas Temp']-amb_temp)-((1+(c/df.loc[1,'Gas Vel 1']**0.5)))*(df.loc[0,'Temp Sprinkler']-amb_temp))
# initialise remaining rows
while x < 1308:
df.loc[x,'Temp Sprinkler'] = df.loc[x-1, 'Temp Sprinkler'] + ((df.loc[x-1, 'Gas Vel 1']**0.5)/RTI)*((df.loc[x-1, 'Gas Temp']-amb_temp)-((1+(c/df.loc[x-1, 'Gas Vel 1']**0.5)))*(df.loc[x-1, 'Temp Sprinkler']-amb_temp))
x = x+1
elif (a == 'one') & (b == 'two'):
df.loc[1, 'Temp Sprinkler'] = amb_temp + ((df.loc[1,'Gas Vel 2']**0.5)/RTI)*((df.loc[1,'Gas Temp']-amb_temp)-((1+(c/df.loc[1,'Gas Vel 2']**0.5)))*(df.loc[0,'Temp Sprinkler']-amb_temp))
while x < 1308:
df.loc[x,'Temp Sprinkler'] = df.loc[x-1, 'Temp Sprinkler'] + ((df.loc[x-1, 'Gas Vel 2']**0.5)/RTI)*((df.loc[x-1, 'Gas Temp']-amb_temp)-((1+(c/df.loc[x-1, 'Gas Vel 2']**0.5)))*(df.loc[x-1, 'Temp Sprinkler']-amb_temp))
x = x+1
elif (a == 'two') & (b == 'one'):
df.loc[1, 'Temp Sprinkler'] = amb_temp + ((df.loc[1,'Gas Vel 1']**0.5)/RTI)*((df.loc[1,'Gas Temp']-amb_temp)-((1+(c/df.loc[1,'Gas Vel 1']**0.5)))*(df.loc[0,'Temp Sprinkler']-amb_temp))
while x < 1308:
df.loc[x,'Temp Sprinkler'] = df.loc[x-1, 'Temp Sprinkler'] + ((df.loc[x-1, 'Gas Vel 1']**0.5)/RTI)*((df.loc[x-1, 'Gas Temp']-amb_temp)-((1+(c/df.loc[x-1, 'Gas Vel 1']**0.5)))*(df.loc[x-1, 'Temp Sprinkler']-amb_temp))
x = x+1
else:
df.loc[1, 'Temp Sprinkler'] = amb_temp + ((df.loc[1,'Gas Vel 2']**0.5)/RTI)*((df.loc[1,'Gas Temp']-amb_temp)-((1+(c/df.loc[1,'Gas Vel 2']**0.5)))*(df.loc[0,'Temp Sprinkler']-amb_temp))
while x < 1308:
df.loc[x,'Temp Sprinkler'] = df.loc[x-1, 'Temp Sprinkler'] + ((df.loc[x-1, 'Gas Vel 2']**0.5)/RTI)*((df.loc[x-1, 'Gas Temp']-amb_temp)-((1+(c/df.loc[x-1, 'Gas Vel 2']**0.5)))*(df.loc[x-1, 'Temp Sprinkler']-amb_temp))
x = x+1
df.head()
Step 6. Plot the graph
Step 6.1. Determine the sprinkler activation temperature
try:
act_time = df.loc[df['Temp Sprinkler']>activation, 'Time'].iloc[0]
except:
print('The sprinkler does not activate')
Step 6.2. Determine the HRR at sprinkler activation
try:
act_hrr = round(df.loc[df['Temp Sprinkler'] > activation, 'HRR'].iloc[0],1)
except:
print('The sprinkler does not activate')
Step 6.3. Create annotation for horizontal and vertical lines
act_time_text = 'Sprinkler activates at ' + str(act_time) + ' s.' + '\n'+ ' Fire size: ' + str(act_hrr) + ' kW'
act_temp_text = 'Activation temperature: ' + str(activation) + ' °C'
Step 6.4. Generate the graph
fig = px.line(df, x="Time", y="Temp Sprinkler", title="Alpert's Correlation: Sprinkler Activation Time", template = 'none')
fig.update_layout(
autosize=False,
width=600,
height=500,
yaxis=dict(
title_text="Temperature (°C)",
titlefont=dict(size=12),
),
xaxis=dict(
title_text="Time (s)",
titlefont=dict(size=12),
)
)
fig.update_layout(
title={
'y':0.9,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'})
fig.update_layout(
xaxis = dict(
tickmode = 'linear',
tick0 = 0,
dtick = 250
)
)
fig.add_hline(y=activation, line_width=1, line_dash="dash", line_color="green", annotation_text = act_temp_text)
fig.add_vline(x=act_time, line_width=1, line_dash="dash", line_color="green", annotation_text = act_time_text)
fig.update_annotations(font_size=10, font_color = 'darkblue')
fig.show()
Step 7. Testing
Step 8. Resources
You can read my blog here: https://jabirjamal.com/predicting-sprinkler-activation-time-using-alperts-correlations/
Also, download the scripts from my GitHub: https://github.com/jabirjamal/jabirjamal.com/tree/main/FE/FE_07
You can also find a video version of this article below: