对齐Amesim氦气PR物性与PNVO流量
This commit is contained in:
1 parent
18d9802f03
commit
046aa49814
13 files changed
+730
-73
No files matched your search
@@ -206,9 +206,13 @@ class AmesimPnor001(AlgebraicComponent):
|
||||
|
||||
def _upstream_temperature(self, port_name: str) -> float:
|
||||
port = self.get_port(port_name)
|
||||
if port.h_outflow > 0.0:
|
||||
return max(self.medium.temperature_from_enthalpy(port.h_outflow), 1.0)
|
||||
return self.medium.T_ref
|
||||
return max(
|
||||
self.medium.temperature_from_pressure_enthalpy(
|
||||
max(port.p, 1.0),
|
||||
port.h_outflow,
|
||||
),
|
||||
1.0,
|
||||
)
|
||||
|
||||
def mass_flow(self, p_1: float, p_2: float) -> float:
|
||||
if p_1 == p_2 or self.effective_area == 0.0:
|
||||
@@ -461,6 +465,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
||||
self.port_2.h_outflow = initial_h
|
||||
self.port_3 = self.register_declared_port("port_3")
|
||||
self.port_3.h_outflow = initial_h
|
||||
self._connected_h: dict[str, float] = {}
|
||||
|
||||
@staticmethod
|
||||
def _integer_parameter(name: str, value: float) -> int:
|
||||
@@ -507,9 +512,16 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
||||
|
||||
def _upstream_temperature(self, port_name: str) -> float:
|
||||
port = self.get_port(port_name)
|
||||
if port.h_outflow > 0.0:
|
||||
return max(self.medium.temperature_from_enthalpy(port.h_outflow), 1.0)
|
||||
return self.medium.T_ref
|
||||
# A component port's h_outflow describes fluid leaving the valve; the
|
||||
# upstream state comes from the connection on that same physical side.
|
||||
inlet_h = self._connected_h.get(port_name, port.h_outflow)
|
||||
return max(
|
||||
self.medium.temperature_from_pressure_enthalpy(
|
||||
max(port.p, 1.0),
|
||||
inlet_h,
|
||||
),
|
||||
1.0,
|
||||
)
|
||||
|
||||
def mass_flow(self, p_2: float, p_3: float) -> float:
|
||||
if p_2 == p_3 or self.effective_area == 0.0:
|
||||
@@ -526,6 +538,64 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
||||
upstream_temperature=self._upstream_temperature("port_3"),
|
||||
)
|
||||
|
||||
def _one_way_flow_characteristics(
|
||||
self,
|
||||
*,
|
||||
upstream_pressure: float,
|
||||
downstream_pressure: float,
|
||||
upstream_temperature: float,
|
||||
) -> tuple[float, float]:
|
||||
p_up = max(upstream_pressure, 1.0)
|
||||
p_down = max(min(downstream_pressure, p_up), 0.0)
|
||||
T_up = max(upstream_temperature, 1.0)
|
||||
gamma_s = self.medium.isentropic_density_pressure_factor(
|
||||
p_up,
|
||||
T_up,
|
||||
p_down,
|
||||
)
|
||||
gamma_s = min(max(gamma_s, 1.0e-9), 1.0 - 1.0e-9)
|
||||
density = max(self.medium.density(p_up, T_up), 1.0e-12)
|
||||
pressure_ratio = max(p_down / p_up, 0.0)
|
||||
critical_ratio = (2.0 * gamma_s / (gamma_s + 1.0)) ** (
|
||||
1.0 / (1.0 - gamma_s)
|
||||
)
|
||||
if pressure_ratio <= critical_ratio:
|
||||
mass_flow_parameter = (
|
||||
sqrt(2.0 / (1.0 + gamma_s) * density * T_up / p_up)
|
||||
* (2.0 * gamma_s / (gamma_s + 1.0))
|
||||
** (gamma_s / (1.0 - gamma_s))
|
||||
)
|
||||
gas_velocity = sqrt(
|
||||
2.0 / (1.0 + gamma_s) * p_up / density
|
||||
)
|
||||
else:
|
||||
expansion = (
|
||||
pressure_ratio ** (2.0 * gamma_s)
|
||||
- pressure_ratio ** (1.0 + gamma_s)
|
||||
)
|
||||
mass_flow_parameter = sqrt(
|
||||
max(
|
||||
2.0
|
||||
/ (1.0 - gamma_s)
|
||||
* density
|
||||
* T_up
|
||||
/ p_up
|
||||
* expansion,
|
||||
0.0,
|
||||
)
|
||||
)
|
||||
gas_velocity = sqrt(
|
||||
max(
|
||||
2.0
|
||||
/ (1.0 - gamma_s)
|
||||
* p_up
|
||||
/ density
|
||||
* (1.0 - pressure_ratio ** (1.0 - gamma_s)),
|
||||
0.0,
|
||||
)
|
||||
)
|
||||
return mass_flow_parameter, gas_velocity
|
||||
|
||||
def _one_way_mass_flow(
|
||||
self,
|
||||
*,
|
||||
@@ -534,44 +604,45 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
||||
upstream_temperature: float,
|
||||
) -> float:
|
||||
p_up = max(upstream_pressure, 1.0)
|
||||
p_down = max(min(downstream_pressure, p_up), 0.0)
|
||||
T_up = max(upstream_temperature, 1.0)
|
||||
gamma = max(self.medium.gamma, 1.000001)
|
||||
pressure_ratio = max(p_down / p_up, 0.0)
|
||||
critical_ratio = (2.0 / (gamma + 1.0)) ** (gamma / (gamma - 1.0))
|
||||
if pressure_ratio <= critical_ratio:
|
||||
flow_factor = sqrt(gamma / (self.medium.R_gas * T_up)) * (
|
||||
2.0 / (gamma + 1.0)
|
||||
) ** ((gamma + 1.0) / (2.0 * (gamma - 1.0)))
|
||||
else:
|
||||
expansion = pressure_ratio ** (2.0 / gamma) - pressure_ratio ** (
|
||||
(gamma + 1.0) / gamma
|
||||
)
|
||||
flow_factor = sqrt(
|
||||
max(
|
||||
2.0
|
||||
* gamma
|
||||
* expansion
|
||||
/ (self.medium.R_gas * T_up * (gamma - 1.0)),
|
||||
0.0,
|
||||
)
|
||||
)
|
||||
return self.effective_cq * self.effective_area * p_up * flow_factor
|
||||
mass_flow_parameter, _gas_velocity = self._one_way_flow_characteristics(
|
||||
upstream_pressure=p_up,
|
||||
downstream_pressure=downstream_pressure,
|
||||
upstream_temperature=T_up,
|
||||
)
|
||||
return (
|
||||
self.effective_cq
|
||||
* self.effective_area
|
||||
* p_up
|
||||
* mass_flow_parameter
|
||||
/ sqrt(T_up)
|
||||
)
|
||||
|
||||
def component_result_values(self) -> Mapping[str, float]:
|
||||
p_2 = max(self.port_2.p, 1.0)
|
||||
p_3 = max(self.port_3.p, 1.0)
|
||||
m_flow = abs(self.mass_flow(self.port_2.p, self.port_3.p))
|
||||
upstream_pressure = max(p_2, p_3)
|
||||
if p_2 >= p_3:
|
||||
upstream_port_name = "port_2"
|
||||
upstream_pressure = p_2
|
||||
downstream_pressure = p_3
|
||||
flow_direction = 1.0
|
||||
else:
|
||||
upstream_port_name = "port_3"
|
||||
upstream_pressure = p_3
|
||||
downstream_pressure = p_2
|
||||
flow_direction = -1.0
|
||||
upstream_temperature = self._upstream_temperature(
|
||||
"port_2" if p_2 >= p_3 else "port_3"
|
||||
upstream_port_name
|
||||
)
|
||||
mass_flow_parameter, gas_velocity = self._one_way_flow_characteristics(
|
||||
upstream_pressure=upstream_pressure,
|
||||
downstream_pressure=downstream_pressure,
|
||||
upstream_temperature=upstream_temperature,
|
||||
)
|
||||
density = max(self.medium.density(upstream_pressure, upstream_temperature), 1.0e-12)
|
||||
area = max(self.effective_area, 1.0e-18)
|
||||
return {
|
||||
"xv": self.opening,
|
||||
"cm": m_flow / (self.effective_cq * area * upstream_pressure),
|
||||
"gasvel": m_flow / (density * area),
|
||||
"cm": mass_flow_parameter,
|
||||
"gasvel": flow_direction * gas_velocity,
|
||||
}
|
||||
|
||||
def pressure_flow_equation_residuals(self) -> tuple[EquationResidual, ...]:
|
||||
@@ -605,6 +676,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
||||
)
|
||||
|
||||
def update_stream_outflows(self, connected_h: Mapping[str, float]) -> None:
|
||||
self._connected_h = dict(connected_h)
|
||||
self.port_2.h_outflow = connected_h["port_3"]
|
||||
self.port_3.h_outflow = connected_h["port_2"]
|
||||
|
||||
@@ -684,6 +756,7 @@ class AmesimPnvo001SignalOpening(AmesimPnvo001FixedOpening):
|
||||
self.port_2.h_outflow = initial_h
|
||||
self.port_3 = self.register_declared_port("port_3")
|
||||
self.port_3.h_outflow = initial_h
|
||||
self._connected_h: dict[str, float] = {}
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
|
||||
@@ -164,9 +164,13 @@ class AmesimPnl00r(AlgebraicComponent):
|
||||
|
||||
def _port_temperature(self, port_name: str) -> float:
|
||||
port = self.get_port(port_name)
|
||||
if port.h_outflow > 0.0:
|
||||
return max(self.medium.temperature_from_enthalpy(port.h_outflow), 1.0)
|
||||
return self.medium.T_ref
|
||||
return max(
|
||||
self.medium.temperature_from_pressure_enthalpy(
|
||||
max(port.p, 1.0),
|
||||
port.h_outflow,
|
||||
),
|
||||
1.0,
|
||||
)
|
||||
|
||||
def _dynamic_viscosity(self, temperature_k: float) -> float:
|
||||
return self.medium.dynamic_viscosity(temperature_k)
|
||||
@@ -494,9 +498,9 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
|
||||
self.volume = self.area * self.le
|
||||
self.exchange_area = pi * self.diam * self.le
|
||||
m0 = medium.density(self.p0, self.T0) * self.volume
|
||||
U0 = m0 * medium.specific_internal_energy(self.T0)
|
||||
U0 = m0 * medium.specific_internal_energy_at_pressure(self.p0, self.T0)
|
||||
self.state = VolumeState(m=m0, U=U0)
|
||||
initial_h = medium.specific_enthalpy(self.T0)
|
||||
initial_h = medium.specific_enthalpy_at_pressure(self.p0, self.T0)
|
||||
self.port_1 = self.register_declared_port("port_1")
|
||||
self.port_1.p = self.p0
|
||||
self.port_1.h_outflow = initial_h
|
||||
@@ -978,8 +982,8 @@ class AmesimPnl0003(DynamicComponent):
|
||||
self.exchange_area = pi * self.diam * self.le
|
||||
self.state_1 = self._initial_state(float(p1_0), float(T1_0))
|
||||
self.state_2 = self._initial_state(float(p2_0), float(T2_0))
|
||||
h1 = medium.specific_enthalpy(float(T1_0))
|
||||
h2 = medium.specific_enthalpy(float(T2_0))
|
||||
h1 = medium.specific_enthalpy_at_pressure(float(p1_0), float(T1_0))
|
||||
h2 = medium.specific_enthalpy_at_pressure(float(p2_0), float(T2_0))
|
||||
self.port_1 = self.register_declared_port("port_1")
|
||||
self.port_1.p = float(p1_0)
|
||||
self.port_1.h_outflow = h1
|
||||
@@ -999,7 +1003,13 @@ class AmesimPnl0003(DynamicComponent):
|
||||
|
||||
def _initial_state(self, pressure: float, temperature: float) -> VolumeState:
|
||||
mass = self.medium.density(pressure, temperature) * self.compliance_volume
|
||||
return VolumeState(m=mass, U=mass * self.medium.specific_internal_energy(temperature))
|
||||
return VolumeState(
|
||||
m=mass,
|
||||
U=mass * self.medium.specific_internal_energy_at_pressure(
|
||||
pressure,
|
||||
temperature,
|
||||
),
|
||||
)
|
||||
|
||||
def get_state_vector(self) -> list[float]:
|
||||
return [*self.state_1.as_vector(), *self.state_2.as_vector()]
|
||||
|
||||
Reference in new issue
Block a user