There is this code in which the calculation of the centrifugal nozzle of a liquid rocket engine is performed. All basic calculations take place in the Injector
class. The AngularValues
class stores the value of the right angle required for the code to work. The ConstructiveTypes
class stores the type of nozzle being designed.
I'm thinking is it worth dividing the code into classes for calculation by type of construction, or is such code quite readable?
I also noticed that in cases when all functions are called sequentially, then many functions are executed more than once. Maybe it's worth caching using the functools
library?
All formulas from this code, as well as possibly some additional information, are found in this book on pages 47 - 54 (book)
from enum import Enum
from math import pi, sqrt, log, atan, cos
from dataclasses import dataclass
class AngularValues(Enum):
RIGHT_ANGLE = 90
class ConstructiveTypes(Enum):
CENTRIFUGAL_INJECTOR = "CENTRIFUGAL"
SCREW_INJECTOR = "SCREW"
@dataclass(frozen=True, slots=True)
class Injector:
outer_diameter_injector: float
side_wall_thickness_injector: float
number_input_tangential_holes: float
diameter_input_tangential_holes: float
length_input_tangential_holes: float
relative_length_twisting_chamber: float
diameter_injector_nozzle: float
relative_length_injector_nozzle: float
angle_nozzle_axis: float
mass_flow_rate: float
viscosity: float
cross_sectional_area_one_passage_channel: float
density_fuel_component_front_injector: float
density_combustion_products: float
surface_tension_coefficient: float
injector_type: str
@property
def diameter_twisting_chamber_injector(self) -> float:
"""Возвращает диаметр камеры закручивания центробежной форсунки"""
return self.outer_diameter_injector - 2 * self.side_wall_thickness_injector
@property
def relative_length_tangential_hole(self) -> float:
"""Возвращает отношение длины входного тангенциального к его диаметру"""
return self.length_input_tangential_holes / self.diameter_input_tangential_holes
@property
def length_twisting_chamber(self) -> float:
"""Возвращает длину камеры закручивания центробежной форсунки"""
return self.relative_length_twisting_chamber * self.diameter_twisting_chamber_injector
@property
def radius_twisting_chamber_injector(self) -> float:
"""Возвращает радиус камеры закручивания центробежной форсунки"""
return self.diameter_twisting_chamber_injector / 2
@property
def radius_input_tangential_holes(self) -> float:
"""Возвращает радиус входных тангенциальных отверстий"""
return self.diameter_input_tangential_holes / 2
@property
def radius_tangential_inlet(self) -> float:
"""Возвращает величину радиуса, на котором расположена ось входного тангенциального отверстия от оси форсунки"""
return self.radius_twisting_chamber_injector - self.radius_input_tangential_holes
@property
def length_injector_nozzle(self) -> float:
"""Возвращает длину сопла форсунки"""
return self.relative_length_injector_nozzle * self.diameter_injector_nozzle
@property
def radius_injector_nozzle(self) -> float:
"""Возвращает радиус сопла форсунки"""
return self.diameter_injector_nozzle / 2
@property
def reynolds_number(self) -> float:
"""Возвращает число Рейнольдса"""
return (4 * self.mass_flow_rate) / (pi * self.viscosity * self.diameter_input_tangential_holes
* sqrt(self.number_input_tangential_holes))
@property
def coefficient_friction(self) -> float:
"""Возвращает коэффициент трения"""
return 10 ** ((25.8 / (log(self.reynolds_number, 10)) ** 2.58) - 2)
@property
def geometric_characteristics_screw_injector(self) -> float:
"""Возвращает геометрическую характеристику шнековой форсунки"""
return (pi * self.radius_tangential_inlet * self.radius_injector_nozzle) / \
(self.number_input_tangential_holes * self.cross_sectional_area_one_passage_channel)
@property
def geometric_characteristics_centrifugal_injector(self) -> float:
"""Возвращает геометрическую характеристику центробежной форсунки"""
if self.angle_nozzle_axis == AngularValues.RIGHT_ANGLE.value:
return (self.radius_tangential_inlet * self.radius_injector_nozzle) / \
(self.number_input_tangential_holes * self.radius_input_tangential_holes ** 2)
else:
return (self.radius_tangential_inlet * self.radius_injector_nozzle) / \
(
self.number_input_tangential_holes * self.radius_input_tangential_holes ** 2) * \
self.angle_nozzle_axis
@property
def equivalent_geometric_characteristic_injector(self) -> float:
"""Возвращает эквивалентную геометрическую характеристику"""
if self.injector_type == ConstructiveTypes.SCREW_INJECTOR.value:
geometric_characteristics = self.geometric_characteristics_screw_injector
else:
geometric_characteristics = self.geometric_characteristics_centrifugal_injector
return geometric_characteristics / (1 + self.coefficient_friction / 2 * self.radius_tangential_inlet *
(self.radius_tangential_inlet + self.diameter_input_tangential_holes -
self.radius_injector_nozzle))
@property
def ratio_live_section_injector_nozzle(self) -> float:
"""Возвращает коэффициент живого сечения сопла форсунки"""
return 1 / ((self.equivalent_geometric_characteristic_injector / (2 * sqrt(2)) +
sqrt(self.equivalent_geometric_characteristic_injector**2 / 8 - 1 / 27))**(1/3) +
(self.equivalent_geometric_characteristic_injector / (2 * sqrt(2)) -
sqrt(self.equivalent_geometric_characteristic_injector**2 / 8 - 1 / 27))**(1/3))**2
@property
def flow_rate_centrifugal_injector(self) -> float:
"""Возвращает коэффициент расхода центробежной форсунки"""
return self.ratio_live_section_injector_nozzle * sqrt(self.ratio_live_section_injector_nozzle /
(2 - self.ratio_live_section_injector_nozzle))
@property
def average_angle_spray_torch(self) -> float:
"""Возвращает средний угол факела распыла"""
return atan(2 * self.flow_rate_centrifugal_injector * self.equivalent_geometric_characteristic_injector /
sqrt((1 + sqrt(1 - self.ratio_live_section_injector_nozzle))**2 - 4 *
self.flow_rate_centrifugal_injector**2 *
self.equivalent_geometric_characteristic_injector**2))
@property
def injector_nozzle_area(self) -> float:
"""Возвращает площадь сопла форсунки"""
return pi * self.diameter_injector_nozzle ** 2 / 4
@property
def pressure_drop_front_injector(self) -> float:
"""Возврашает перепад давления на форсунке, для обеспечения необходимого расхода компонента через форсунку"""
return self.mass_flow_rate**2 / (2 * self.density_fuel_component_front_injector *
self.flow_rate_centrifugal_injector**2 * self.injector_nozzle_area**2)
@property
def radius_vortex_outlet_section_injector(self) -> float:
"""Возвращает радиус вихря жидкости или воздушного вихря в выходном сечении форсунки"""
return self.radius_injector_nozzle * sqrt(1 - self.ratio_live_section_injector_nozzle)
@property
def area_live_section_injector_nozzle(self) -> float:
"""Возвращает площадь живого сечения сопла форсунки"""
return self.ratio_live_section_injector_nozzle * self.injector_nozzle_area
@property
def average_value_axial_velocity_outlet_injector(self) -> float:
"""Возвращает среднее значение осевой скорости на выходе из форсунки"""
return self.mass_flow_rate / (self.density_fuel_component_front_injector *
self.area_live_section_injector_nozzle)
@property
def average_value_absolute_velocity_outlet_injector(self) -> float:
"""Возвращает среднее значение абсолютной скорости на выходе из форсунки"""
return self.average_value_axial_velocity_outlet_injector / cos(self.average_angle_spray_torch)
@property
def thickness_veil_outlet_injector(self) -> float:
"""Возвращает толщину пелены на выходе из форсунки"""
return self.radius_injector_nozzle - self.radius_vortex_outlet_section_injector
@property
def weber_criterion(self) -> float:
"""Возвращает критерий Вебера"""
return self.density_combustion_products * self.average_value_absolute_velocity_outlet_injector**2 * \
self.diameter_injector_nozzle / self.surface_tension_coefficient
@property
def laplace_criterion(self) -> float:
"""Возвращает критерий Лапласа"""
return self.density_fuel_component_front_injector * self.thickness_veil_outlet_injector * \
self.surface_tension_coefficient / self.viscosity
@property
def media_diameter_spray_torch_droplets(self) -> float:
"""Возвращает медианный диаметр образовавшихся капель в факеле распыла форсунки"""
return 269 * self.laplace_criterion**-0.35 * ((self.weber_criterion * self.density_combustion_products) /
self.density_fuel_component_front_injector)**0.483