39 lines
1.2 KiB
C++
39 lines
1.2 KiB
C++
#include "FluidSim/Solver.hpp"
|
|
|
|
#include <algorithm>
|
|
|
|
namespace fluidsim::port {
|
|
|
|
Solver::Solver(std::vector<Pipe1D> &pipes, BoundarySystem &boundaries)
|
|
: pipes_(pipes), boundaries_(boundaries) {}
|
|
|
|
void Solver::add_component(Component &component) { components_.push_back(&component); }
|
|
|
|
void Solver::step(float dt) {
|
|
if (!std::isfinite(dt) || dt < 0)
|
|
throw std::invalid_argument("invalid solver timestep");
|
|
if (dt == 0)
|
|
return;
|
|
boundaries_.validate_topology();
|
|
const float maximum_dt = dt / static_cast<float>(std::max(minimum_substeps, 1));
|
|
double remaining = dt;
|
|
int count = 0;
|
|
while (remaining > double(dt) * 1e-7) {
|
|
float sub_dt = std::min(maximum_dt, static_cast<float>(remaining));
|
|
for (auto &pipe : pipes_)
|
|
sub_dt = std::min(sub_dt, pipe.prepare_step());
|
|
if (!(sub_dt > 0) || ++count > 1000000)
|
|
throw std::runtime_error("solver timestep failed to progress");
|
|
++substep_count_;
|
|
boundaries_.resolve(sub_dt);
|
|
for (auto &pipe : pipes_)
|
|
pipe.advance(sub_dt);
|
|
for (Component *component : components_)
|
|
component->update_state(sub_dt);
|
|
remaining -= sub_dt;
|
|
}
|
|
++step_count_;
|
|
}
|
|
|
|
} // namespace fluidsim::port
|