Files
FluidSimCpp/include/FluidSim/Turbocharger.hpp
2026-10-23 03:00:20 +02:00

82 lines
4.1 KiB
C++

#pragma once
#include "FluidSim/Fluid.hpp"
#include <array>
#include <cstdint>
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<float, 4> 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<Pipe1D>& 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<Port*> 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<Port*, 4> internal_;
std::array<float, 4> 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