92 lines
4.0 KiB
C++
92 lines
4.0 KiB
C++
#include "FluidSim/Fluid.hpp"
|
|
#include "FluidSim/Scenario.hpp"
|
|
#include "FluidSim/TwoStrokeScenario.hpp"
|
|
#include "FluidSim/HelmholtzScenario.hpp"
|
|
#include "FluidSim/PulseTestScenario.hpp"
|
|
#include <algorithm>
|
|
#include <barrier>
|
|
#include <chrono>
|
|
#include <cmath>
|
|
#include <iostream>
|
|
#include <numeric>
|
|
#include <stdexcept>
|
|
#include <thread>
|
|
#include <vector>
|
|
using namespace fluidsim::port;
|
|
static void set_uniform_resolution(std::vector<Pipe1D>& pipes, int cells_per_meter) {
|
|
if (cells_per_meter <= 0) throw std::invalid_argument("cells per meter must be positive");
|
|
for (auto& pipe : pipes) {
|
|
const float length = std::accumulate(pipe.cell_lengths.begin(), pipe.cell_lengths.end(), 0.0f);
|
|
const int count = std::max(1, static_cast<int>(std::ceil(length * cells_per_meter)));
|
|
const float damping = pipe.damping_multiplier;
|
|
const float relaxation = pipe.energy_relaxation_rate;
|
|
pipe = Pipe1D(pipe.area, length, count);
|
|
pipe.damping_multiplier = damping;
|
|
pipe.energy_relaxation_rate = relaxation;
|
|
}
|
|
}
|
|
int main(int argc, char** argv) {
|
|
const int uniform_cells_per_meter = argc > 1 ? std::stoi(argv[1]) : 0;
|
|
for (std::string name : {"twin", "b205", "v8", "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 == "v8" ? FourStrokePreset::AmericanV8 : name == "b205" ? FourStrokePreset::SaabB205 : FourStrokePreset::Twin);
|
|
geometry = s.pipes;
|
|
}
|
|
if (name == "v8" && uniform_cells_per_meter > 0)
|
|
set_uniform_resolution(geometry, uniform_cells_per_meter);
|
|
const int steps = 4000;
|
|
for (int workers : {1, 2, 4}) {
|
|
auto p = geometry;
|
|
auto advance = [&](int worker) {
|
|
for (int k = worker; k < static_cast<int>(p.size()); k += workers) {
|
|
auto &a = p[k];
|
|
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;
|
|
a.right_ghost = r;
|
|
a.advance(.0000005f);
|
|
}
|
|
};
|
|
std::barrier sync(workers + 1);
|
|
std::vector<std::jthread> pool;
|
|
if (workers > 1)
|
|
for (int k = 0; k < workers; k++)
|
|
pool.emplace_back([&, k] {
|
|
for (int i = 0; i < steps; i++) {
|
|
sync.arrive_and_wait();
|
|
advance(k);
|
|
sync.arrive_and_wait();
|
|
}
|
|
});
|
|
auto start = std::chrono::steady_clock::now();
|
|
for (int i = 0; i < steps; i++) {
|
|
if (workers == 1)
|
|
advance(0);
|
|
else {
|
|
sync.arrive_and_wait();
|
|
sync.arrive_and_wait();
|
|
}
|
|
}
|
|
double sec = std::chrono::duration<double>(std::chrono::steady_clock::now() - start).count();
|
|
pool.clear();
|
|
double sum = 0;
|
|
for (auto &q : p)
|
|
sum += q.state(0).pressure;
|
|
std::cout << "scenario=" << name << " pipes=" << p.size() << " workers=" << workers
|
|
<< " steps=" << steps << " seconds=" << sec << " checksum=" << sum << '\n';
|
|
}
|
|
}
|
|
}
|