42 lines
2.1 KiB
C++
42 lines
2.1 KiB
C++
#include "FluidSim/TwoStrokeScenario.hpp"
|
|
#include <algorithm>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
|
|
using namespace fluidsim::port;
|
|
int main() {
|
|
std::cout << "exhaust,rpm,shaft_kW,shaft_Nm,firings_per_revolution,carb_afr,crankcase_afr,repairs,wall_seconds\n";
|
|
for (auto exhaust : {TwoStrokeExhaust::Straight, TwoStrokeExhaust::Racing}) {
|
|
for (float rpm : {6000.f, 8000.f, 10000.f, 12000.f, 14000.f, 17000.f}) {
|
|
TwoStrokeConfig config;
|
|
config.exhaust = exhaust;
|
|
TwoStrokeScenario s(44100, config);
|
|
s.set_throttle(1);
|
|
const auto start = std::chrono::steady_clock::now();
|
|
double torque = 0, power = 0;
|
|
std::uint64_t initial_firings = 0;
|
|
// An ideal absorbing/motoring dyno imposes speed, exchanging shaft
|
|
// work externally. It never changes gas energy or adds combustion.
|
|
for (int i = 0; i < 44100; ++i) {
|
|
s.crankshaft.omega = rpm * 2 * pi / 60;
|
|
s.process();
|
|
if (i == 22049) initial_firings = s.cylinder.combustion_count();
|
|
if (i >= 22050) {
|
|
torque += s.crankshaft.average_torque / 22050;
|
|
power += s.crankshaft.average_power / (22050 * 1000.f);
|
|
}
|
|
}
|
|
unsigned long long repairs = 0;
|
|
for (const auto& pipe : s.pipes) repairs += pipe.positivity_repairs;
|
|
const double wall = std::chrono::duration<double>(std::chrono::steady_clock::now()-start).count();
|
|
std::cout << (exhaust == TwoStrokeExhaust::Racing ? "racing" : "straight") << ',' << rpm
|
|
<< ',' << power << ',' << torque << ','
|
|
<< (s.cylinder.combustion_count()-initial_firings) / (rpm / 120)
|
|
<< ',' << s.carburetor.indicated_afr()
|
|
<< ',' << s.crankcase.mass() * s.crankcase.air_fraction() /
|
|
std::max(s.crankcase.fuel_mass(), 1e-12f)
|
|
<< ',' << repairs << ',' << wall << std::endl;
|
|
}
|
|
}
|
|
}
|