增加质量计算接口
This commit is contained in:
1 parent
5407eebf2f
commit
63fd509a3f
3 files changed
+134
-6
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
"""Tools for CO2 Brayton cycle simulation and optimization."""
|
"""Tools for CO2 Brayton cycle simulation and optimization."""
|
||||||
|
|
||||||
from .components import (
|
from .components import (
|
||||||
|
ComponentMassMixin,
|
||||||
Compressor,
|
Compressor,
|
||||||
Concentrator,
|
Concentrator,
|
||||||
Condenser,
|
Condenser,
|
||||||
@@ -26,6 +27,7 @@ from .sensitivity import (
|
|||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"BraytonCycle",
|
"BraytonCycle",
|
||||||
|
"ComponentMassMixin",
|
||||||
"CO2PropertyCalculator",
|
"CO2PropertyCalculator",
|
||||||
"Compressor",
|
"Compressor",
|
||||||
"Concentrator",
|
"Concentrator",
|
||||||
|
|||||||
@@ -1,8 +1,74 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Component models used by Brayton cycle simulations."""
|
"""Component models used by Brayton cycle simulations."""
|
||||||
|
|
||||||
class Compressor():
|
|
||||||
|
class ComponentMassMixin:
|
||||||
|
"""Shared mass-calculation interface for cycle components."""
|
||||||
|
|
||||||
|
component_type = "component"
|
||||||
|
|
||||||
|
def _init_mass_interface(self):
|
||||||
|
self.mass = None
|
||||||
|
self.mass_variables = None
|
||||||
|
|
||||||
|
def calculate_mass(self, mass_model=None, **kwargs):
|
||||||
|
"""Calculate and store component mass.
|
||||||
|
|
||||||
|
The future mass model can be provided as either a callable accepting
|
||||||
|
``(component, **kwargs)`` or an object exposing ``calculate_mass`` or
|
||||||
|
``calculate_<component_type>_mass``.
|
||||||
|
"""
|
||||||
|
if self.variables is None:
|
||||||
|
raise ValueError("Run component calculator before mass calculation")
|
||||||
|
|
||||||
|
if mass_model is None:
|
||||||
|
result = self._calculate_mass(**kwargs)
|
||||||
|
else:
|
||||||
|
result = self._run_external_mass_model(mass_model, **kwargs)
|
||||||
|
|
||||||
|
return self._store_mass_result(result)
|
||||||
|
|
||||||
|
def mass_calculator(self, mass_model=None, **kwargs):
|
||||||
|
return self.calculate_mass(mass_model=mass_model, **kwargs)
|
||||||
|
|
||||||
|
def _calculate_mass(self, **kwargs):
|
||||||
|
raise NotImplementedError(
|
||||||
|
f"{self.__class__.__name__} mass model is not implemented yet. "
|
||||||
|
"Pass a mass_model or override _calculate_mass()."
|
||||||
|
)
|
||||||
|
|
||||||
|
def _run_external_mass_model(self, mass_model, **kwargs):
|
||||||
|
method_name = f"calculate_{self.component_type}_mass"
|
||||||
|
if hasattr(mass_model, method_name):
|
||||||
|
return getattr(mass_model, method_name)(self, **kwargs)
|
||||||
|
if hasattr(mass_model, "calculate_mass"):
|
||||||
|
return mass_model.calculate_mass(self, **kwargs)
|
||||||
|
if callable(mass_model):
|
||||||
|
return mass_model(self, **kwargs)
|
||||||
|
raise TypeError("mass_model must be callable or expose a supported method")
|
||||||
|
|
||||||
|
def _store_mass_result(self, result):
|
||||||
|
if isinstance(result, dict):
|
||||||
|
if "mass" in result:
|
||||||
|
mass = result["mass"]
|
||||||
|
elif "total_mass" in result:
|
||||||
|
mass = result["total_mass"]
|
||||||
|
else:
|
||||||
|
raise ValueError("Mass result dictionary must include 'mass'")
|
||||||
|
mass_variables = dict(result)
|
||||||
|
else:
|
||||||
|
mass = result
|
||||||
|
mass_variables = {"mass": result}
|
||||||
|
|
||||||
|
self.mass = mass
|
||||||
|
self.mass_variables = mass_variables
|
||||||
|
self.variables["mass"] = self.mass
|
||||||
|
self.variables["mass_variables"] = self.mass_variables
|
||||||
|
return self.mass
|
||||||
|
|
||||||
|
class Compressor(ComponentMassMixin):
|
||||||
"""压缩机类"""
|
"""压缩机类"""
|
||||||
|
component_type = "compressor"
|
||||||
def __init__(self, name, eff):
|
def __init__(self, name, eff):
|
||||||
"""
|
"""
|
||||||
初始化参数
|
初始化参数
|
||||||
@@ -18,6 +84,7 @@ class Compressor():
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.eff = eff
|
self.eff = eff
|
||||||
self.variables = None
|
self.variables = None
|
||||||
|
self._init_mass_interface()
|
||||||
|
|
||||||
def calculator(self, p_in, T_in, p_out, property_calculator):
|
def calculator(self, p_in, T_in, p_out, property_calculator):
|
||||||
# 先计算熵值
|
# 先计算熵值
|
||||||
@@ -51,8 +118,9 @@ class Compressor():
|
|||||||
'pi': p_out / p_in
|
'pi': p_out / p_in
|
||||||
}
|
}
|
||||||
|
|
||||||
class Turbine():
|
class Turbine(ComponentMassMixin):
|
||||||
"""透平类"""
|
"""透平类"""
|
||||||
|
component_type = "turbine"
|
||||||
def __init__(self, name, eff):
|
def __init__(self, name, eff):
|
||||||
"""
|
"""
|
||||||
初始化参数
|
初始化参数
|
||||||
@@ -62,6 +130,7 @@ class Turbine():
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.eff = eff
|
self.eff = eff
|
||||||
self.variables = None
|
self.variables = None
|
||||||
|
self._init_mass_interface()
|
||||||
|
|
||||||
def calculator(self, p_in, T_in, p_out, property_calculator):
|
def calculator(self, p_in, T_in, p_out, property_calculator):
|
||||||
"""涡轮参数计算"""
|
"""涡轮参数计算"""
|
||||||
@@ -94,8 +163,9 @@ class Turbine():
|
|||||||
'pi': p_in / p_out
|
'pi': p_in / p_out
|
||||||
}
|
}
|
||||||
|
|
||||||
class Recuperator():
|
class Recuperator(ComponentMassMixin):
|
||||||
"""换热器类"""
|
"""换热器类"""
|
||||||
|
component_type = "recuperator"
|
||||||
def __init__(self, name, eff, x=0):
|
def __init__(self, name, eff, x=0):
|
||||||
"""
|
"""
|
||||||
初始化参数
|
初始化参数
|
||||||
@@ -107,6 +177,7 @@ class Recuperator():
|
|||||||
self.Q_ex = None
|
self.Q_ex = None
|
||||||
self.variables = None
|
self.variables = None
|
||||||
self.x = x
|
self.x = x
|
||||||
|
self._init_mass_interface()
|
||||||
|
|
||||||
def calculator(self, cold_inlet_state, hot_inlet_state, bypass_info, ploss=0.0, property_calculator=None):
|
def calculator(self, cold_inlet_state, hot_inlet_state, bypass_info, ploss=0.0, property_calculator=None):
|
||||||
"""
|
"""
|
||||||
@@ -254,11 +325,13 @@ class Recuperator():
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
class Heater():
|
class Heater(ComponentMassMixin):
|
||||||
"""加热器类"""
|
"""加热器类"""
|
||||||
|
component_type = "heater"
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.variables = None
|
self.variables = None
|
||||||
|
self._init_mass_interface()
|
||||||
def calculator(self, inlet_state, outlet_state):
|
def calculator(self, inlet_state, outlet_state):
|
||||||
h_in = inlet_state['h']
|
h_in = inlet_state['h']
|
||||||
h_out = outlet_state['h']
|
h_out = outlet_state['h']
|
||||||
@@ -280,11 +353,13 @@ class Heater():
|
|||||||
'Q_in': Q_input,
|
'Q_in': Q_input,
|
||||||
}
|
}
|
||||||
|
|
||||||
class Condenser():
|
class Condenser(ComponentMassMixin):
|
||||||
"""冷凝器类"""
|
"""冷凝器类"""
|
||||||
|
component_type = "condenser"
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.variables = None
|
self.variables = None
|
||||||
|
self._init_mass_interface()
|
||||||
def calculator(self, inlet_state, outlet_state):
|
def calculator(self, inlet_state, outlet_state):
|
||||||
h_in = inlet_state['h']
|
h_in = inlet_state['h']
|
||||||
h_out = outlet_state['h']
|
h_out = outlet_state['h']
|
||||||
@@ -306,11 +381,13 @@ class Condenser():
|
|||||||
'Q_out': Q_output,
|
'Q_out': Q_output,
|
||||||
}
|
}
|
||||||
|
|
||||||
class Concentrator():
|
class Concentrator(ComponentMassMixin):
|
||||||
"""汇流组件"""
|
"""汇流组件"""
|
||||||
|
component_type = "concentrator"
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.variables = None
|
self.variables = None
|
||||||
|
self._init_mass_interface()
|
||||||
def calculator(self, inlet_state_bypass, inlet_state_mroad, x, property_calculator):
|
def calculator(self, inlet_state_bypass, inlet_state_mroad, x, property_calculator):
|
||||||
h_in_bypass = inlet_state_bypass['h']
|
h_in_bypass = inlet_state_bypass['h']
|
||||||
h_in_mroad = inlet_state_mroad['h']
|
h_in_mroad = inlet_state_mroad['h']
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ class BraytonCycle:
|
|||||||
self.heater = None
|
self.heater = None
|
||||||
self.condenser = None
|
self.condenser = None
|
||||||
self.concentrator = None
|
self.concentrator = None
|
||||||
|
self.component_masses = None
|
||||||
|
self.total_mass = None
|
||||||
self.refprop_path = refprop_path
|
self.refprop_path = refprop_path
|
||||||
self.property_calculator = CO2PropertyCalculator(self.refprop_path)
|
self.property_calculator = CO2PropertyCalculator(self.refprop_path)
|
||||||
|
|
||||||
@@ -36,6 +38,53 @@ class BraytonCycle:
|
|||||||
Q_input = self.heater.variables["Q_in"]
|
Q_input = self.heater.variables["Q_in"]
|
||||||
return (Wt - Wc) / Q_input
|
return (Wt - Wc) / Q_input
|
||||||
|
|
||||||
|
def iter_components(self):
|
||||||
|
"""Yield initialized component objects in the current cycle."""
|
||||||
|
for value in (
|
||||||
|
self.compressor,
|
||||||
|
self.turbine,
|
||||||
|
self.recuperator,
|
||||||
|
self.heater,
|
||||||
|
self.condenser,
|
||||||
|
self.concentrator,
|
||||||
|
):
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
|
if isinstance(value, list):
|
||||||
|
for component in value:
|
||||||
|
if component is not None:
|
||||||
|
yield component
|
||||||
|
else:
|
||||||
|
yield value
|
||||||
|
|
||||||
|
def calculate_component_masses(self, mass_model=None, **kwargs):
|
||||||
|
"""Calculate mass for each initialized component."""
|
||||||
|
component_masses = {}
|
||||||
|
for component in self.iter_components():
|
||||||
|
mass = component.calculate_mass(mass_model=mass_model, **kwargs)
|
||||||
|
key = component.variables.get("name", component.name)
|
||||||
|
component_masses[key] = {
|
||||||
|
"component_type": component.component_type,
|
||||||
|
"mass": mass,
|
||||||
|
"mass_variables": component.mass_variables,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.component_masses = component_masses
|
||||||
|
return self.component_masses
|
||||||
|
|
||||||
|
def cycle_mass_calculator(self, mass_model=None, **kwargs):
|
||||||
|
"""Calculate and return total cycle component mass."""
|
||||||
|
component_masses = self.calculate_component_masses(
|
||||||
|
mass_model=mass_model,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
self.total_mass = sum(item["mass"] for item in component_masses.values())
|
||||||
|
return self.total_mass
|
||||||
|
|
||||||
|
def calculate_total_mass(self, mass_model=None, **kwargs):
|
||||||
|
"""Compatibility alias for cycle_mass_calculator."""
|
||||||
|
return self.cycle_mass_calculator(mass_model=mass_model, **kwargs)
|
||||||
|
|
||||||
def SC(self, T_low, T_high, p_low, p_high, param=None):
|
def SC(self, T_low, T_high, p_low, p_high, param=None):
|
||||||
"""Simple Brayton cycle."""
|
"""Simple Brayton cycle."""
|
||||||
defaults = {
|
defaults = {
|
||||||
|
|||||||
Reference in new issue
Block a user