Update
This commit is contained in:
@@ -100,6 +100,11 @@ else()
|
||||
endif()
|
||||
|
||||
include(CTest)
|
||||
if(BUILD_TESTING)
|
||||
add_executable(fluidsim_saab_turbo_regression tests/saab_turbo_regression.cpp)
|
||||
target_link_libraries(fluidsim_saab_turbo_regression PRIVATE fluidsim_core)
|
||||
add_test(NAME fluidsim_saab_turbo_regression COMMAND fluidsim_saab_turbo_regression)
|
||||
endif()
|
||||
if(BUILD_TESTING)
|
||||
add_executable(fluidsim_physics_tests tests/physics_tests.cpp)
|
||||
target_link_libraries(fluidsim_physics_tests PRIVATE fluidsim_core)
|
||||
@@ -108,6 +113,8 @@ endif()
|
||||
|
||||
add_executable(fluidsim_physics_benchmark tools/physics_benchmark.cpp)
|
||||
target_link_libraries(fluidsim_physics_benchmark PRIVATE fluidsim_core)
|
||||
add_executable(fluidsim_scenario_benchmark tools/scenario_benchmark.cpp)
|
||||
target_link_libraries(fluidsim_scenario_benchmark PRIVATE fluidsim_core)
|
||||
if(BUILD_TESTING)
|
||||
add_executable(fluidsim_fluid_validation tests/fluid_validation.cpp)
|
||||
target_link_libraries(fluidsim_fluid_validation PRIVATE fluidsim_core)
|
||||
|
||||
23
README.md
23
README.md
@@ -1,5 +1,10 @@
|
||||
# FluidSimCpp
|
||||
|
||||
Solver performance measurements and reproducible SIMD/threading experiments are
|
||||
documented in [the optimization audit](verification/OPTIMIZATION.md). Current
|
||||
scenarios use serial pipe execution because per-substep threading costs more than
|
||||
it saves at their graph sizes. Portable compiler SIMD remains enabled by default.
|
||||
|
||||
FluidSimCpp aims to reproduce sound from a physically accurate simulation of
|
||||
compressible flow in pipes and connected volumes, sampled at 44,100 Hz. Each
|
||||
audio sample advances physical time by 1/44100 second; adaptive internal
|
||||
@@ -157,13 +162,19 @@ unboosted twin is unchanged unless `--turbo vz21` is selected.
|
||||
|
||||
This is an estimated VZ21-size model, not a measured turbo map. Engine exhaust
|
||||
pulses are implemented; blade-passing whistle/wakes are still pending. The
|
||||
seven-second twin transient and all nine CTest suites passed. Sustained high-load
|
||||
performance is close to, or slower than, real time in the current benchmark;
|
||||
watch the underrun counter during testing. See
|
||||
seven-second twin transient and all nine CTest suites passed. The optimized
|
||||
7,000-RPM workload takes about 0.65 wall seconds per simulated second on the audit
|
||||
machine; actual playback headroom depends on the computer. See
|
||||
[turbo verification](verification/TURBO_VZ21.md) for assumptions and results.
|
||||
|
||||
## Saab B205 / 9-5 wagon baseline
|
||||
|
||||
The Saab menu entry now includes an estimated GT17 turbo and ECU wastegate boost
|
||||
control (up to 0.45 bar gauge). Launch with `--scenario b205 --turbo gt17`, or use
|
||||
`--turbo none` for the naturally aspirated baseline. See [GT17 verification](verification/SAAB_GT17.md)
|
||||
for controller behavior, assumptions and tests. Charge heating and backpressure
|
||||
are simulated; an intercooler is not yet included.
|
||||
|
||||
Select **Saab B205 / 9-5 wagon** from the desktop menu, or launch directly:
|
||||
|
||||
```sh
|
||||
@@ -177,10 +188,10 @@ cylinder and 1-3-4-2 firing order. Four intake runners and four exhaust headers
|
||||
connect shared plenums and a tailpipe. The vehicle approximates a 9-5 wagon:
|
||||
1675 kg with driver, five-speed manual, FM55 B05 overall ratios
|
||||
13.70 / 7.12 / 4.77 / 3.62 / 2.67, and 4.05 final drive. No sixth gear is offered.
|
||||
Controls and dyno match the other scenarios. There is no turbo system yet;
|
||||
this is an atmospheric-breathing B205 geometry baseline. Pipe/cam dimensions,
|
||||
Controls and dyno match the other scenarios. The original atmospheric-breathing
|
||||
geometry baseline remains available with `--turbo none`. Pipe/cam dimensions,
|
||||
friction, idle/ignition maps, clutch, drag and loaded tire radius are estimates.
|
||||
It does not reproduce factory turbo power or turbo/exhaust acoustics.
|
||||
Turbo calibration and acoustics are approximate; factory power is not validated.
|
||||
See [B205 verification](verification/B205_BASELINE.md) for sources and checks.
|
||||
|
||||
## Current port status
|
||||
|
||||
@@ -9,12 +9,12 @@ namespace fluidsim::port {
|
||||
// the twin already protects its own simulation state.
|
||||
class DesktopScenario {
|
||||
public:
|
||||
explicit DesktopScenario(ScenarioKind kind, TwoStrokeConfig config = {}) {
|
||||
explicit DesktopScenario(ScenarioKind kind, TwoStrokeConfig config = {}, bool saab_turbo = true) {
|
||||
if (kind == ScenarioKind::TwoStroke)
|
||||
two_ = std::make_unique<TwoStrokeScenario>(44100, config);
|
||||
else
|
||||
twin_ = std::make_unique<FourStrokeScenario>(44100, kind == ScenarioKind::SaabB205 ?
|
||||
FourStrokePreset::SaabB205 : FourStrokePreset::Twin, kind == ScenarioKind::TurboTwin);
|
||||
FourStrokePreset::SaabB205 : FourStrokePreset::Twin, kind == ScenarioKind::TurboTwin || (kind == ScenarioKind::SaabB205 && saab_turbo));
|
||||
}
|
||||
AudioFrame process() {
|
||||
if (twin_)
|
||||
|
||||
@@ -17,6 +17,12 @@ public:
|
||||
float overrun_cut_rpm{3500.0f}, overrun_resume_rpm{2400.0f};
|
||||
float idle_spark_gain{0.0f}, idle_minimum_advance{-5.0f}; // degrees/RPM, degrees BTDC
|
||||
float stoichiometric_afr{14.7f}, power_afr{12.8f};
|
||||
bool boost_control_enabled{false};
|
||||
float maximum_boost{45000}; // Pa gauge, estimated low-pressure B205 calibration
|
||||
float boost_kp{1e-5f}, boost_ki{4e-6f};
|
||||
void control_boost(float dt, float pedal, float rpm, float manifold, float charge, float ambient = 101325);
|
||||
float boost_target() const { return boost_target_; }
|
||||
float wastegate_duty() const { return boost_duty_; }
|
||||
|
||||
void step(float dt, float pedal, float rpm);
|
||||
float fuel_for_air(float trapped_air_mass) const;
|
||||
@@ -24,12 +30,14 @@ public:
|
||||
float throttle_target() const { return target_; }
|
||||
float target_afr() const { return afr_; }
|
||||
float spark_advance() const { return spark_; }
|
||||
bool fuel_cut() const { return limiter_ || overrun_ || fault_; }
|
||||
bool fuel_cut() const { return limiter_ || overrun_ || fault_ || boost_cut_; }
|
||||
bool rev_limited() const { return limiter_; }
|
||||
bool idle_active() const { return idle_; }
|
||||
bool sensor_fault() const { return fault_; }
|
||||
|
||||
private:
|
||||
float boost_target_{}, boost_duty_{}, boost_integral_{}, filtered_boost_{};
|
||||
bool boost_cut_{};
|
||||
float filtered_rpm_{};
|
||||
bool initialized_{};
|
||||
float opening_{}, target_{}, integral_{}, afr_{14.7f}, spark_{10.0f};
|
||||
|
||||
@@ -189,10 +189,14 @@ public:
|
||||
float dt = std::numeric_limits<float>::max();
|
||||
for (std::size_t i = 0; i < cells.size(); ++i) {
|
||||
states_[i] = primitive(cells[i]);
|
||||
waves_[i] = wave(states_[i]);
|
||||
}
|
||||
// Keep the arithmetic loop free of exceptional control flow so SIMD
|
||||
// can evaluate independent cells, then validate before any flux update.
|
||||
for (std::size_t i = 0; i < cells.size(); ++i) {
|
||||
const auto &s = states_[i];
|
||||
if (!(s.rho > 0) || !(s.pressure > 0) || !std::isfinite(s.velocity) || !std::isfinite(s.pressure))
|
||||
throw std::runtime_error("nonphysical pipe state in preparation");
|
||||
waves_[i] = wave(s);
|
||||
dt = std::min(dt, cfl * cell_lengths[i] / waves_[i]);
|
||||
}
|
||||
prepared_ = true;
|
||||
@@ -265,7 +269,12 @@ public:
|
||||
en = minimum;
|
||||
++positivity_repairs;
|
||||
}
|
||||
next_cells_[i] = {rho, mom, en, std::clamp(air / rho, 0.0f, 1.0f)};
|
||||
// Purged tracer tails below the smallest normal float carry less
|
||||
// than 1.18e-38 of the gas mass. Avoid repeatedly transporting
|
||||
// subnormal concentrations; total gas mass and energy are unchanged.
|
||||
const float fraction = std::clamp(air / rho, 0.0f, 1.0f);
|
||||
next_cells_[i] = {rho, mom, en,
|
||||
fraction < std::numeric_limits<float>::min() ? 0.0f : fraction};
|
||||
}
|
||||
cells.swap(next_cells_);
|
||||
prepared_ = false;
|
||||
@@ -399,6 +408,7 @@ private:
|
||||
float *area{};
|
||||
float cd{1}, length{}, loss{}, mdot{};
|
||||
std::size_t budget{std::numeric_limits<std::size_t>::max()};
|
||||
double previous_pressure{};
|
||||
};
|
||||
struct Open {
|
||||
int pipe;
|
||||
@@ -491,7 +501,8 @@ private:
|
||||
const double zero_pressure = s.pressure * std::pow(zero_sound / c, 2 * g / (g - 1));
|
||||
double low = std::min(zero_pressure, double(v.pressure));
|
||||
double high = std::max(zero_pressure, double(v.pressure));
|
||||
double duct_pressure = .5 * (low + high);
|
||||
double duct_pressure = o.length == 0 && o.previous_pressure > low && o.previous_pressure < high
|
||||
? o.previous_pressure : .5 * (low + high);
|
||||
const double flow_sign = v.pressure >= zero_pressure ? 1 : -1;
|
||||
const double flow_scale = area * o.cd;
|
||||
const double density_ratio_scale = std::pow(double(s.pressure) / v.pressure, 1 / g);
|
||||
@@ -537,6 +548,7 @@ private:
|
||||
? candidate
|
||||
: .5 * (low + high);
|
||||
}
|
||||
o.previous_pressure = duct_pressure;
|
||||
float mdot = static_cast<float>(nozzle_flow(duct_pressure));
|
||||
const bool upstream_port = mdot >= 0;
|
||||
const float pup = upstream_port ? v.pressure : static_cast<float>(duct_pressure);
|
||||
|
||||
@@ -24,6 +24,7 @@ enum class FourStrokePreset { Twin, SaabB205 };
|
||||
|
||||
struct ScenarioSnapshot {
|
||||
bool turbo_enabled{};
|
||||
float boost_target{}, wastegate_duty{};
|
||||
TurboSnapshot turbo{};
|
||||
int cylinder_count{2};
|
||||
float rev_limit_rpm{10000};
|
||||
@@ -115,5 +116,9 @@ class SaabB205Scenario : public FourStrokeScenario {
|
||||
public:
|
||||
explicit SaabB205Scenario(int sample_rate = 44100) : FourStrokeScenario(sample_rate, FourStrokePreset::SaabB205) {}
|
||||
};
|
||||
class SaabTurboScenario : public FourStrokeScenario {
|
||||
public:
|
||||
explicit SaabTurboScenario(int sample_rate = 44100) : FourStrokeScenario(sample_rate, FourStrokePreset::SaabB205, true) {}
|
||||
};
|
||||
|
||||
} // namespace fluidsim::port
|
||||
|
||||
@@ -9,6 +9,7 @@ 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};
|
||||
@@ -58,6 +59,7 @@ public:
|
||||
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_;
|
||||
@@ -68,6 +70,7 @@ private:
|
||||
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,
|
||||
|
||||
@@ -63,7 +63,7 @@ std::optional<ScenarioKind> choose_scenario(sf::RenderWindow& window, const sf::
|
||||
const std::array<const char*, 4> descriptions{
|
||||
"Four-stroke twin, motorcycle test and dyno",
|
||||
"125 cc single, expansion chamber, motorcycle test and dyno",
|
||||
"2.0 litre inline-four, no turbo yet, five-speed wagon and dyno",
|
||||
"2.0 litre inline-four, GT17 turbo, ECU boost control and five-speed wagon",
|
||||
"Coupled turbine/compressor, shaft inertia and pressure diagnostics"};
|
||||
int selected = 0;
|
||||
while (window.isOpen()) {
|
||||
@@ -330,7 +330,7 @@ void draw_dashboard(sf::RenderWindow& window, const sf::Font* font, const Scenar
|
||||
if (state.turbo_enabled) {
|
||||
const auto& t = state.turbo;
|
||||
std::ostringstream text;
|
||||
text << std::fixed << std::setprecision(0) << "VZ21-size: " << t.rpm << " rpm "
|
||||
text << std::fixed << std::setprecision(0) << (state.cylinder_count==4 ? "GT17-size: " : "VZ21-size: ") << t.rpm << " rpm "
|
||||
<< std::setprecision(2) << "CPR " << t.compressor_pressure_ratio
|
||||
<< " Charge " << t.charge_pressure/1000 << " kPa / " << std::setprecision(0) << t.charge_temperature << " K"
|
||||
<< "\nTurbine inlet " << t.turbine_inlet_pressure/1000 << " kPa Outlet " << t.turbine_outlet_pressure/1000 << " kPa"
|
||||
@@ -416,9 +416,15 @@ void draw_twin_scene(sf::RenderWindow& window, const sf::Font* font, const Scena
|
||||
|
||||
void draw_b205_scene(sf::RenderWindow& window, const sf::Font* font, const ScenarioSnapshot& s) {
|
||||
window.clear({9, 12, 17});
|
||||
draw_label(window, font, "SAAB B205 | 1985 cc inline-four | firing 1-3-4-2 | no turbo yet",
|
||||
draw_label(window, font, s.turbo_enabled ? "SAAB B205 | GT17 turbo | ECU wastegate control" : "SAAB B205 | naturally aspirated baseline",
|
||||
{260, 181}, sf::Color::White, 16);
|
||||
draw_pipe(window, s, 0, 215, 25, 110);
|
||||
if (s.turbo_enabled) {
|
||||
draw_pipe(window, s, 10, 320, 25, 70);
|
||||
draw_volume(window, float(s.turbo.charge_pressure), {{75, 300}, {35, 38}});
|
||||
draw_graph_line(window, {90, 300}, {25, 215}, {80,145,200});
|
||||
draw_label(window, font, "COMP", {75, 345}, sf::Color::White, 11);
|
||||
}
|
||||
draw_volume(window, s.intake_pressure, {{120, 195}, {65, 65}});
|
||||
draw_label(window, font, "PLENUM", {120, 270}, sf::Color::White, 12);
|
||||
draw_graph_line(window, {190, 211}, {820, 211}, {80, 145, 200});
|
||||
@@ -436,8 +442,15 @@ void draw_b205_scene(sf::RenderWindow& window, const sf::Font* font, const Scena
|
||||
{x, 445}, {180,190,205}, 12);
|
||||
}
|
||||
draw_volume(window, s.exhaust_pressure, {{850, 393}, {65, 48}});
|
||||
draw_pipe(window, s, 9, 420, 920, 1240);
|
||||
draw_label(window, font, "COLLECTOR / OPEN EXHAUST", {930, 390}, sf::Color::White, 12);
|
||||
draw_pipe(window, s, 9, 420, 920, s.turbo_enabled ? 990 : 1240);
|
||||
if (s.turbo_enabled) {
|
||||
draw_volume(window, float(s.turbo.turbine_inlet_pressure), {{995, 397}, {55, 45}});
|
||||
draw_pipe(window, s, 11, 420, 1055, 1240);
|
||||
draw_label(window, font, "GT17", {1000, 450}, sf::Color::White, 12);
|
||||
draw_label(window, font, "Boost target " + std::to_string(int(s.boost_target/1000)) + " kPa gauge | WG duty " + std::to_string(int(100*s.wastegate_duty)) + "%",
|
||||
{25, 515}, sf::Color::White, 14);
|
||||
}
|
||||
draw_label(window, font, s.turbo_enabled ? "COLLECTOR / GT17 / EXHAUST" : "COLLECTOR / OPEN EXHAUST", {930, 375}, sf::Color::White, 12);
|
||||
draw_label(window, font, "9-5 wagon baseline: 1675 kg with driver, five-speed manual, 4.05 final drive",
|
||||
{25, 550}, sf::Color::White, 14);
|
||||
draw_label(window, font, "Engine dimensions/firing from Saab WIS. Manifolds, cams, losses and ECU are estimates.",
|
||||
@@ -465,6 +478,7 @@ int main(int argc, char** argv) {
|
||||
ScenarioKind selected_kind=ScenarioKind::Twin;
|
||||
bool scenario_from_args=false;
|
||||
bool turbo_from_args=false;
|
||||
std::string turbo_name;
|
||||
TwoStrokeConfig two_stroke_config;
|
||||
OutdoorScene selected_scene=OutdoorScene::Wall;
|
||||
for(int i=1;i<argc;++i){
|
||||
@@ -477,8 +491,9 @@ int main(int argc, char** argv) {
|
||||
(value=="two-stroke" ? ScenarioKind::TwoStroke : ScenarioKind::Twin);
|
||||
scenario_from_args=true;
|
||||
}else if(option=="--turbo"){
|
||||
if(value!="none"&&value!="vz21"){std::cerr<<"Choose none or vz21 turbo\n";return 2;}
|
||||
turbo_from_args=value=="vz21";
|
||||
if(value!="none"&&value!="vz21"&&value!="gt17"){std::cerr<<"Choose none, vz21 or gt17 turbo\n";return 2;}
|
||||
turbo_name=value;
|
||||
turbo_from_args=value!="none";
|
||||
}else if(option=="--exhaust"){
|
||||
if(value=="racing") two_stroke_config.exhaust=TwoStrokeExhaust::Racing;
|
||||
else if(value=="straight") two_stroke_config.exhaust=TwoStrokeExhaust::Straight;
|
||||
@@ -490,7 +505,7 @@ int main(int argc, char** argv) {
|
||||
else if(value=="woodland")selected_scene=OutdoorScene::Woodland;
|
||||
else {std::cerr<<"Choose dry, field, wall or woodland\n";return 2;}
|
||||
}
|
||||
}else{std::cerr<<"Usage: fluidsim_desktop [--scenario twin|two-stroke|b205] [--scene dry|field|wall|woodland] [--exhaust racing|straight] [--turbo none|vz21]\n";return 2;}
|
||||
}else{std::cerr<<"Usage: fluidsim_desktop [--scenario twin|two-stroke|b205] [--scene dry|field|wall|woodland] [--exhaust racing|straight] [--turbo none|vz21|gt17]\n";return 2;}
|
||||
}
|
||||
const sf::Vector2u initial_size = scenario_from_args ? sf::Vector2u{window_width, window_height}
|
||||
: sf::Vector2u{720, 606};
|
||||
@@ -519,14 +534,17 @@ int main(int argc, char** argv) {
|
||||
window.setView(sf::View(sf::FloatRect({0, 0}, {float(window_width), float(window_height)})));
|
||||
}
|
||||
if(turbo_from_args) {
|
||||
if(selected_kind!=ScenarioKind::Twin && selected_kind!=ScenarioKind::TurboTwin) {
|
||||
std::cerr<<"The VZ21 turbo test uses the twin scenario\n";return 2;
|
||||
if(turbo_name=="gt17" && selected_kind==ScenarioKind::SaabB205) {
|
||||
// Saab preset selects its GT17 calibration.
|
||||
} else if(turbo_name=="vz21" && (selected_kind==ScenarioKind::Twin || selected_kind==ScenarioKind::TurboTwin)) {
|
||||
selected_kind=ScenarioKind::TurboTwin;
|
||||
} else {
|
||||
std::cerr<<"Use gt17 with b205 or vz21 with twin\n";return 2;
|
||||
}
|
||||
selected_kind=ScenarioKind::TurboTwin;
|
||||
}
|
||||
window.setTitle(selected_kind == ScenarioKind::TurboTwin ? "FluidSim - twin + VZ21 turbo" : selected_kind == ScenarioKind::SaabB205 ? "FluidSim - Saab B205 / 9-5 wagon" :
|
||||
(selected_kind == ScenarioKind::TwoStroke ? "FluidSim - YZ125 two-stroke" : "FluidSim - parallel twin"));
|
||||
DesktopScenario scenario(selected_kind, two_stroke_config);
|
||||
DesktopScenario scenario(selected_kind, two_stroke_config, turbo_name!="none");
|
||||
scenario.set_audio_scene(selected_scene);
|
||||
SimulationRingBuffer ring(ring_capacity);
|
||||
for (std::size_t i = 0; i < preroll_samples; ++i) {
|
||||
|
||||
21
src/ecu.cpp
21
src/ecu.cpp
@@ -3,6 +3,27 @@
|
||||
#include <cmath>
|
||||
|
||||
namespace fluidsim::port {
|
||||
void Ecu::control_boost(float dt, float pedal, float rpm, float manifold, float charge, float ambient) {
|
||||
boost_target_ = boost_duty_ = 0;
|
||||
if (!boost_control_enabled) { boost_integral_ = 0; boost_cut_ = false; return; }
|
||||
if (!std::isfinite(dt) || dt <= 0 || !std::isfinite(pedal) || !std::isfinite(rpm) ||
|
||||
!std::isfinite(manifold) || !std::isfinite(charge) || !std::isfinite(ambient) ||
|
||||
manifold <= 0 || charge <= 0 || ambient <= 0) {
|
||||
boost_integral_ = 0; boost_cut_ = true; return;
|
||||
}
|
||||
const float boost = manifold-ambient;
|
||||
filtered_boost_ += (boost-filtered_boost_)*(-std::expm1(-dt/.05f));
|
||||
if (std::max(manifold, charge)-ambient > maximum_boost+30000) boost_cut_ = true;
|
||||
else if (std::max(manifold, charge)-ambient < maximum_boost+10000) boost_cut_ = false;
|
||||
boost_target_ = maximum_boost*std::clamp((pedal-.5f)/.5f, 0.f, 1.f)*std::clamp((rpm-1500)/1500, 0.f, 1.f);
|
||||
if (boost_target_ <= 0 || fuel_cut()) { boost_integral_ = 0; return; }
|
||||
const float error = boost_target_-filtered_boost_;
|
||||
const float proposed = boost_integral_+boost_ki*error*dt;
|
||||
const float command = .3f+boost_kp*error+proposed;
|
||||
if ((command >= 0 && command <= .85f) || (command > .85f && error < 0) || (command < 0 && error > 0))
|
||||
boost_integral_ = proposed;
|
||||
boost_duty_ = std::clamp(.3f+boost_kp*error+boost_integral_, 0.f, .85f);
|
||||
}
|
||||
void Ecu::step(float dt, float pedal, float rpm) {
|
||||
fault_ = !std::isfinite(dt) || dt <= 0.0f || !std::isfinite(pedal) || !std::isfinite(rpm) || rpm < 0.0f;
|
||||
if (fault_) { target_ = 0.0f; idle_ = false; return; }
|
||||
|
||||
15
src/main.cpp
15
src/main.cpp
@@ -17,6 +17,7 @@ int main(int argc, char** argv) {
|
||||
std::string scenario_name = "twin";
|
||||
TwoStrokeConfig two_stroke_config;
|
||||
bool turbo_enabled = false;
|
||||
std::string turbo_name;
|
||||
for (int i = 1; i + 1 < argc; ++i) {
|
||||
const std::string option = argv[i];
|
||||
if (option == "--seconds") duration_seconds = std::max(0.0f, std::strtof(argv[++i], nullptr));
|
||||
@@ -24,8 +25,9 @@ int main(int argc, char** argv) {
|
||||
else if (option == "--scenario") scenario_name = argv[++i];
|
||||
else if (option == "--turbo") {
|
||||
const std::string value = argv[++i];
|
||||
if (value != "none" && value != "vz21") { std::cerr << "Choose none or vz21 turbo\n"; return 2; }
|
||||
turbo_enabled = value == "vz21";
|
||||
if (value != "none" && value != "vz21" && value != "gt17") { std::cerr << "Choose none, vz21 or gt17 turbo\n"; return 2; }
|
||||
turbo_name = value;
|
||||
turbo_enabled = value != "none";
|
||||
}
|
||||
else if (option == "--exhaust") {
|
||||
const std::string value = argv[++i];
|
||||
@@ -35,14 +37,19 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
if (turbo_enabled && scenario_name != "twin") { std::cerr << "The turbo test preset uses --scenario twin\n"; return 2; }
|
||||
if (turbo_name.empty() && scenario_name == "b205") turbo_enabled = true;
|
||||
if ((!turbo_name.empty() && turbo_name != "none" &&
|
||||
!((turbo_name == "gt17" && scenario_name == "b205") || (turbo_name == "vz21" && scenario_name == "twin"))) ||
|
||||
(turbo_enabled && scenario_name != "twin" && scenario_name != "b205")) {
|
||||
std::cerr << "Use gt17 with b205 or vz21 with twin\n"; return 2;
|
||||
}
|
||||
constexpr int sample_rate = 44100;
|
||||
const auto total_samples = static_cast<std::uint64_t>(duration_seconds * sample_rate);
|
||||
const auto report_interval = static_cast<std::uint64_t>(sample_rate / 10);
|
||||
if (scenario_name == "twin" || scenario_name == "b205") {
|
||||
FourStrokeScenario scenario(sample_rate, scenario_name == "b205" ? FourStrokePreset::SaabB205 : FourStrokePreset::Twin, turbo_enabled);
|
||||
scenario.throttle = throttle;
|
||||
std::cout << (scenario_name == "b205" ? "FluidSimCpp | Saab B205 / 9-5 wagon (no turbo) | throttle " : "FluidSimCpp | 600 cc parallel twin | throttle ") << std::fixed << std::setprecision(0)
|
||||
std::cout << (scenario_name == "b205" ? "FluidSimCpp | Saab B205 / 9-5 wagon | throttle " : "FluidSimCpp | 600 cc parallel twin | throttle ") << std::fixed << std::setprecision(0)
|
||||
<< throttle * 100.0f << "%\n";
|
||||
for (std::uint64_t i = 0; i < total_samples; ++i) {
|
||||
scenario.process();
|
||||
|
||||
@@ -81,7 +81,8 @@ FourStrokeScenario::FourStrokeScenario(int sample_rate, FourStrokePreset selecte
|
||||
solver_.add_component(intake_plenum);
|
||||
solver_.add_component(exhaust_collector);
|
||||
if (turbo_enabled) {
|
||||
turbo = std::make_unique<Turbocharger>();
|
||||
turbo = std::make_unique<Turbocharger>(saab ? TurboConfig::gt17() : TurboConfig{});
|
||||
ecu.boost_control_enabled = saab;
|
||||
const int fresh = 2+2*count, exhaust_exit = fresh+1;
|
||||
boundaries_.add_orifice(intake_atmosphere.port, fresh, true, intake_boundary_area_);
|
||||
turbo->connect(boundaries_, pipes, fresh, false, 0, true, 1+2*count, false, exhaust_exit, true);
|
||||
@@ -109,6 +110,10 @@ AudioFrame FourStrokeScenario::process() {
|
||||
const std::lock_guard guard(mutex_);
|
||||
step_motorcycle(crankshaft, dt_, preset == FourStrokePreset::SaabB205 ? 200.f : 30.f);
|
||||
ecu.step(dt_, throttle, crankshaft.omega * 60 / (2*pi));
|
||||
if (turbo) {
|
||||
ecu.control_boost(dt_, throttle, crankshaft.omega * 60/(2*pi), intake_plenum.pressure(), turbo->compressor_outlet.pressure());
|
||||
turbo->set_wastegate_duty(ecu.wastegate_duty());
|
||||
}
|
||||
const auto engines = cylinders();
|
||||
for (int i = 0; i < cylinder_count(); ++i) {
|
||||
auto& c = *engines[i];
|
||||
@@ -180,6 +185,8 @@ ScenarioSnapshot FourStrokeScenario::snapshot() const {
|
||||
const std::lock_guard<std::mutex> guard(mutex_);
|
||||
ScenarioSnapshot result;
|
||||
result.turbo_enabled = bool(turbo);
|
||||
result.boost_target = ecu.boost_target();
|
||||
result.wastegate_duty = ecu.wastegate_duty();
|
||||
if (turbo) result.turbo = turbo->snapshot();
|
||||
result.solver_substeps = solver_.substep_count();
|
||||
result.boundary_iterations = boundaries_.nonlinear_iterations;
|
||||
@@ -240,7 +247,7 @@ std::vector<Pipe1D> FourStrokeScenario::create_pipes(FourStrokePreset preset, bo
|
||||
result.emplace_back(area_for_diameter(saab ? .032f : .0275f), saab ? .25f : .12f, 10);
|
||||
for (int i = 0; i < count; ++i)
|
||||
result.emplace_back(area_for_diameter(saab ? .034f : .028f), saab ? .28f : .20f, saab ? 10 : 6);
|
||||
result.emplace_back(area_for_diameter(saab ? .060f : .028f), turbo_enabled ? .12f : (saab ? 1.4f : .40f), saab ? 40 : 10);
|
||||
result.emplace_back(area_for_diameter(saab ? .060f : .028f), turbo_enabled ? .12f : (saab ? 1.4f : .40f), saab ? (turbo_enabled ? 8 : 40) : 10);
|
||||
if (turbo_enabled) {
|
||||
result.emplace_back(area_for_diameter(saab ? .060f : .0275f), .10f, 8);
|
||||
result.emplace_back(area_for_diameter(saab ? .060f : .032f), .60f, 24);
|
||||
|
||||
@@ -22,6 +22,26 @@ TurboConfig checked(TurboConfig c) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
TurboConfig TurboConfig::gt17() {
|
||||
TurboConfig c;
|
||||
c.shaft_inertia = 2.0e-5;
|
||||
c.compressor_radius = .026;
|
||||
c.turbine_radius = .019;
|
||||
c.compressor_efficiency = .70;
|
||||
c.turbine_peak_efficiency = .70;
|
||||
c.compressor_effective_area = 420e-6;
|
||||
c.turbine_effective_area = 350e-6;
|
||||
c.bearing_viscous = 2e-7;
|
||||
c.windage = 5e-11;
|
||||
c.gate_diaphragm_area = .001;
|
||||
c.gate_spring_preload = 25;
|
||||
c.gate_diameter = .024;
|
||||
c.gate_maximum_lift = .007;
|
||||
c.compressor_inlet_volume = c.compressor_outlet_volume = 100e-6f;
|
||||
c.turbine_inlet_volume = c.turbine_outlet_volume = 100e-6f;
|
||||
c.connection_diameters = {.045f, .045f, .040f, .050f};
|
||||
return c;
|
||||
}
|
||||
Turbocharger::Turbocharger(TurboConfig configuration)
|
||||
: config(checked(configuration)),
|
||||
compressor_inlet(config.compressor_inlet_volume), compressor_outlet(config.compressor_outlet_volume),
|
||||
@@ -114,7 +134,7 @@ void Turbocharger::update_state(float timestep) {
|
||||
|
||||
const double tp = turbine_inlet.pressure(), tout = turbine_outlet.pressure();
|
||||
const double can_force = std::max(0., double(compressor_outlet.pressure())-config.reference_pressure)*
|
||||
config.gate_diaphragm_area;
|
||||
config.gate_diaphragm_area*(1-gate_duty_);
|
||||
const double equilibrium_lift = (can_force-config.gate_spring_preload)/config.gate_spring_stiffness;
|
||||
// Overdamped spring-can linkage: b*dx/dt + k*x = F-Fpreload, with seats.
|
||||
wastegate_lift_ = std::clamp(equilibrium_lift+(wastegate_lift_-equilibrium_lift)*
|
||||
|
||||
@@ -48,6 +48,23 @@ int main() {
|
||||
std::cout << "FAIL " << n << ": " << e.what() << '\n';
|
||||
}
|
||||
};
|
||||
test("tracer underflow preserves bulk gas and normal concentrations", [] {
|
||||
for (float fraction : {1e-40f, 1e-30f, .5f}) {
|
||||
Pipe1D p(.001f, 1, 8);
|
||||
for (int i=0; i<8; ++i) set(p, i, 101325, 1.2f, 0, fraction);
|
||||
p.left_ghost = p.state(0);
|
||||
p.right_ghost = p.state(7);
|
||||
const double before_mass = mass(p), before_energy = energy(p);
|
||||
p.advance(1e-6f);
|
||||
near(mass(p), before_mass, 0, "tracer truncation changed total mass");
|
||||
near(energy(p), before_energy, 0, "tracer truncation changed energy");
|
||||
for (auto cell : p.cells) {
|
||||
check(std::fpclassify(cell.air) != FP_SUBNORMAL, "subnormal tracer survived");
|
||||
near(cell.air, fraction < std::numeric_limits<float>::min() ? 0 : fraction,
|
||||
fraction * 1e-6, "normal tracer concentration changed");
|
||||
}
|
||||
}
|
||||
});
|
||||
test("invalid uniform geometry", [] {
|
||||
bool caught = false;
|
||||
try {
|
||||
|
||||
46
tests/saab_turbo_regression.cpp
Normal file
46
tests/saab_turbo_regression.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "FluidSim/Scenario.hpp"
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
using namespace fluidsim::port;
|
||||
void check(bool ok, const char* message) { if (!ok) throw std::runtime_error(message); }
|
||||
int main() {
|
||||
Ecu ecu;
|
||||
ecu.boost_control_enabled = true;
|
||||
ecu.step(.001f, 1, 3500);
|
||||
for (int i=0;i<1000;++i) ecu.control_boost(.001f,1,3500,110000,115000);
|
||||
check(ecu.wastegate_duty()>0 && ecu.wastegate_duty()<=.85f,"no spool duty");
|
||||
ecu.control_boost(.001f,1,3500,190000,190000);
|
||||
check(ecu.fuel_cut() && ecu.wastegate_duty()==0,"overboost protection failed");
|
||||
ecu.control_boost(.001f,1,3500,140000,140000);
|
||||
check(!ecu.fuel_cut(),"overboost recovery failed");
|
||||
ecu.control_boost(.001f,0,3500,100000,100000);
|
||||
check(ecu.wastegate_duty()==0 && ecu.boost_target()==0,"lift-off did not restore spring control");
|
||||
ecu.control_boost(.001f,1,3500,NAN,100000);
|
||||
check(ecu.fuel_cut() && ecu.wastegate_duty()==0,"boost sensor fail-safe failed");
|
||||
FourStrokeScenario s(44100,FourStrokePreset::SaabB205,true);
|
||||
check(s.pipes.size()==12 && s.turbo && s.ecu.boost_control_enabled,"Saab turbo topology missing");
|
||||
double peak_rpm=0, peak_map=0, peak_audio=0, settled_pressure=0;
|
||||
for(int second=0;second<10;++second) {
|
||||
for(int i=0;i<44100;++i) {
|
||||
s.throttle = second>=1 && second<7 ? 1.f : 0.f;
|
||||
if(second<7) s.crankshaft.omega=3500*2*pi/60;
|
||||
const auto a=s.process();
|
||||
if(second>=4 && second<7) settled_pressure+=s.intake_plenum.pressure()/(3.*44100);
|
||||
check(std::isfinite(a.left) && std::isfinite(a.right),"nonfinite audio");
|
||||
peak_audio=std::max(peak_audio,double(std::abs(a.left)));
|
||||
}
|
||||
auto t=s.turbo->snapshot();
|
||||
peak_rpm=std::max(peak_rpm,t.rpm);
|
||||
peak_map=std::max(peak_map,double(s.intake_plenum.pressure()));
|
||||
check(std::isfinite(t.rpm) && std::abs(t.energy_residual)<.1,"turbo energy balance failed");
|
||||
check(t.limited_transfers==0,"housing donor limit hit");
|
||||
std::cout<<second+1<<" MAP="<<s.intake_plenum.pressure()/1000<<" charge="<<t.charge_pressure/1000
|
||||
<<" rpm="<<t.rpm<<" duty="<<s.ecu.wastegate_duty()<<" gate_mm="<<t.wastegate_lift*1000<<'\n';
|
||||
}
|
||||
check(peak_rpm>50000 && peak_map>110000,"GT17 failed to spool/boost");
|
||||
check(peak_audio<1,"audio exceeds monitoring range");
|
||||
check(std::abs(settled_pressure-146325)<8000,"boost did not settle near target");
|
||||
check(s.ecu.wastegate_duty()==0 && s.turbo->snapshot().rpm<peak_rpm,"lift-off control/spool-down failed");
|
||||
for(auto& p:s.pipes) check(p.positivity_repairs==0,"pipe state repaired");
|
||||
}
|
||||
@@ -99,6 +99,7 @@ int main(int argc, char **argv) {
|
||||
float seconds = 6, pedal = 1;
|
||||
TwoStrokeConfig config;
|
||||
bool turbo_enabled = false;
|
||||
std::string turbo_name;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::string key = argv[i];
|
||||
if (i + 1 >= argc)
|
||||
@@ -113,8 +114,9 @@ int main(int argc, char **argv) {
|
||||
else if (key == "--throttle")
|
||||
pedal = std::stof(value);
|
||||
else if (key == "--turbo") {
|
||||
if (value != "none" && value != "vz21") throw std::runtime_error("choose none or vz21 turbo");
|
||||
turbo_enabled = value == "vz21";
|
||||
if (value != "none" && value != "vz21" && value != "gt17") throw std::runtime_error("choose none, vz21 or gt17 turbo");
|
||||
turbo_name = value;
|
||||
turbo_enabled = value != "none";
|
||||
}
|
||||
else if (key == "--exhaust") {
|
||||
if (value == "racing") config.exhaust = TwoStrokeExhaust::Racing;
|
||||
@@ -143,11 +145,16 @@ int main(int argc, char **argv) {
|
||||
if (!std::filesystem::path(prefix).parent_path().empty())
|
||||
std::filesystem::create_directories(std::filesystem::path(prefix).parent_path());
|
||||
const int frames = int(std::lround(seconds * 44100));
|
||||
if (turbo_enabled && scenario != "twin") throw std::runtime_error("turbo test uses the twin scenario");
|
||||
if (turbo_name.empty() && scenario == "b205") turbo_enabled = true;
|
||||
if (!turbo_name.empty() && turbo_name!="none" &&
|
||||
!((turbo_name=="vz21" && scenario=="twin") || (turbo_name=="gt17" && scenario=="b205")))
|
||||
throw std::runtime_error("use gt17 with b205 or vz21 with twin");
|
||||
if (scenario == "twin" && turbo_enabled)
|
||||
capture<TurboTwinScenario>(prefix, frames, pedal, selected, config);
|
||||
else if (scenario == "twin")
|
||||
capture<FourStrokeTwinScenario>(prefix, frames, pedal, selected, config);
|
||||
else if (scenario == "b205" && turbo_enabled)
|
||||
capture<SaabTurboScenario>(prefix, frames, pedal, selected, config);
|
||||
else if (scenario == "b205")
|
||||
capture<SaabB205Scenario>(prefix, frames, pedal, selected, config);
|
||||
else if (scenario == "two-stroke")
|
||||
|
||||
75
tools/scenario_benchmark.cpp
Normal file
75
tools/scenario_benchmark.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "FluidSim/Scenario.hpp"
|
||||
#include "FluidSim/TwoStrokeScenario.hpp"
|
||||
#include "FluidSim/HelmholtzScenario.hpp"
|
||||
#include "FluidSim/PulseTestScenario.hpp"
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
using namespace fluidsim::port;
|
||||
template<class S, class Control> void run(const char* name, S& s, int seconds, Control control) {
|
||||
double checksum = 0;
|
||||
std::uint64_t previous_iterations = 0;
|
||||
for (int second = 0; second < seconds; ++second) {
|
||||
const auto begin = std::chrono::steady_clock::now();
|
||||
for (int i = 0; i < 44100; ++i) {
|
||||
control(second);
|
||||
auto value = s.process();
|
||||
if constexpr (requires { value.left; }) checksum += value.left;
|
||||
else checksum += value;
|
||||
}
|
||||
const double elapsed = std::chrono::duration<double>(std::chrono::steady_clock::now()-begin).count();
|
||||
std::cout << name << ',' << second+1 << ',' << elapsed << ',' << checksum << std::endl;
|
||||
if constexpr (requires { s.pipes; }) {
|
||||
unsigned tiny = 0;
|
||||
for (const auto& pipe : s.pipes)
|
||||
for (const auto& cell : pipe.cells)
|
||||
for (float value : {cell.rho, cell.momentum, cell.energy, cell.air})
|
||||
tiny += std::fpclassify(value) == FP_SUBNORMAL;
|
||||
std::cerr << name << " second=" << second+1 << " subnormal_cell_fields=" << tiny << '\n';
|
||||
}
|
||||
if constexpr (requires { s.snapshot().boundary_iterations; }) {
|
||||
const auto state = s.snapshot();
|
||||
std::cerr << name << " iterations_per_frame="
|
||||
<< (state.boundary_iterations-previous_iterations)/44100.0 << '\n';
|
||||
previous_iterations = state.boundary_iterations;
|
||||
}
|
||||
}
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
const int seconds = argc > 1 ? std::stoi(argv[1]) : 6;
|
||||
const std::string mode = argc > 2 ? argv[2] : "pedal";
|
||||
const std::string only = argc > 3 ? argv[3] : "all";
|
||||
auto pedal = [&](int second) {
|
||||
return mode == "idle" ? 0.0f : mode == "transient" && (second == 0 || second >= seconds-2) ? 0.0f : .7f;
|
||||
};
|
||||
std::cout << "scenario,second,wall_seconds,checksum\n";
|
||||
for (auto name : {"twin", "turbo", "b205", "b205-gt17"}) {
|
||||
if (only != "all" && only != name) continue;
|
||||
auto s = std::make_unique<FourStrokeScenario>(44100,
|
||||
std::string(name).starts_with("b205") ? FourStrokePreset::SaabB205 : FourStrokePreset::Twin,
|
||||
std::string(name)=="turbo" || std::string(name)=="b205-gt17");
|
||||
s->throttle = .7f;
|
||||
run(name, *s, seconds, [&](int second) {
|
||||
s->throttle = pedal(second);
|
||||
if (mode == "loaded") s->crankshaft.omega = (std::string(name)=="b205-gt17" ? 5500 : 7000) * 2*pi/60;
|
||||
});
|
||||
}
|
||||
for (bool racing : {true, false}) {
|
||||
if (only != "all" && only != (racing ? "two-stroke-racing" : "two-stroke-straight")) continue;
|
||||
TwoStrokeConfig config;
|
||||
config.exhaust = racing ? TwoStrokeExhaust::Racing : TwoStrokeExhaust::Straight;
|
||||
TwoStrokeScenario s(44100, config);
|
||||
s.set_throttle(.7f);
|
||||
run(racing ? "two-stroke-racing" : "two-stroke-straight", s, seconds, [&](int second) {
|
||||
s.set_throttle(pedal(second));
|
||||
if (mode == "loaded") s.crankshaft.omega = 10000 * 2*pi/60;
|
||||
});
|
||||
}
|
||||
if (only == "all" || only == "helmholtz") {
|
||||
HelmholtzScenario helmholtz; run("helmholtz", helmholtz, seconds, [](int){});
|
||||
}
|
||||
if (only == "all" || only == "pulse") {
|
||||
PulseTestScenario pulse; run("pulse", pulse, seconds, [](int){});
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,37 @@
|
||||
#include "FluidSim/Fluid.hpp"
|
||||
#include "FluidSim/Scenario.hpp"
|
||||
#include "FluidSim/TwoStrokeScenario.hpp"
|
||||
#include "FluidSim/HelmholtzScenario.hpp"
|
||||
#include "FluidSim/PulseTestScenario.hpp"
|
||||
#include <barrier>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
using namespace fluidsim::port;
|
||||
int main() {
|
||||
for (auto size : {std::pair{6, 10}, std::pair{64, 256}}) {
|
||||
const int steps = 1000;
|
||||
for (std::string name : {"twin", "turbo", "b205", "two-stroke-racing", "two-stroke-straight", "helmholtz", "pulse", "large"}) {
|
||||
std::vector<Pipe1D> geometry;
|
||||
if (name == "large") {
|
||||
for (int i=0; i<64; ++i) geometry.emplace_back(.001f, 2, 256);
|
||||
} else if (name == "helmholtz") {
|
||||
HelmholtzScenario s; geometry.push_back(s.neck());
|
||||
} else if (name == "pulse") {
|
||||
PulseTestScenario s; geometry.push_back(s.pipe());
|
||||
} else if (name.starts_with("two-stroke")) {
|
||||
TwoStrokeConfig config;
|
||||
config.exhaust = name == "two-stroke-straight" ? TwoStrokeExhaust::Straight : TwoStrokeExhaust::Racing;
|
||||
TwoStrokeScenario s(44100, config); geometry = s.pipes;
|
||||
} else {
|
||||
FourStrokeScenario s(44100, name == "b205" ? FourStrokePreset::SaabB205 : FourStrokePreset::Twin, name == "turbo");
|
||||
geometry = s.pipes;
|
||||
}
|
||||
const int steps = 4000;
|
||||
for (int workers : {1, 2, 4}) {
|
||||
std::vector<Pipe1D> p;
|
||||
for (int i = 0; i < size.first; i++)
|
||||
p.emplace_back(.001f, 2, size.second);
|
||||
auto p = geometry;
|
||||
auto advance = [&](int worker) {
|
||||
for (int k = worker; k < size.first; k += workers) {
|
||||
for (int k = worker; k < static_cast<int>(p.size()); k += workers) {
|
||||
auto &a = p[k];
|
||||
auto l = a.state(0), r = a.state(size.second - 1);
|
||||
auto l = a.state(0), r = a.state(static_cast<int>(a.cells.size()) - 1);
|
||||
l.velocity = -l.velocity;
|
||||
r.velocity = -r.velocity;
|
||||
a.left_ghost = l;
|
||||
@@ -47,7 +64,7 @@ int main() {
|
||||
double sum = 0;
|
||||
for (auto &q : p)
|
||||
sum += q.state(0).pressure;
|
||||
std::cout << "pipes=" << size.first << " cells/pipe=" << size.second << " workers=" << workers
|
||||
std::cout << "scenario=" << name << " pipes=" << p.size() << " workers=" << workers
|
||||
<< " steps=" << steps << " seconds=" << sec << " checksum=" << sum << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
109
verification/OPTIMIZATION.md
Normal file
109
verification/OPTIMIZATION.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Solver optimization audit
|
||||
|
||||
Measured on an Intel Core i5-12600K, Linux, GCC 16.2.1, Release (`-O3`,
|
||||
no fast-math). Reference is commit `589d22a`. Performance results are specific
|
||||
to this machine; Windows/MSVC runtime measurements remain pending. The retained
|
||||
changes use portable C++ and compiler vectorization, with no new CPU requirement.
|
||||
|
||||
## Retained changes
|
||||
|
||||
* Boundary solves start from the previous converged face pressure when it is
|
||||
inside the new physical bracket. Otherwise they start at the bracket midpoint.
|
||||
The safeguarded Newton solver, residual tolerance, iteration cap, choking,
|
||||
reverse flow, donor budgets and inertance calculation remain unchanged.
|
||||
* Pipe preparation computes primitive states and wave speeds in an independent
|
||||
loop, then validates states and reduces the CFL timestep. GCC confirms 128-bit
|
||||
vectorization of the arithmetic loop. Invalid states still throw before flux
|
||||
updates. No approximate reciprocal/square root or relaxed arithmetic is used.
|
||||
* Pipe fresh-air tracer fractions smaller than the smallest **normal** float
|
||||
(approximately 1.175e-38) are rounded to zero. Previously, purged intake/exhaust
|
||||
tracer tails persisted as subnormals, causing severe sustained-load slowdown.
|
||||
This affects species attribution below that precision, not total density,
|
||||
momentum or energy. The regression suite checks bulk conservation and retention
|
||||
of normal tracer concentrations. Global flush-to-zero modes are not enabled.
|
||||
|
||||
Starting guesses change numerical trajectories within the existing convergence
|
||||
tolerance; long engine/audio traces need not be bit-identical to the reference.
|
||||
|
||||
## Profiling and experiments
|
||||
|
||||
A `-pg` build running every scenario for two simulated seconds attributed about
|
||||
39% of sampled executable time to pipe advancement, 38% to orifice boundary
|
||||
solves, and 13% to Solver::step (including inlined preparation). Turbo mechanics
|
||||
were under 1% and outdoor emitter rendering about 1%. These are sampled gprof
|
||||
results, not precise attribution of time inside dynamically linked math functions.
|
||||
|
||||
`fluidsim_thread_benchmark` now uses each scenario's actual pipe geometry and
|
||||
compares persistent 1/2/4-worker execution with barriers per substep. This isolates
|
||||
the parallelizable pipe work; boundary/component work would remain serial. Every
|
||||
current scenario loses with workers, so production remains serial. The synthetic
|
||||
64-pipe, 256-cells-per-pipe case benefits from workers, confirming that this
|
||||
strategy has a useful scale threshold. It does not justify adding its scheduling
|
||||
and synchronization cost to the current small graphs.
|
||||
|
||||
SIMD-disabled and `-march=native` builds are comparison experiments. Native
|
||||
compilation is not enabled in the project defaults, since the executable could
|
||||
then require instructions missing on another machine.
|
||||
|
||||
## Results
|
||||
|
||||
Mean wall seconds per simulated second, six-second sustained-load runs:
|
||||
|
||||
| Scenario | Reference | Optimized | Time reduction | SIMD disabled |
|
||||
|---|---:|---:|---:|---:|
|
||||
| Twin | .528 | .405 | 23% | .423 |
|
||||
| Turbo twin | 1.368 | .649 | 53% | .684 |
|
||||
| B205 | .884 | .689 | 22% | .737 |
|
||||
| Two-stroke racing | .561 | .470 | 16% | .535 |
|
||||
| Two-stroke straight | .539 | .464 | 14% | .525 |
|
||||
| Helmholtz | .167 | .141 | 16% | .160 |
|
||||
| Pulse | .256 | .238 | 7% | .315 |
|
||||
|
||||
Idle/transient optimized means (seconds per simulated second): twin .394/.399,
|
||||
turbo .627/.651, B205 .666/.683, racing two-stroke .450/.459, straight two-stroke
|
||||
.452/.453, Helmholtz .141/.140, and pulse .238/.238.
|
||||
|
||||
The pulse scenario has no orifice, so its improvement isolates the SIMD-friendly
|
||||
preparation change. Disabling SIMD increases time in every scenario. An optional
|
||||
native-instruction build improves some timings further, but is not shipped as
|
||||
the default: FMA also changes rounding and the binary is CPU-specific.
|
||||
|
||||
Initial isolated changes measured approximately .40 seconds for the twin after
|
||||
boundary warm starts alone (previously .53). The sustained turbo still took
|
||||
about 1.2 seconds after that change; eliminating subnormal tracer tails brought
|
||||
it to about .65. The diagnostic found 22 subnormal pipe fields before truncation
|
||||
and zero afterwards. This is distinct from reducing CFL substeps or geometry;
|
||||
neither was changed. Six-second idle and throttle/release runs also complete
|
||||
for every scenario. These are finite test windows, not a guarantee of real-time
|
||||
performance for every user configuration or arbitrarily long simulation.
|
||||
|
||||
## Reproduction
|
||||
|
||||
Final validation: all nine CTest suites passed both with SIMD enabled (28.50 s)
|
||||
and disabled (30.86 s). The fluid validation executable includes 30 checks,
|
||||
including tracer underflow conservation. The Release SFML desktop target also
|
||||
rebuilt successfully. This audit verifies desktop compilation and headless audio
|
||||
rendering; interactive playback underrun testing remains a separate user check.
|
||||
|
||||
```sh
|
||||
cmake -S . -B build-opt -DCMAKE_BUILD_TYPE=Release -DFLUIDSIM_BUILD_DESKTOP=OFF
|
||||
cmake --build build-opt -j
|
||||
ctest --test-dir build-opt --output-on-failure
|
||||
./build-opt/fluidsim_scenario_benchmark 6 loaded
|
||||
./build-opt/fluidsim_scenario_benchmark 6 idle
|
||||
./build-opt/fluidsim_scenario_benchmark 6 transient
|
||||
./build-opt/fluidsim_thread_benchmark
|
||||
```
|
||||
|
||||
The scenario benchmark runs twin, turbo twin, B205, racing and straight-pipe
|
||||
two-strokes, Helmholtz and pulse scenarios, including their normal audio path.
|
||||
`loaded` holds four-strokes at 7,000 RPM and two-strokes at 10,000 RPM using an
|
||||
ideal speed-holding dyno; engine throttle is 70%. `idle` releases the pedal;
|
||||
`transient` starts released, applies 70%, then releases for the last two seconds.
|
||||
The optional final argument selects one scenario, e.g. `6 loaded turbo`.
|
||||
CSV timing/checksum goes to stdout; subnormal and iteration diagnostics go to
|
||||
stderr. Inspection happens outside the timed sample-processing loop.
|
||||
|
||||
Use `-DFLUIDSIM_ENABLE_SIMD=OFF` in a separate build for scalar comparisons.
|
||||
Run timed experiments sequentially, without concurrent builds or simulations.
|
||||
The raw final measurements are retained in `verification/optimization/`.
|
||||
46
verification/SAAB_GT17.md
Normal file
46
verification/SAAB_GT17.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Saab B205 with GT17 and ECU boost control
|
||||
|
||||
The desktop Saab menu entry and `--scenario b205` now select an estimated GT1752
|
||||
turbo configuration. `--turbo gt17` makes that choice explicit; `--turbo none`
|
||||
selects the previous naturally aspirated baseline. CLI and WAV capture follow
|
||||
the same defaults. `SaabB205Scenario` preserves its baseline API;
|
||||
`SaabTurboScenario` is the boosted convenience class.
|
||||
|
||||
The GT17 calibration uses a 26 mm compressor tip radius, 19 mm effective turbine
|
||||
radius, 2e-5 kg m² rotor inertia, 420/350 mm² effective compressor/turbine areas,
|
||||
70% efficiencies, 100 cc housing volumes and a 24 mm wastegate. These are model
|
||||
estimates, not a measured Saab map or verified rotor inertia. The Garrett catalog
|
||||
identifies the Saab GT1752 application:
|
||||
https://www.turbomaster.info/eng/downloads/catalog_garrett.pdf
|
||||
|
||||
The ECU requests up to 45 kPa gauge boost, ramping with pedal and RPM. A PI
|
||||
controller uses manifold pressure filtered over 50 ms, conditional integration,
|
||||
and bounded pneumatic bleed duty (0–85%). Duty reduces the pressure signal to
|
||||
the existing spring/diaphragm actuator. Actual valve travel remains damped and
|
||||
boost emerges from the physical rotor, restrictions and conserved gas transfers.
|
||||
Zero duty restores the mechanical pressure-can response; it does not forcibly
|
||||
open the valve or impose a manifold pressure. Targets below spring boost cannot
|
||||
be achieved by wastegate bleed alone.
|
||||
|
||||
Lift-off, fuel cut and invalid sensor data request zero duty and clear the PI
|
||||
integral. Invalid boost sensors cut fuel. Manifold or charge pressure above
|
||||
75 kPa gauge triggers fuel cut, recovering below 55 kPa gauge. This is a basic
|
||||
estimated safety calibration, not a reproduction of Saab Trionic software.
|
||||
No intercooler, compressor surge/BOV model or knock model has been added;
|
||||
charge heating and exhaust backpressure remain present.
|
||||
|
||||
The regression holds the engine at 3,500 RPM, applies full pedal for six seconds,
|
||||
then releases for three. It checks boost settling within 8 kPa of the 45 kPa
|
||||
target, shaft spool-up/down, finite audio, no pipe positivity repairs, no housing
|
||||
donor limiting, and gas/rotor energy residual below 0.1 J. Controller checks cover
|
||||
overboost, recovery, pedal release and an invalid sensor. The HUD shows target
|
||||
gauge boost, actuator bleed duty, turbo RPM and absolute gas pressures.
|
||||
|
||||
```sh
|
||||
cmake --build build-desktop --target fluidsim_desktop -j4
|
||||
./build-desktop/fluidsim_desktop --scenario b205 --turbo gt17
|
||||
./build-audit/fluidsim_scenario_benchmark 6 loaded b205-gt17
|
||||
```
|
||||
|
||||
All ten CTest suites pass, including the new ten-second Saab turbo regression.
|
||||
The GT17 benchmark holds 5,500 RPM, below the Saab's 6,500 RPM limiter.
|
||||
@@ -88,11 +88,13 @@ shaft power. There is no forced power gain. Effective area/efficiency, gas
|
||||
properties and the base engine's approximate combustion/overlap affect these
|
||||
numbers strongly. They are prototype comparisons, not real engine predictions.
|
||||
|
||||
The benchmark used four solver substeps per output frame. The turbo cost .81
|
||||
The original benchmark used four solver substeps per output frame. The turbo cost .81
|
||||
CPU seconds per simulated second at 4000 RPM and 1.28 at 7000 RPM, versus .53
|
||||
for the unboosted twin. Sustained high-load real-time playback is an open issue;
|
||||
monitor underruns. The mixed transient cost .84 wall seconds per simulated
|
||||
second. Tests run headlessly; latest Windows runtime is unverified.
|
||||
second. The subsequent [optimization audit](OPTIMIZATION.md) resolves the
|
||||
subnormal-tracer slowdown and measures about .65 seconds per simulated second
|
||||
in its 7,000-RPM workload. Tests run headlessly; latest Windows runtime is unverified.
|
||||
|
||||
## Run
|
||||
|
||||
|
||||
30
verification/optimization/baseline-loaded-diagnostics.txt
Normal file
30
verification/optimization/baseline-loaded-diagnostics.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
twin second=1 subnormal_cell_fields=0
|
||||
twin second=2 subnormal_cell_fields=0
|
||||
twin second=3 subnormal_cell_fields=0
|
||||
twin second=4 subnormal_cell_fields=0
|
||||
twin second=5 subnormal_cell_fields=0
|
||||
twin second=6 subnormal_cell_fields=0
|
||||
turbo second=1 subnormal_cell_fields=22
|
||||
turbo second=2 subnormal_cell_fields=22
|
||||
turbo second=3 subnormal_cell_fields=22
|
||||
turbo second=4 subnormal_cell_fields=22
|
||||
turbo second=5 subnormal_cell_fields=22
|
||||
turbo second=6 subnormal_cell_fields=22
|
||||
b205 second=1 subnormal_cell_fields=0
|
||||
b205 second=2 subnormal_cell_fields=0
|
||||
b205 second=3 subnormal_cell_fields=0
|
||||
b205 second=4 subnormal_cell_fields=0
|
||||
b205 second=5 subnormal_cell_fields=0
|
||||
b205 second=6 subnormal_cell_fields=0
|
||||
two-stroke-racing second=1 subnormal_cell_fields=0
|
||||
two-stroke-racing second=2 subnormal_cell_fields=0
|
||||
two-stroke-racing second=3 subnormal_cell_fields=0
|
||||
two-stroke-racing second=4 subnormal_cell_fields=0
|
||||
two-stroke-racing second=5 subnormal_cell_fields=0
|
||||
two-stroke-racing second=6 subnormal_cell_fields=0
|
||||
two-stroke-straight second=1 subnormal_cell_fields=0
|
||||
two-stroke-straight second=2 subnormal_cell_fields=0
|
||||
two-stroke-straight second=3 subnormal_cell_fields=0
|
||||
two-stroke-straight second=4 subnormal_cell_fields=0
|
||||
two-stroke-straight second=5 subnormal_cell_fields=0
|
||||
two-stroke-straight second=6 subnormal_cell_fields=0
|
||||
43
verification/optimization/baseline-loaded.csv
Normal file
43
verification/optimization/baseline-loaded.csv
Normal file
@@ -0,0 +1,43 @@
|
||||
scenario,second,wall_seconds,checksum
|
||||
twin,1,0.541263,-0.474995
|
||||
twin,2,0.528657,0.56663
|
||||
twin,3,0.5197,-0.445512
|
||||
twin,4,0.524947,-0.457089
|
||||
twin,5,0.525219,0.543696
|
||||
twin,6,0.525349,-0.453353
|
||||
turbo,1,1.15992,-0.310561
|
||||
turbo,2,1.40615,0.239385
|
||||
turbo,3,1.41159,0.0378158
|
||||
turbo,4,1.40703,-0.317772
|
||||
turbo,5,1.40288,0.217977
|
||||
turbo,6,1.42287,0.0202671
|
||||
b205,1,0.89491,0.37201
|
||||
b205,2,0.892261,-0.672984
|
||||
b205,3,0.879947,-0.0819311
|
||||
b205,4,0.87503,0.383653
|
||||
b205,5,0.879982,-0.660539
|
||||
b205,6,0.880262,-0.105939
|
||||
two-stroke-racing,1,0.559599,0.0799002
|
||||
two-stroke-racing,2,0.557103,-0.446533
|
||||
two-stroke-racing,3,0.562561,-0.0135526
|
||||
two-stroke-racing,4,0.56292,0.0502098
|
||||
two-stroke-racing,5,0.566538,-0.436311
|
||||
two-stroke-racing,6,0.556811,0.0131825
|
||||
two-stroke-straight,1,0.54203,0.451678
|
||||
two-stroke-straight,2,0.53757,-0.576794
|
||||
two-stroke-straight,3,0.539195,0.301482
|
||||
two-stroke-straight,4,0.537166,0.436597
|
||||
two-stroke-straight,5,0.538783,-0.56488
|
||||
two-stroke-straight,6,0.539518,0.317271
|
||||
helmholtz,1,0.16266,0.000610898
|
||||
helmholtz,2,0.156802,0.000204372
|
||||
helmholtz,3,0.161843,-9.63693e-05
|
||||
helmholtz,4,0.175722,4.28612e-07
|
||||
helmholtz,5,0.173455,4.28612e-07
|
||||
helmholtz,6,0.17374,4.28612e-07
|
||||
pulse,1,0.256065,0.155302
|
||||
pulse,2,0.25603,-0.0240824
|
||||
pulse,3,0.256108,-0.00420275
|
||||
pulse,4,0.255712,0.00691116
|
||||
pulse,5,0.255998,-0.00446426
|
||||
pulse,6,0.256098,0.00211677
|
||||
|
43
verification/optimization/final-idle.csv
Normal file
43
verification/optimization/final-idle.csv
Normal file
@@ -0,0 +1,43 @@
|
||||
scenario,second,wall_seconds,checksum
|
||||
twin,1,0.39941,-0.0283469
|
||||
twin,2,0.39433,0.0344893
|
||||
twin,3,0.392258,0.0739791
|
||||
twin,4,0.39095,0.0786597
|
||||
twin,5,0.392216,-0.0207043
|
||||
twin,6,0.393483,-0.195189
|
||||
turbo,1,0.660359,-0.0302299
|
||||
turbo,2,0.618997,-0.0283187
|
||||
turbo,3,0.616863,-0.0501136
|
||||
turbo,4,0.622639,0.00249347
|
||||
turbo,5,0.622078,-0.0029317
|
||||
turbo,6,0.619506,0.0828663
|
||||
b205,1,0.668236,0.274864
|
||||
b205,2,0.663904,-1.06343
|
||||
b205,3,0.675893,-0.186468
|
||||
b205,4,0.664992,-0.896026
|
||||
b205,5,0.675325,-1.3108
|
||||
b205,6,0.650313,1.14027
|
||||
two-stroke-racing,1,0.433659,-0.00810563
|
||||
two-stroke-racing,2,0.458929,-0.0171482
|
||||
two-stroke-racing,3,0.451155,-0.0116779
|
||||
two-stroke-racing,4,0.451558,-0.00741182
|
||||
two-stroke-racing,5,0.449763,-0.0575893
|
||||
two-stroke-racing,6,0.455667,0.0116538
|
||||
two-stroke-straight,1,0.455246,-0.00988272
|
||||
two-stroke-straight,2,0.452271,-0.145458
|
||||
two-stroke-straight,3,0.450603,-0.0420168
|
||||
two-stroke-straight,4,0.451646,0.115697
|
||||
two-stroke-straight,5,0.453984,0.104074
|
||||
two-stroke-straight,6,0.45035,-0.169018
|
||||
helmholtz,1,0.139612,0.000636785
|
||||
helmholtz,2,0.150413,0.00020821
|
||||
helmholtz,3,0.146235,2.83233e-05
|
||||
helmholtz,4,0.15035,2.23088e-05
|
||||
helmholtz,5,0.140412,-1.88624e-07
|
||||
helmholtz,6,0.117403,-1.88624e-07
|
||||
pulse,1,0.236966,0.155302
|
||||
pulse,2,0.237632,-0.0240824
|
||||
pulse,3,0.238374,-0.00420275
|
||||
pulse,4,0.238214,0.00691116
|
||||
pulse,5,0.236785,-0.00446426
|
||||
pulse,6,0.238714,0.00211677
|
||||
|
30
verification/optimization/final-loaded-diagnostics.txt
Normal file
30
verification/optimization/final-loaded-diagnostics.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
twin second=1 subnormal_cell_fields=0
|
||||
twin second=2 subnormal_cell_fields=0
|
||||
twin second=3 subnormal_cell_fields=0
|
||||
twin second=4 subnormal_cell_fields=0
|
||||
twin second=5 subnormal_cell_fields=0
|
||||
twin second=6 subnormal_cell_fields=0
|
||||
turbo second=1 subnormal_cell_fields=0
|
||||
turbo second=2 subnormal_cell_fields=0
|
||||
turbo second=3 subnormal_cell_fields=0
|
||||
turbo second=4 subnormal_cell_fields=0
|
||||
turbo second=5 subnormal_cell_fields=0
|
||||
turbo second=6 subnormal_cell_fields=0
|
||||
b205 second=1 subnormal_cell_fields=0
|
||||
b205 second=2 subnormal_cell_fields=0
|
||||
b205 second=3 subnormal_cell_fields=0
|
||||
b205 second=4 subnormal_cell_fields=0
|
||||
b205 second=5 subnormal_cell_fields=0
|
||||
b205 second=6 subnormal_cell_fields=0
|
||||
two-stroke-racing second=1 subnormal_cell_fields=0
|
||||
two-stroke-racing second=2 subnormal_cell_fields=0
|
||||
two-stroke-racing second=3 subnormal_cell_fields=0
|
||||
two-stroke-racing second=4 subnormal_cell_fields=0
|
||||
two-stroke-racing second=5 subnormal_cell_fields=0
|
||||
two-stroke-racing second=6 subnormal_cell_fields=0
|
||||
two-stroke-straight second=1 subnormal_cell_fields=0
|
||||
two-stroke-straight second=2 subnormal_cell_fields=0
|
||||
two-stroke-straight second=3 subnormal_cell_fields=0
|
||||
two-stroke-straight second=4 subnormal_cell_fields=0
|
||||
two-stroke-straight second=5 subnormal_cell_fields=0
|
||||
two-stroke-straight second=6 subnormal_cell_fields=0
|
||||
43
verification/optimization/final-loaded.csv
Normal file
43
verification/optimization/final-loaded.csv
Normal file
@@ -0,0 +1,43 @@
|
||||
scenario,second,wall_seconds,checksum
|
||||
twin,1,0.406471,-0.474996
|
||||
twin,2,0.399598,0.566629
|
||||
twin,3,0.404976,-0.445512
|
||||
twin,4,0.406038,-0.457089
|
||||
twin,5,0.407558,0.543696
|
||||
twin,6,0.406988,-0.453352
|
||||
turbo,1,0.681746,-0.310561
|
||||
turbo,2,0.643922,0.239385
|
||||
turbo,3,0.646531,0.037816
|
||||
turbo,4,0.639071,-0.317772
|
||||
turbo,5,0.64264,0.217976
|
||||
turbo,6,0.641204,0.0202668
|
||||
b205,1,0.684996,0.372009
|
||||
b205,2,0.687167,-0.672981
|
||||
b205,3,0.686279,-0.0819324
|
||||
b205,4,0.685947,0.383653
|
||||
b205,5,0.703778,-0.660537
|
||||
b205,6,0.684529,-0.105941
|
||||
two-stroke-racing,1,0.471101,0.0798995
|
||||
two-stroke-racing,2,0.4718,-0.446533
|
||||
two-stroke-racing,3,0.469381,-0.0135509
|
||||
two-stroke-racing,4,0.469582,0.0502136
|
||||
two-stroke-racing,5,0.468865,-0.436305
|
||||
two-stroke-racing,6,0.468437,0.0131878
|
||||
two-stroke-straight,1,0.464019,0.45168
|
||||
two-stroke-straight,2,0.460395,-0.576791
|
||||
two-stroke-straight,3,0.463492,0.301486
|
||||
two-stroke-straight,4,0.463567,0.436602
|
||||
two-stroke-straight,5,0.465461,-0.564872
|
||||
two-stroke-straight,6,0.464165,0.317279
|
||||
helmholtz,1,0.140996,0.000636785
|
||||
helmholtz,2,0.150978,0.00020821
|
||||
helmholtz,3,0.146364,2.83233e-05
|
||||
helmholtz,4,0.150862,2.23088e-05
|
||||
helmholtz,5,0.139892,-1.88624e-07
|
||||
helmholtz,6,0.116593,-1.88624e-07
|
||||
pulse,1,0.237912,0.155302
|
||||
pulse,2,0.23779,-0.0240824
|
||||
pulse,3,0.236885,-0.00420275
|
||||
pulse,4,0.238309,0.00691116
|
||||
pulse,5,0.238156,-0.00446426
|
||||
pulse,6,0.238296,0.00211677
|
||||
|
43
verification/optimization/final-native-loaded.csv
Normal file
43
verification/optimization/final-native-loaded.csv
Normal file
@@ -0,0 +1,43 @@
|
||||
scenario,second,wall_seconds,checksum
|
||||
twin,1,0.404945,-0.474997
|
||||
twin,2,0.394585,0.566634
|
||||
twin,3,0.392608,-0.445506
|
||||
twin,4,0.393395,-0.457098
|
||||
twin,5,0.390801,0.543708
|
||||
twin,6,0.391814,-0.453348
|
||||
turbo,1,0.666509,-0.310561
|
||||
turbo,2,0.614616,0.239377
|
||||
turbo,3,0.623926,0.0378054
|
||||
turbo,4,0.623417,-0.317773
|
||||
turbo,5,0.624208,0.217954
|
||||
turbo,6,0.623219,0.0202511
|
||||
b205,1,0.669162,0.372021
|
||||
b205,2,0.667619,-0.672981
|
||||
b205,3,0.666157,-0.0819704
|
||||
b205,4,0.663694,0.383699
|
||||
b205,5,0.66461,-0.660516
|
||||
b205,6,0.660155,-0.106025
|
||||
two-stroke-racing,1,0.450183,0.079881
|
||||
two-stroke-racing,2,0.43969,-0.446531
|
||||
two-stroke-racing,3,0.43438,-0.0135516
|
||||
two-stroke-racing,4,0.435173,0.0501685
|
||||
two-stroke-racing,5,0.439108,-0.436284
|
||||
two-stroke-racing,6,0.436695,0.0132443
|
||||
two-stroke-straight,1,0.430592,0.451674
|
||||
two-stroke-straight,2,0.431947,-0.576801
|
||||
two-stroke-straight,3,0.435235,0.301495
|
||||
two-stroke-straight,4,0.43456,0.436544
|
||||
two-stroke-straight,5,0.434657,-0.564871
|
||||
two-stroke-straight,6,0.434816,0.317316
|
||||
helmholtz,1,0.132025,0.000620049
|
||||
helmholtz,2,0.141761,0.000208197
|
||||
helmholtz,3,0.137805,-0.00013923
|
||||
helmholtz,4,0.136093,-7.93035e-05
|
||||
helmholtz,5,0.123899,-9.85328e-07
|
||||
helmholtz,6,0.107671,-9.85328e-07
|
||||
pulse,1,0.205303,0.155306
|
||||
pulse,2,0.206141,-0.0240772
|
||||
pulse,3,0.204146,-0.00422162
|
||||
pulse,4,0.204149,0.00692384
|
||||
pulse,5,0.205064,-0.00446612
|
||||
pulse,6,0.205247,0.0021024
|
||||
|
43
verification/optimization/final-scalar-loaded.csv
Normal file
43
verification/optimization/final-scalar-loaded.csv
Normal file
@@ -0,0 +1,43 @@
|
||||
scenario,second,wall_seconds,checksum
|
||||
twin,1,0.429083,-0.474996
|
||||
twin,2,0.425191,0.566629
|
||||
twin,3,0.422704,-0.445512
|
||||
twin,4,0.422067,-0.457089
|
||||
twin,5,0.423142,0.543696
|
||||
twin,6,0.417602,-0.453352
|
||||
turbo,1,0.722612,-0.310561
|
||||
turbo,2,0.678594,0.239385
|
||||
turbo,3,0.676959,0.037816
|
||||
turbo,4,0.675587,-0.317772
|
||||
turbo,5,0.677697,0.217976
|
||||
turbo,6,0.674842,0.0202668
|
||||
b205,1,0.733499,0.372009
|
||||
b205,2,0.738059,-0.672981
|
||||
b205,3,0.739555,-0.0819324
|
||||
b205,4,0.733441,0.383653
|
||||
b205,5,0.737382,-0.660537
|
||||
b205,6,0.740199,-0.105941
|
||||
two-stroke-racing,1,0.532053,0.0798995
|
||||
two-stroke-racing,2,0.530479,-0.446533
|
||||
two-stroke-racing,3,0.535284,-0.0135509
|
||||
two-stroke-racing,4,0.538289,0.0502136
|
||||
two-stroke-racing,5,0.537818,-0.436305
|
||||
two-stroke-racing,6,0.536216,0.0131878
|
||||
two-stroke-straight,1,0.526753,0.45168
|
||||
two-stroke-straight,2,0.530518,-0.576791
|
||||
two-stroke-straight,3,0.515521,0.301486
|
||||
two-stroke-straight,4,0.531466,0.436602
|
||||
two-stroke-straight,5,0.523436,-0.564872
|
||||
two-stroke-straight,6,0.522323,0.317279
|
||||
helmholtz,1,0.160304,0.000636785
|
||||
helmholtz,2,0.171026,0.00020821
|
||||
helmholtz,3,0.166819,2.83233e-05
|
||||
helmholtz,4,0.172109,2.23088e-05
|
||||
helmholtz,5,0.159173,-1.88624e-07
|
||||
helmholtz,6,0.130939,-1.88624e-07
|
||||
pulse,1,0.30969,0.155302
|
||||
pulse,2,0.314339,-0.0240824
|
||||
pulse,3,0.318903,-0.00420275
|
||||
pulse,4,0.317587,0.00691116
|
||||
pulse,5,0.317432,-0.00446426
|
||||
pulse,6,0.313647,0.00211677
|
||||
|
24
verification/optimization/final-threads.txt
Normal file
24
verification/optimization/final-threads.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
scenario=twin pipes=6 workers=1 steps=4000 seconds=0.00275881 checksum=607950
|
||||
scenario=twin pipes=6 workers=2 steps=4000 seconds=0.00970369 checksum=607950
|
||||
scenario=twin pipes=6 workers=4 steps=4000 seconds=0.00580565 checksum=607950
|
||||
scenario=turbo pipes=8 workers=1 steps=4000 seconds=0.00438693 checksum=810600
|
||||
scenario=turbo pipes=8 workers=2 steps=4000 seconds=0.0124137 checksum=810600
|
||||
scenario=turbo pipes=8 workers=4 steps=4000 seconds=0.00970905 checksum=810600
|
||||
scenario=b205 pipes=10 workers=1 steps=4000 seconds=0.00516911 checksum=1.01325e+06
|
||||
scenario=b205 pipes=10 workers=2 steps=4000 seconds=0.014045 checksum=1.01325e+06
|
||||
scenario=b205 pipes=10 workers=4 steps=4000 seconds=0.0101158 checksum=1.01325e+06
|
||||
scenario=two-stroke-racing pipes=4 workers=1 steps=4000 seconds=0.00631318 checksum=405300
|
||||
scenario=two-stroke-racing pipes=4 workers=2 steps=4000 seconds=0.0129319 checksum=405300
|
||||
scenario=two-stroke-racing pipes=4 workers=4 steps=4000 seconds=0.0219618 checksum=405300
|
||||
scenario=two-stroke-straight pipes=4 workers=1 steps=4000 seconds=0.0120785 checksum=405300
|
||||
scenario=two-stroke-straight pipes=4 workers=2 steps=4000 seconds=0.0213055 checksum=405300
|
||||
scenario=two-stroke-straight pipes=4 workers=4 steps=4000 seconds=0.0239495 checksum=405300
|
||||
scenario=helmholtz pipes=1 workers=1 steps=4000 seconds=0.000931972 checksum=101325
|
||||
scenario=helmholtz pipes=1 workers=2 steps=4000 seconds=0.00404044 checksum=101325
|
||||
scenario=helmholtz pipes=1 workers=4 steps=4000 seconds=0.00449503 checksum=101325
|
||||
scenario=pulse pipes=1 workers=1 steps=4000 seconds=0.00689863 checksum=125674
|
||||
scenario=pulse pipes=1 workers=2 steps=4000 seconds=0.0155282 checksum=125674
|
||||
scenario=pulse pipes=1 workers=4 steps=4000 seconds=0.0233903 checksum=125674
|
||||
scenario=large pipes=64 workers=1 steps=4000 seconds=0.577183 checksum=6.4848e+06
|
||||
scenario=large pipes=64 workers=2 steps=4000 seconds=0.321996 checksum=6.4848e+06
|
||||
scenario=large pipes=64 workers=4 steps=4000 seconds=0.186585 checksum=6.4848e+06
|
||||
43
verification/optimization/final-transient.csv
Normal file
43
verification/optimization/final-transient.csv
Normal file
@@ -0,0 +1,43 @@
|
||||
scenario,second,wall_seconds,checksum
|
||||
twin,1,0.409869,-0.0283469
|
||||
twin,2,0.402371,0.80967
|
||||
twin,3,0.403052,-0.911818
|
||||
twin,4,0.402699,0.534151
|
||||
twin,5,0.400457,0.207363
|
||||
twin,6,0.373759,0.0279407
|
||||
turbo,1,0.659625,-0.0302299
|
||||
turbo,2,0.644645,-0.0319911
|
||||
turbo,3,0.651985,0.186487
|
||||
turbo,4,0.638045,-0.153387
|
||||
turbo,5,0.681532,-0.0672159
|
||||
turbo,6,0.632109,-0.00641479
|
||||
b205,1,0.676147,0.274864
|
||||
b205,2,0.689301,-0.142368
|
||||
b205,3,0.683649,-1.24857
|
||||
b205,4,0.684867,0.692396
|
||||
b205,5,0.691513,-0.277036
|
||||
b205,6,0.671074,3.18497
|
||||
two-stroke-racing,1,0.439156,-0.00810563
|
||||
two-stroke-racing,2,0.476664,-0.0454537
|
||||
two-stroke-racing,3,0.491684,0.182272
|
||||
two-stroke-racing,4,0.481265,0.0605218
|
||||
two-stroke-racing,5,0.460421,-0.042154
|
||||
two-stroke-racing,6,0.404627,-0.0445087
|
||||
two-stroke-straight,1,0.462682,-0.00988272
|
||||
two-stroke-straight,2,0.465014,0.834933
|
||||
two-stroke-straight,3,0.463,-0.788353
|
||||
two-stroke-straight,4,0.462517,-0.624996
|
||||
two-stroke-straight,5,0.447777,-0.229619
|
||||
two-stroke-straight,6,0.416485,0.0188991
|
||||
helmholtz,1,0.141009,0.000636785
|
||||
helmholtz,2,0.150956,0.00020821
|
||||
helmholtz,3,0.146729,2.83233e-05
|
||||
helmholtz,4,0.148541,2.23088e-05
|
||||
helmholtz,5,0.138622,-1.88624e-07
|
||||
helmholtz,6,0.116949,-1.88624e-07
|
||||
pulse,1,0.238432,0.155302
|
||||
pulse,2,0.238248,-0.0240824
|
||||
pulse,3,0.236267,-0.00420275
|
||||
pulse,4,0.236616,0.00691116
|
||||
pulse,5,0.237568,-0.00446426
|
||||
pulse,6,0.237908,0.00211677
|
||||
|
186
verification/optimization/scalar-tests.log
Normal file
186
verification/optimization/scalar-tests.log
Normal file
@@ -0,0 +1,186 @@
|
||||
Start testing: Oct 23 02:38 CEST
|
||||
----------------------------------------------------------
|
||||
1/9 Testing: fluidsim_physics_tests
|
||||
1/9 Test: fluidsim_physics_tests
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-simd-off/fluidsim_physics_tests"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-simd-off
|
||||
"fluidsim_physics_tests" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
FluidSim C++ physics tests passed
|
||||
<end of output>
|
||||
Test time = 2.67 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_physics_tests" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_physics_tests" time elapsed: 00:00:02
|
||||
----------------------------------------------------------
|
||||
|
||||
2/9 Testing: fluidsim_fluid_validation
|
||||
2/9 Test: fluidsim_fluid_validation
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-simd-off/fluidsim_fluid_validation"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-simd-off
|
||||
"fluidsim_fluid_validation" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
PASS tracer underflow preserves bulk gas and normal concentrations
|
||||
PASS invalid uniform geometry
|
||||
PASS closed pipe conservation
|
||||
PASS profiled pipe conservation
|
||||
PASS volume pipe sealed conservation
|
||||
PASS equal pressure hot contact
|
||||
PASS NASA choked nozzle mass flow
|
||||
PASS inertance units
|
||||
PASS moving volume adiabatic law
|
||||
PASS profile at rest is well balanced
|
||||
PASS pipe connection all four orientations
|
||||
PASS split pipe matches unsplit pipe
|
||||
PASS three volumes shared donor conservation
|
||||
PASS open boundary reports actual conserved flux both ends
|
||||
PASS duplicate and invalid boundary rejection
|
||||
PASS supersonic outlet extrapolates
|
||||
PASS underdefined supersonic inlet rejected
|
||||
PASS closed and open acoustic reflection signs
|
||||
Sod n=100 density L1=0.0233209
|
||||
Sod n=200 density L1=0.0159539
|
||||
Sod n=400 density L1=0.0105216
|
||||
PASS Sod shock tube convergence
|
||||
PASS strong pulse and near-vacuum rarefaction
|
||||
Helmholtz frequency=135.6 analytic lumped=138.508
|
||||
PASS small-signal Helmholtz resonance
|
||||
PASS invalid volume and timestep rejection
|
||||
PASS fresh-air species conservation across connection
|
||||
PASS unsupported unequal junction rejected
|
||||
PASS unconnected endpoint rejected by solver
|
||||
closed mode n=50 f=171.897 analytic=171.91
|
||||
closed mode n=100 f=171.914 analytic=171.91
|
||||
closed mode n=200 f=171.911 analytic=171.91
|
||||
PASS closed duct acoustic eigenfrequency
|
||||
PASS inertance impulse and dissipative resistance
|
||||
PASS incompatible gas coupling rejected
|
||||
PASS thermal relaxation matches analytic energy decay
|
||||
PASS sealed crankcase compression conserves mass above five bar
|
||||
30/30 passed
|
||||
<end of output>
|
||||
Test time = 0.12 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_fluid_validation" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_fluid_validation" time elapsed: 00:00:00
|
||||
----------------------------------------------------------
|
||||
|
||||
3/9 Testing: fluidsim_intake_regression
|
||||
3/9 Test: fluidsim_intake_regression
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-simd-off/fluidsim_intake_regression"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-simd-off
|
||||
"fluidsim_intake_regression" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Intake regression passed: idle_MAP=35.764 kPa, open_MAP=85.4564 kPa, open_T=298.957 K, inlet_T=296.92 K, recovered_MAP=34.502 kPa, recovered_RPM=1820.05
|
||||
<end of output>
|
||||
Test time = 6.61 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_intake_regression" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_intake_regression" time elapsed: 00:00:06
|
||||
----------------------------------------------------------
|
||||
|
||||
4/9 Testing: fluidsim_outdoor_audio_tests
|
||||
4/9 Test: fluidsim_outdoor_audio_tests
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-simd-off/fluidsim_outdoor_audio_tests"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-simd-off
|
||||
"fluidsim_outdoor_audio_tests" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Outdoor audio tests passed: direct=385 samples, ground=463 samples, filtered step ratio=0.155034, stereo lead=7 samples
|
||||
<end of output>
|
||||
Test time = 0.02 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_outdoor_audio_tests" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_outdoor_audio_tests" time elapsed: 00:00:00
|
||||
----------------------------------------------------------
|
||||
|
||||
5/9 Testing: fluidsim_two_stroke_regression
|
||||
5/9 Test: fluidsim_two_stroke_regression
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-simd-off/fluidsim_two_stroke_regression"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-simd-off
|
||||
"fluidsim_two_stroke_regression" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Two-stroke regression passed: peak=0.2566, maximum RPM=16127.3, recovered RPM=3158.32, bike speed=61.2948 km/h
|
||||
<end of output>
|
||||
Test time = 10.39 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_two_stroke_regression" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_two_stroke_regression" time elapsed: 00:00:10
|
||||
----------------------------------------------------------
|
||||
|
||||
6/9 Testing: fluidsim_two_stroke_physics
|
||||
6/9 Test: fluidsim_two_stroke_physics
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-simd-off/fluidsim_two_stroke_physics"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-simd-off
|
||||
"fluidsim_two_stroke_physics" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Two-stroke physics passed: diffuser reflection=-34.3281 Pa, baffle reflection=27.5234 Pa, first reduction=30.2759
|
||||
<end of output>
|
||||
Test time = 0.01 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_two_stroke_physics" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_two_stroke_physics" time elapsed: 00:00:00
|
||||
----------------------------------------------------------
|
||||
|
||||
7/9 Testing: fluidsim_b205_regression
|
||||
7/9 Test: fluidsim_b205_regression
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-simd-off/fluidsim_b205_regression"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-simd-off
|
||||
"fluidsim_b205_regression" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
B205 passed: firing events=33, wagon speed=56.5685 km/h, recovered RPM=1311.5, audio peak=0.186449, wall seconds=5.89428 for 8 simulated seconds
|
||||
<end of output>
|
||||
Test time = 5.90 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_b205_regression" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_b205_regression" time elapsed: 00:00:05
|
||||
----------------------------------------------------------
|
||||
|
||||
8/9 Testing: fluidsim_turbo_physics
|
||||
8/9 Test: fluidsim_turbo_physics
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-simd-off/fluidsim_turbo_physics"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-simd-off
|
||||
"fluidsim_turbo_physics" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Closed balance initial_rpm=0 mass_error=0 energy_error=-1.59125e-07 J
|
||||
Closed balance initial_rpm=120000 mass_error=0 energy_error=-7.09297e-07 J
|
||||
Turbo pipe bench passed: rpm=189122 compressor flow=0.0306693 kg/s, charge T=375.978 K, turbine power range=1189.38..4022.29 W, residual=-5.44049e-06 J
|
||||
<end of output>
|
||||
Test time = 0.32 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_turbo_physics" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_turbo_physics" time elapsed: 00:00:00
|
||||
----------------------------------------------------------
|
||||
|
||||
9/9 Testing: fluidsim_turbo_twin_regression
|
||||
9/9 Test: fluidsim_turbo_twin_regression
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-simd-off/fluidsim_turbo_twin_regression"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-simd-off
|
||||
"fluidsim_turbo_twin_regression" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Turbo twin passed: max_rpm=236218, max_charge=181.458 kPa, max_turbine_pressure=674.103 kPa, gate=2.7762 mm, final_rpm=151754, peak_audio=0.0293228, energy_residual=2.16491e-06 J
|
||||
<end of output>
|
||||
Test time = 4.83 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_turbo_twin_regression" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_turbo_twin_regression" time elapsed: 00:00:04
|
||||
----------------------------------------------------------
|
||||
|
||||
End testing: Oct 23 02:38 CEST
|
||||
186
verification/optimization/simd-tests.log
Normal file
186
verification/optimization/simd-tests.log
Normal file
@@ -0,0 +1,186 @@
|
||||
Start testing: Oct 23 02:37 CEST
|
||||
----------------------------------------------------------
|
||||
1/9 Testing: fluidsim_physics_tests
|
||||
1/9 Test: fluidsim_physics_tests
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-audit/fluidsim_physics_tests"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-audit
|
||||
"fluidsim_physics_tests" start time: Oct 23 02:37 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
FluidSim C++ physics tests passed
|
||||
<end of output>
|
||||
Test time = 2.51 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_physics_tests" end time: Oct 23 02:37 CEST
|
||||
"fluidsim_physics_tests" time elapsed: 00:00:02
|
||||
----------------------------------------------------------
|
||||
|
||||
2/9 Testing: fluidsim_fluid_validation
|
||||
2/9 Test: fluidsim_fluid_validation
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-audit/fluidsim_fluid_validation"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-audit
|
||||
"fluidsim_fluid_validation" start time: Oct 23 02:37 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
PASS tracer underflow preserves bulk gas and normal concentrations
|
||||
PASS invalid uniform geometry
|
||||
PASS closed pipe conservation
|
||||
PASS profiled pipe conservation
|
||||
PASS volume pipe sealed conservation
|
||||
PASS equal pressure hot contact
|
||||
PASS NASA choked nozzle mass flow
|
||||
PASS inertance units
|
||||
PASS moving volume adiabatic law
|
||||
PASS profile at rest is well balanced
|
||||
PASS pipe connection all four orientations
|
||||
PASS split pipe matches unsplit pipe
|
||||
PASS three volumes shared donor conservation
|
||||
PASS open boundary reports actual conserved flux both ends
|
||||
PASS duplicate and invalid boundary rejection
|
||||
PASS supersonic outlet extrapolates
|
||||
PASS underdefined supersonic inlet rejected
|
||||
PASS closed and open acoustic reflection signs
|
||||
Sod n=100 density L1=0.0233209
|
||||
Sod n=200 density L1=0.0159539
|
||||
Sod n=400 density L1=0.0105216
|
||||
PASS Sod shock tube convergence
|
||||
PASS strong pulse and near-vacuum rarefaction
|
||||
Helmholtz frequency=135.6 analytic lumped=138.508
|
||||
PASS small-signal Helmholtz resonance
|
||||
PASS invalid volume and timestep rejection
|
||||
PASS fresh-air species conservation across connection
|
||||
PASS unsupported unequal junction rejected
|
||||
PASS unconnected endpoint rejected by solver
|
||||
closed mode n=50 f=171.897 analytic=171.91
|
||||
closed mode n=100 f=171.914 analytic=171.91
|
||||
closed mode n=200 f=171.911 analytic=171.91
|
||||
PASS closed duct acoustic eigenfrequency
|
||||
PASS inertance impulse and dissipative resistance
|
||||
PASS incompatible gas coupling rejected
|
||||
PASS thermal relaxation matches analytic energy decay
|
||||
PASS sealed crankcase compression conserves mass above five bar
|
||||
30/30 passed
|
||||
<end of output>
|
||||
Test time = 0.10 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_fluid_validation" end time: Oct 23 02:37 CEST
|
||||
"fluidsim_fluid_validation" time elapsed: 00:00:00
|
||||
----------------------------------------------------------
|
||||
|
||||
3/9 Testing: fluidsim_intake_regression
|
||||
3/9 Test: fluidsim_intake_regression
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-audit/fluidsim_intake_regression"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-audit
|
||||
"fluidsim_intake_regression" start time: Oct 23 02:37 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Intake regression passed: idle_MAP=35.764 kPa, open_MAP=85.4564 kPa, open_T=298.957 K, inlet_T=296.92 K, recovered_MAP=34.502 kPa, recovered_RPM=1820.05
|
||||
<end of output>
|
||||
Test time = 6.26 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_intake_regression" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_intake_regression" time elapsed: 00:00:06
|
||||
----------------------------------------------------------
|
||||
|
||||
4/9 Testing: fluidsim_outdoor_audio_tests
|
||||
4/9 Test: fluidsim_outdoor_audio_tests
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-audit/fluidsim_outdoor_audio_tests"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-audit
|
||||
"fluidsim_outdoor_audio_tests" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Outdoor audio tests passed: direct=385 samples, ground=463 samples, filtered step ratio=0.155034, stereo lead=7 samples
|
||||
<end of output>
|
||||
Test time = 0.02 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_outdoor_audio_tests" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_outdoor_audio_tests" time elapsed: 00:00:00
|
||||
----------------------------------------------------------
|
||||
|
||||
5/9 Testing: fluidsim_two_stroke_regression
|
||||
5/9 Test: fluidsim_two_stroke_regression
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-audit/fluidsim_two_stroke_regression"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-audit
|
||||
"fluidsim_two_stroke_regression" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Two-stroke regression passed: peak=0.2566, maximum RPM=16127.3, recovered RPM=3158.32, bike speed=61.2948 km/h
|
||||
<end of output>
|
||||
Test time = 9.18 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_two_stroke_regression" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_two_stroke_regression" time elapsed: 00:00:09
|
||||
----------------------------------------------------------
|
||||
|
||||
6/9 Testing: fluidsim_two_stroke_physics
|
||||
6/9 Test: fluidsim_two_stroke_physics
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-audit/fluidsim_two_stroke_physics"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-audit
|
||||
"fluidsim_two_stroke_physics" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Two-stroke physics passed: diffuser reflection=-34.3281 Pa, baffle reflection=27.5234 Pa, first reduction=30.2759
|
||||
<end of output>
|
||||
Test time = 0.00 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_two_stroke_physics" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_two_stroke_physics" time elapsed: 00:00:00
|
||||
----------------------------------------------------------
|
||||
|
||||
7/9 Testing: fluidsim_b205_regression
|
||||
7/9 Test: fluidsim_b205_regression
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-audit/fluidsim_b205_regression"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-audit
|
||||
"fluidsim_b205_regression" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
B205 passed: firing events=33, wagon speed=56.5685 km/h, recovered RPM=1311.5, audio peak=0.186449, wall seconds=5.48769 for 8 simulated seconds
|
||||
<end of output>
|
||||
Test time = 5.49 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_b205_regression" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_b205_regression" time elapsed: 00:00:05
|
||||
----------------------------------------------------------
|
||||
|
||||
8/9 Testing: fluidsim_turbo_physics
|
||||
8/9 Test: fluidsim_turbo_physics
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-audit/fluidsim_turbo_physics"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-audit
|
||||
"fluidsim_turbo_physics" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Closed balance initial_rpm=0 mass_error=0 energy_error=-1.59125e-07 J
|
||||
Closed balance initial_rpm=120000 mass_error=0 energy_error=-7.09297e-07 J
|
||||
Turbo pipe bench passed: rpm=189122 compressor flow=0.0306693 kg/s, charge T=375.978 K, turbine power range=1189.38..4022.29 W, residual=-5.44049e-06 J
|
||||
<end of output>
|
||||
Test time = 0.31 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_turbo_physics" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_turbo_physics" time elapsed: 00:00:00
|
||||
----------------------------------------------------------
|
||||
|
||||
9/9 Testing: fluidsim_turbo_twin_regression
|
||||
9/9 Test: fluidsim_turbo_twin_regression
|
||||
Command: "/home/grillkol/repos/FluidSimCpp/build-audit/fluidsim_turbo_twin_regression"
|
||||
Directory: /home/grillkol/repos/FluidSimCpp/build-audit
|
||||
"fluidsim_turbo_twin_regression" start time: Oct 23 02:38 CEST
|
||||
Output:
|
||||
----------------------------------------------------------
|
||||
Turbo twin passed: max_rpm=236218, max_charge=181.458 kPa, max_turbine_pressure=674.103 kPa, gate=2.7762 mm, final_rpm=151754, peak_audio=0.0293228, energy_residual=2.16491e-06 J
|
||||
<end of output>
|
||||
Test time = 4.61 sec
|
||||
----------------------------------------------------------
|
||||
Test Passed.
|
||||
"fluidsim_turbo_twin_regression" end time: Oct 23 02:38 CEST
|
||||
"fluidsim_turbo_twin_regression" time elapsed: 00:00:04
|
||||
----------------------------------------------------------
|
||||
|
||||
End testing: Oct 23 02:38 CEST
|
||||
Reference in New Issue
Block a user