Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/hyddown/HydDown.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"folders": [
{
"path": "../.."
}
]
}
Binary file removed src/hyddown/__pycache__/hdclass.cpython-312.pyc
Binary file not shown.
Binary file removed src/hyddown/__pycache__/validator.cpython-312.pyc
Binary file not shown.
29 changes: 29 additions & 0 deletions src/hyddown/examples/LPG_Droste_1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
vessel:
length: 3.6
diameter: 1.25
orientation: "horizontal"
heat_capacity: 500
density: 7700
thickness: 0.0059
liquid_level: 0.625 #1.15
type: "DIN"
initial:
temperature: 283
pressure: 1350000
fluid: "propane"
calculation:
type: "energybalance"
time_step: 1
end_time: 900.
valve:
flow: "discharge"
type: "psv"
diameter: 0.015
discharge_coef: 0.975
set_pressure: 1730000
blowdown: 0.0
back_pressure: 101300.
heat_transfer:
type: "s-b"
fire: "scandpower_pool"
scaling: 0.7
34 changes: 34 additions & 0 deletions src/hyddown/examples/LPG_specified_q.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
vessel:
length: 3.5
diameter: 1.6763
orientation: "horizontal"
type: "Hemispherical"
heat_capacity: 500
density: 7700
thickness: 0.01185
liquid_level: 0.4668
initial:
temperature: 279
pressure: 550000
fluid: "propane"
calculation:
type: "energybalance"
time_step: 1
end_time: 720.
valve:
flow: "discharge"
type: "psv"
diameter: 0.0475
discharge_coef: 0.975
set_pressure: 1430000
blowdown: 0.24
back_pressure: 101300.
heat_transfer:
type: "specified_q"
h_inner: "calc"
q_outer:
time: [0.0, 120.0, 130.0, 140.0, 150.0, 160.0, 170.0, 180.0, 190.0, 200.0, 210.0, 220.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0, 380.0, 390.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 470.0, 480.0, 490.0, 500.0, 510.0, 520.0, 530.0, 540.0, 550.0, 560.0, 570.0, 580.0, 590.0, 600.0, 610.0, 620.0, 630.0, 640.0, 650.0, 660.0, 670.0, 680.0, 690.0, 700.0, 710.0, 720.0, 730]
heat_flux: [0, 0, 64020.08, 68626.41, 73069.31, 73570.21, 73847.06, 74417.00, 74927.83, 75194.43, 75618.54, 76055.93, 76463.23, 76864.81, 77259.94, 77695.54, 78169.01, 78484.32, 79016.89, 79549.52, 80082.12, 80614.72, 81197.03, 81752.35, 82349.76, 83005.97, 83712.95, 84350.98, 84989.33, 85627.91, 86266.67, 86970.51, 86777.99, 86144.24, 85510.49, 84925.77, 84329.11, 83798.73, 83212.07, 82560.15, 81998.49, 81405.55, 80937.47, 81351.16, 81910.74, 82362.27, 82668.13, 82959.11, 83198.99, 83401.45, 83075.37, 82536.11, 81948.55, 81460.60, 80966.35, 80534.18, 79998.41, 79364.66, 78730.91, 78245.89, 77264.09, 42895.00, 2057.16]
rupture:
material: "CS_360LT"
fire: "scandpower_pool_peak"
70 changes: 53 additions & 17 deletions src/hyddown/hdclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,33 @@ def read_input(self):
self.scaling = 1.0
if self.input["valve"]["flow"] == "filling":
raise ValueError("Filling and Fire heat load not implemented")
if self.heat_method == "specified_q":
self.vessel_cp = self.input["vessel"]["heat_capacity"]
self.vessel_density = self.input["vessel"]["density"]
self.vessel_orientation = self.input["vessel"]["orientation"]
self.thickness = self.input["vessel"]["thickness"]
# Handle q_outer: can be a number (fixed) or dict (time-dependent)
q_outer_input = self.input["heat_transfer"]["q_outer"]
if isinstance(q_outer_input, (int, float)):
# Fixed heat flux
self.q_outer_func = lambda t: q_outer_input
elif isinstance(q_outer_input, dict):
# Time-dependent heat flux from dict
time_data = np.array(q_outer_input["time"])
heat_flux_data = np.array(q_outer_input["heat_flux"])
self.q_outer_func = lambda t: np.interp(t, time_data, heat_flux_data)
else:
raise ValueError("q_outer must be a number or dict with time/heat_flux")
# Handle h_inner
if "h_inner" in self.input["heat_transfer"]:
self.h_in = self.input["heat_transfer"]["h_inner"]
else:
self.h_in = "calc"
if self.input["valve"]["flow"] == "filling":
if "D_throat" in self.input["heat_transfer"]:
self.D_throat = self.input["heat_transfer"]["D_throat"]
else:
self.D_throat = self.input["vessel"]["diameter"]

def initialize(self):
"""
Expand Down Expand Up @@ -802,7 +829,7 @@ def run(self, disable_pbar=True):
# HEAT TRANSFER COEFFICIENT CALCULATIONS
# ====================================================================
# Calculate convective heat transfer coefficients for specified_h or detailed methods
if self.heat_method == "specified_h" or self.heat_method == "detailed":
if self.heat_method == "specified_h" or self.heat_method == "detailed" or self.heat_method == "specified_q":
if self.h_in == "calc":
if self.vessel_orientation == "horizontal":
L = self.diameter
Expand Down Expand Up @@ -928,24 +955,33 @@ def run(self, disable_pbar=True):

# Heat transfer from environment to unwetted outer wall
# Use outer surface area directly (outer surface is exposed to environment)
self.Q_outer[i] = (
(self.surf_area_outer - wetted_area_outer)
* self.h_out
* (self.Tamb - self.T_outer_wall[i - 1])
)
self.q_outer[i] = self.h_out * (
self.Tamb - self.T_outer_wall[i - 1]
)
if self.heat_method == "specified_q":
# User-defined heat flux (time-dependent or constant)
q_ext = self.q_outer_func(self.time_array[i])
self.Q_outer[i] = q_ext * (self.surf_area_outer - wetted_area_outer)
self.q_outer[i] = q_ext
self.Q_outer_wetted[i] = q_ext * wetted_area_outer
self.q_outer_wetted[i] = q_ext
else:
# specified_h or detailed: convective heat transfer
self.Q_outer[i] = (
(self.surf_area_outer - wetted_area_outer)
* self.h_out
* (self.Tamb - self.T_outer_wall[i - 1])
)
self.q_outer[i] = self.h_out * (
self.Tamb - self.T_outer_wall[i - 1]
)

self.Q_outer_wetted[i] = (
wetted_area_outer
* self.h_out
* (self.Tamb - self.T_outer_wall_wetted[i - 1])
)
self.Q_outer_wetted[i] = (
wetted_area_outer
* self.h_out
* (self.Tamb - self.T_outer_wall_wetted[i - 1])
)

self.q_outer_wetted[i] = self.h_out * (
self.Tamb - self.T_outer_wall_wetted[i - 1]
)
self.q_outer_wetted[i] = self.h_out * (
self.Tamb - self.T_outer_wall_wetted[i - 1]
)
if np.isnan(self.Q_outer_wetted[i]):
self.Q_outer_wetted[i] = 0

Expand Down
69 changes: 68 additions & 1 deletion src/hyddown/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,13 @@ def validate_mandatory_ruleset(input):
"fire",
"s-b",
"D_throat",
"q_outer",
"scaling",
],
"schema": {
"type": {
"type": "string",
"allowed": ["specified_Q", "specified_h", "specified_U", "s-b"],
"allowed": ["specified_Q", "specified_h", "specified_U", "s-b", "specified_q"],
},
"Q_fix": {"required": False, "type": "number"},
"U_fix": {"required": False, "type": "number", "min": 0},
Expand All @@ -208,6 +209,13 @@ def validate_mandatory_ruleset(input):
],
},
"D_throat": {"required": False, "type": "number", "min": 0},
"q_outer": {
"required": False,
"anyof": [
{"type": "number"},
{"type": "dict"},
],
},
"scaling": {
"required": False,
"type": "number",
Expand Down Expand Up @@ -701,6 +709,65 @@ def heat_transfer_validation(input):
},
},
}

elif input["heat_transfer"]["type"] == "specified_q":
schema_heattransfer = {
"initial": {"required": True},
"calculation": {"required": True},
"validation": {"required": False},
"valve": {"required": True},
"rupture": {"required": False},
"vessel": {
"required": True,
"type": "dict",
"allow_unknown": False,
"schema": {
"length": {"required": True, "type": "number"},
"diameter": {"required": True, "type": "number"},
"thickness": {"required": True, "type": "number", "min": 0.0},
"heat_capacity": {"required": True, "type": "number", "min": 1},
"density": {"required": True, "type": "number", "min": 1},
"orientation": {
"required": True,
"type": "string",
"allowed": ["vertical", "horizontal"],
},
"type": {
"required": False,
"type": "string",
"allowed": ["Flat-end", "DIN", "ASME F&D", "Hemispherical"],
},
"liquid_level": {
"required": False,
"type": "number",
"min": 0,
},
},
},
"heat_transfer": {
"required": True,
"type": "dict",
"allow_unknown": False,
"allowed": ["type", "q_outer", "h_inner"],
"schema": {
"type": {"type": "string", "allowed": ["specified_q"]},
"q_outer": {
"required": True,
"anyof": [
{"type": "number"},
{
"type": "dict",
"schema": {
"time": {"required": True, "type": "list"},
"heat_flux": {"required": True, "type": "list"},
},
},
],
},
"h_inner": {"required": False, "type": ["number", "string"]},
},
},
}
v = Validator(schema_heattransfer)
retval = v.validate(input)
if v.errors:
Expand Down
Loading