#pragma once #include "FluidSim/Fluid.hpp" #include #include namespace fluidsim::port { // RHB31/VZ21-size mean-line approximation. Geometry, losses and coefficients // are estimates, not a digitized or validated manufacturer performance map. struct TurboConfig { static TurboConfig gt17(); // estimated Saab GT1752-size calibration double shaft_inertia{4e-6}; // kg m^2, compressor+turbine+shaft rigid rotor double compressor_radius{.018}, turbine_radius{.0135}; double compressor_head_coefficient{.60}, compressor_efficiency{.65}; double turbine_peak_efficiency{.65}, turbine_optimum_speed_ratio{.70}; double compressor_effective_area{110e-6}, turbine_effective_area{100e-6}; double bearing_viscous{1e-7}, windage{2e-11}; // Nm/(rad/s), Nm/(rad/s)^2 // Estimated pressure-can/spring wastegate. Set maximum lift to zero for a // pure ungated turbo bench test. This changes bypass AREA, never boost. double gate_diaphragm_area{8e-4}, gate_spring_preload{40}, gate_spring_stiffness{6000}; double gate_damping{120}, gate_diameter{.014}, gate_maximum_lift{.004}; double reference_pressure{101325}; float compressor_inlet_volume{20e-6f}, compressor_outlet_volume{30e-6f}; float turbine_inlet_volume{30e-6f}, turbine_outlet_volume{20e-6f}; std::array connection_diameters{.024f, .024f, .025f, .026f}; }; struct TurboSnapshot { double rpm{}, angle{}, shaft_energy{}, turbine_power{}, compressor_power{}, bearing_power{}; double compressor_flow{}, turbine_flow{}, compressor_pressure_ratio{}, turbine_pressure_ratio{}; double turbine_inlet_pressure{}, turbine_outlet_pressure{}, charge_pressure{}, charge_temperature{}; double bearing_heat{}, energy_residual{}; std::uint64_t limited_transfers{}; double wastegate_flow{}, wastegate_lift{}; }; // Four pressure-storage nodes joined by turbine/nozzle and centrifugal-pump // characteristics. Existing pipe orifices exchange conserved mass/enthalpy. // The whole turbo is ONE solver component; do not also register its volumes. class Turbocharger final : public Component { public: explicit Turbocharger(TurboConfig config = {}); const TurboConfig config; Volume0D compressor_inlet, compressor_outlet, turbine_inlet, turbine_outlet; Port& compressor_inlet_port; Port& compressor_outlet_port; Port& turbine_inlet_port; Port& turbine_outlet_port; void connect(BoundarySystem& boundaries, const std::vector& pipes, int compressor_in, bool compressor_in_left, int compressor_out, bool compressor_out_left, int turbine_in, bool turbine_in_left, int turbine_out, bool turbine_out_left); std::vector ports() override; void update_state(float dt) override; TurboSnapshot snapshot() const; double omega() const { return omega_; } double shaft_energy() const { return .5*config.shaft_inertia*omega_*omega_; } double fluid_energy() const; // Intended for standalone initialization/tests, never an imposed running speed. void set_initial_rpm(double rpm); void set_wastegate_duty(double duty) { gate_duty_ = std::isfinite(duty) ? std::clamp(duty, 0., .85) : 0.; } private: std::array internal_; std::array connection_areas_{}; double omega_{}, angle_{}, bearing_heat_{}; double turbine_power_{}, compressor_power_{}, bearing_power_{}, energy_residual_{}; double compressor_flow_{}, turbine_flow_{}; double wastegate_flow_{}, wastegate_lift_{}; std::uint64_t limited_transfers_{}; bool connected_{}; double gate_duty_{}; // pneumatic bleed fraction; zero restores spring boost static double nozzle(double upstream_pressure, double upstream_temperature, double downstream_pressure, double area); double transfer_flow(Volume0D& inlet, Volume0D& outlet, Port& inlet_external, Port& outlet_external, double requested, double dt); static void set_transfer(Volume0D& inlet, Volume0D& outlet, Port& inlet_internal, Port& outlet_internal, double flow, double shaft_work, double dt); }; } // namespace fluidsim::port