This commit is contained in:
2026-10-23 03:00:20 +02:00
parent 589d22aa5e
commit 7a5c77c1c8
31 changed files with 1196 additions and 44 deletions

View File

@@ -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);