# HydDown hydrogen/other gas depressurisation
# Copyright (c) 2021-2025 Anders Andreasen
# Published under an MIT license
"""
Material property database for pressure vessel calculations.
This module provides temperature-dependent material properties for common
pressure vessel materials including:
- Stainless steels (SS316, Duplex, Super Duplex)
- Carbon steels (low temperature grade)
- Vessel wall materials (steel, aluminum, composites)
Properties available:
- Heat capacity (Cp) as function of temperature [J/(kg·K)]
- Ultimate tensile strength (UTS) as function of temperature [MPa]
- Allowable tensile stress (ATS) as function of temperature [MPa]
- von Mises equivalent stress calculations
Data sources:
- Scandpower Risk Management AS guidelines for fire scenarios
- EN standards for structural steel properties
- Literature values for composite materials
All temperature data are stored in Kelvin [K].
Property values are interpolated using numpy.interp() for intermediate temperatures.
"""
import math
import numpy as np
# ============================================================================
# HEAT CAPACITY DATA
# ============================================================================
# Temperature array for heat capacity data (converted from °C to K)
# Propeties from Scandpower guideline
T_Cp = (
np.array([20, 100, 200, 300, 400, 500, 600, 700, 750, 800, 900, 1000, 1100])
+ 273.15
)
# Stainless Steel 316 heat capacity [J/(kg·K)] at temperatures in T_Cp
SS316_Cp = np.array((472, 487, 503, 512, 520, 530, 541, 551, 555, 559, 565, 571, 577))
# Duplex stainless steel heat capacity [J/(kg·K)] at temperatures in T_Cp
# Missing points from Scandpower guideline were added manually based on interpolation
Duplex_Cp = np.array([480, 500, 530, 560, 600, 635, 670, 710, 730, 750, 790, 840, 840])
# Super Duplex (SMo254) stainless steel heat capacity [J/(kg·K)] at temperatures in T_Cp
SMo_Cp = np.array([500, 520, 540, 555, 570, 580, 590, 600, 610, 610, 610, 610, 610])
# Carbon Steel Low Temperature grade heat capacity [J/(kg·K)] at temperatures in T_Cp
# Note: Discontinuity at 750°C due to phase transformation (austenite formation)
CS_LT_Cp = np.array([450, 480, 510, 550, 600, 660, 750, 900, 1450, 820, 540, 540, 540])
# ============================================================================
# ULTIMATE TENSILE STRENGTH (UTS) DATA
# ============================================================================
# Temperature array for UTS and ATS data (converted from °C to K)
# Source: Scandpower Risk Management AS guideline
T = (
np.array(
[
20,
50,
100,
150,
200,
250,
300,
350,
400,
450,
500,
550,
600,
650,
700,
750,
800,
900,
1000,
1100,
]
)
+ 273.17
)
# Duplex stainless steel ultimate tensile strength [Pa] at temperatures in T
# Converted from MPa to Pa by multiplying by 1e6
Duplex_UTS = (
np.array(
[
730,
701,
668,
650,
640,
630,
621,
606,
591,
540,
482,
423,
358,
299,
234,
164,
124,
88,
69,
58,
]
)
* 1e6
)
# Stainless steel (generic) ultimate tensile strength [Pa] at temperatures in T
SS_UTS = (
np.array(
[
575,
549,
523,
503,
489,
477,
472,
466,
463,
460,
449,
431,
397,
357,
299,
242,
184,
98,
70,
60,
]
)
* 1e6
)
# Super Duplex (SMo254) stainless steel ultimate tensile strength [Pa] at temperatures in T
SMo_UTS = (
np.array(
[
730,
710,
680,
660,
645,
633,
625,
618,
610,
595,
580,
550,
510,
445,
380,
305,
230,
130,
90,
65,
]
)
* 1e6
)
# Carbon Steel 235 Low Temperature grade ultimate tensile strength [Pa] at temperatures in T
# Note: Last two values are manual hand-interpolations where data was unavailable
CS_235LT_UTS = (
np.array(
[
420,
414,
407,
403,
397,
391,
382,
378,
370,
353,
308,
252,
189,
139,
92,
59,
46,
38,
30, # Manual hand-interpolation
22, # Manual hand-interpolation
]
)
* 1e6
)
# Carbon Steel 360 Low Temperature grade ultimate tensile strength [Pa] at temperatures in T
CS_360LT_UTS = (
np.array(
[
545,
537,
529,
523,
515,
507,
496,
491,
480,
458,
400,
327,
245,
180,
120,
76,
60,
49,
38, # Manual hand-interpolation
27, # Manual hand-interpolation
]
)
* 1e6
)
[docs]
def von_mises(p, d, wt, sigma_a=30e6):
"""
von Mises stress calculated according to:
Hekkelstrand, B.; Skulstad, P. Guidelines for the Protection of Pressurised
Systems Exposed to Fire; Scandpower Risk Management AS: Kjeller, Norway, 2004.
As also applied in:
Andreasen, A.; Borroni, F.; Zan Nieto, M.; Stegelmann, C.; P. Nielsen, R.
On the Adequacy of API 521 Relief-Valve Sizing Method for Gas-Filled Pressure Vessels
Exposed to Fire. Safety 2018, 4, 11. https://doi.org/10.3390/safety4010011
Parameters
----------
p : float
Pressure (Pa)
d : float
Inner diameter (m)
D : float
Outer diameter (m)
wt: float
Wall thickness (m)
sigma_a: float
Default
Returns
----------
sigma_e : float
von Mises stress (Pa)
"""
D = d + 2 * wt
sigma_e = math.sqrt(3 * ((p * D**2) / (D**2 - d**2)) ** 2 + sigma_a)
return sigma_e
[docs]
def ATS(temperature, material, k_s=0.85, k_y=1):
"""
Calculation of Allowable Tensile Strength according to:
Hekkelstrand, B.; Skulstad, P. Guidelines for the Protection of Pressurised
Systems Exposed to Fire; Scandpower Risk Management AS: Kjeller, Norway, 2004.
Parameters
----------
temperature : float
Temperature (K)
material : string
Material type: 235LT, 360LT (ASTM A-333/A-671), 2205 (SA-790/ASTM A-790),
316 (ASTM A-320, ASME A-358), 6Mo (ASTM B-677)
k_s : float
General safety factor. For typical materials 0.85 is used. If "guaranteed" minimum
values a factor 1.0 can be used.
k_y : float
Additional factor used for materials with missing or uncertain material data.
Normally 1.0.
Returns
----------
ATS : float
Allowable Tensile Strength (Pa)
"""
return UTS(temperature, material=material) * k_s * k_y
[docs]
def UTS(temperature, material):
"""
Tabulation look-up / interpolation to retrieve the Ultimate Tensile Strength
as a function of temperature for various typical materials according to:
Hekkelstrand, B.; Skulstad, P. Guidelines for the Protection of Pressurised
Systems Exposed to Fire; Scandpower Risk Management AS: Kjeller, Norway, 2004.
Parameters
----------
temperature : float
Temperature (K)
material : string
Material type: 235LT, 360LT (ASTM A-333/A-671), Duplex (2205, SA-790/ASTM A-790),
316 (ASTM A-320, ASME A-358), 6Mo (ASTM B-677)
Return
----------
UTS : float
Ultimate Tensile Strength (Pa)
"""
if material == "CS_235LT":
return np.interp(temperature, T, CS_235LT_UTS)
elif material == "CS_360LT":
return np.interp(temperature, T, CS_360LT_UTS)
elif material == "SS316":
return np.interp(temperature, T, SS_UTS)
elif material == "Duplex":
return np.interp(temperature, T, Duplex_UTS)
elif material == "6Mo":
return np.interp(temperature, T, SMo_UTS)
[docs]
def steel_Cp(temperature, material):
"""
Tabulation look-up / interpolation to retrieve the heat capacity
as a function of temperature for various typical materials according to:
Hekkelstrand, B.; Skulstad, P. Guidelines for the Protection of Pressurised
Systems Exposed to Fire; Scandpower Risk Management AS: Kjeller, Norway, 2004.
Parameters
----------
temperature : float
Temperature (K)
material : string
Material type: 235LT, 360LT (ASTM A-333/A-671), Duplex (2205, SA-790/ASTM A-790),
316 (ASTM A-320, ASME A-358), 6Mo (ASTM B-677)
Return
----------
Cp : float
Ultimate Tensile Strength (Pa)
"""
if material == "CS_235LT":
return np.interp(temperature, T_Cp, CS_LT_Cp)
elif material == "CS_360LT":
return np.interp(temperature, T_Cp, CS_LT_Cp)
elif material == "SS316":
return np.interp(temperature, T_Cp, SS316_Cp)
elif material == "Duplex":
return np.interp(temperature, T_Cp, Duplex_Cp)
elif material == "6Mo":
return np.interp(temperature, T_Cp, SMo_Cp)
if __name__ == "__main__":
from matplotlib import pyplot as plt
plt.figure(1)
plt.plot(T_Cp, Duplex_Cp, "--", label="22Cr Duplex")
plt.plot(T_Cp, SS316_Cp, "-.", label="SS316")
plt.plot(T_Cp, SMo_Cp, "-", label="6Mo")
plt.plot(T_Cp, CS_LT_Cp, "k--", label="CS")
plt.xlabel("Temperature (K)")
plt.ylabel("Steel heat capacity (J/kg K)")
plt.savefig("heat_capacity.png", dpi=600)
plt.legend(loc="best")
plt.figure(2)
plt.plot(T, Duplex_UTS, "--", label="22Cr Duplex")
plt.plot(T, SS_UTS, "-.", label="SS316")
plt.plot(T, SMo_UTS, "-", label="6Mo")
plt.plot(T, CS_235LT_UTS, "k--", label="235LT")
plt.plot(T, CS_360LT_UTS, "k-.", label="360LT")
plt.xlabel("Temperature (K)")
plt.ylabel("Ultimate Tensile Strength (Pa)")
plt.legend(loc="best")
plt.savefig("UTS.png", dpi=600)
plt.show()