#pragma once #include "FluidSim/Engine.hpp" #include "FluidSim/Ecu.hpp" #include "FluidSim/Vehicle.hpp" #include "FluidSim/Carburetor.hpp" #include #include namespace fluidsim::port { enum class ScenarioKind { Twin, TwoStroke, SaabB205, AmericanV8 }; enum class FourStrokePreset { Twin, SaabB205, AmericanV8 }; enum class EngineLayout { Inline, V, Boxer }; enum class ExhaustTopology { Collector, Staged, AmericanV8 }; struct PipeConfig { std::string id; float diameter{}, length{}; // metres int cells{}, count{1}; bool silenced{}; }; // Parsed calibration only. Runtime state belongs to the scenario components. // Dimensional fields use SI units after loading. struct EngineConfig { int cylinders{}; EngineLayout layout{EngineLayout::Inline}; ExhaustTopology topology{ExhaustTopology::Collector}; float bank_angle{60}; CylinderConfig cylinder; CrankshaftConfig crankshaft; EcuConfig ecu; VehicleConfig vehicle; CarburetorConfig fuel; bool carbureted{}, initialize_phased_charge{true}; float initial_rpm{}, starter_torque{}, maximum_load_torque{}; float plenum_volume{}, collector_volume{}, throttle_diameter{}, pipe_damping{}; int minimum_substeps{1}; std::vector phase_degrees; std::vector pipes; bool has_silenced_exhaust() const { for(const auto& p:pipes)if(p.silenced)return true;return false; } bool american_headers() const { return topology==ExhaustTopology::AmericanV8; } bool staged_headers() const { return topology==ExhaustTopology::Staged; } bool dual_outlets() const { return american_headers() || (staged_headers() && layout==EngineLayout::V); } int header_groups() const { return cylinders==3?1:2; } }; struct JunctionConfig { bool h_pipe{true}; float junction_volume{50e-6f}; }; void validate_engine_config(const EngineConfig& config,const std::string& context="engine config"); }