增加质量计算接口

This commit is contained in:
ljz committed 2026-06-22 15:40:37 +08:00
1 parent 5407eebf2f
commit 63fd509a3f
3 files changed
+134 -6

No files matched your search

+2
View File
@@ -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",
+83 -6
View File
@@ -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']
+49
View File
@@ -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 = {