#pragma once #include "FluidSim/MeshResolution.hpp" #include "FluidSim/Engine.hpp" #include "FluidSim/Ecu.hpp" #include "FluidSim/Vehicle.hpp" #include "FluidSim/Carburetor.hpp" #include "FluidSim/PhysicalGeometry.hpp" #include #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{}; bool operator==(const PipeConfig&) const = default; }; // Parsed calibration only. Runtime state belongs to the scenario components. // Dimensional fields use SI units after loading. struct EngineConfig { PhysicalGeometry geometry; float cells_per_meter{}; // Zero retains legacy programmatic meshes. TOML scenarios specify a density. int cylinders{}; EngineLayout layout{EngineLayout::Inline}; ExhaustTopology topology{ExhaustTopology::Collector}; float bank_angle{60}; CylinderConfig cylinder; CrankshaftConfig crankshaft; EcuConfig ecu; VehicleConfig vehicle; CarburetorConfig fuel; FourStrokeCylinder::CamProfile intake_cam,exhaust_cam; FourStrokeCylinder::ValveDynamics intake_valve,exhaust_valve; struct ValveSound { float mode_hz{3600}, effective_mass_kg{0.18f}, radiation_area{0.001f}, damping_ratio{0.9f}; } valve_sound; 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 JunctionBranchConfig { int pipe{}; bool left{}; std::array direction{}; }; struct JunctionConfig { std::string model{"volume"}; // volume, characteristic, or legacy float turning_loss{0}; std::vector branches; bool h_pipe{true}; float junction_volume{50e-6f}; }; void validate_engine_config(const EngineConfig& config,const std::string& context="engine config"); }