LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
solver_fluid.h File Reference

SolverFluid: the closing method, a port of solver_fluid.m, solver_fluid_iteration.m and solver_fluid_closing.m. More...

Include dependency graph for solver_fluid.h:

Go to the source code of this file.

Classes

struct  line::fluid::FluidOptions
 Controls, defaulting to SolverOptions('Fluid') in the reference. More...
struct  line::fluid::FluidOptions::RateSched
 options.config.rate_sched: explicit per-(station, class) rate trajectories, the third source solver_fluid_ratemult composes. More...
struct  line::fluid::FluidMomentReport
 The second-order results of the moment-closure methods, i.e. More...
struct  line::fluid::FluidTranPoint
 One point of a transient trajectory: the metrics at time t. More...
struct  line::fluid::FluidSolution
 What the analyzer returns, in the same shape as the MVA solver's result. More...

Namespaces

namespace  line
namespace  line::fluid

Functions

template<class T>
void line::fluid::fluid_closing_metrics (const qn::NetworkStruct< T > &sn, const FluidOdeSystem &sys, const std::string &m, const std::vector< double > &xs, Matrix< double > &Q, Matrix< double > &U, Matrix< double > &R, Matrix< double > &T_)
 Read Q/U/R/T off ONE fluid state, for the closing family.
template<class T>
FluidSolution line::fluid::solver_fluid (const qn::NetworkStruct< T > &sn_in, const FluidOptions &opt, qn::NetworkStruct< T > *sn_out=nullptr)
 Port of solver_fluid_analyzer.m: dispatch on the method, refit the non-exponential FCFS stations the reference refits, then apply the utilization and response-time correction it applies to whatever the branch returned.
template<class T>
std::vector< std::pair< std::size_t, std::size_t > > line::fluid::fluid_detect_nhpp (const qn::NetworkStruct< T > &sn)
 Port of local_detect_nhpp in @@SolverFLD/getTranAvg.m: the (station, class) pairs whose SOURCE carries a rate schedule, 1-based.
template<class T>
std::vector< FluidTranPointline::fluid::solver_fluid_transient (const qn::NetworkStruct< T > &sn, const FluidOptions &opt, double t_end, std::size_t points=101, const std::vector< double > &out_grid=std::vector< double >())
 Port of @@SolverFLD/getTranAvg: the metrics along the trajectory, not just at the fixed point.
template<class T>
double line::fluid::fluid_default_horizon (const qn::NetworkStruct< T > &sn, const FluidOptions &opt)
 The horizon a transient runs to when the caller gives none.
template<class T>
std::vector< FluidTranPointline::fluid::solver_fluid_tran_avg (const qn::NetworkStruct< T > &sn, const FluidOptions &opt, std::size_t points=101)
 getTranAvg on the first-order closing drift, over that horizon.
template<class T>
Matrix< double > line::fluid::fluid_jacobian (const qn::NetworkStruct< T > &sn, const std::vector< double > &x)
 The Jacobian of the fluid drift at a state, by central differences.
template<class T>
double line::fluid::fluid_prob_aggr_gaussian (const qn::NetworkStruct< T > &sn, const FluidSolution &sol, std::size_t i, const std::vector< double > &nir, double *logp_out=nullptr)
 The joint probability of the per-class populations at station i (0-based) under the linear noise approximation solved by the moment closure, the local_gaussian_cell of the reference @@SolverFLD/getProbAggr.
template<class T>
double line::fluid::fluid_prob_aggr (const qn::NetworkStruct< T > &sn, const FluidSolution &sol, std::size_t ist, double *logp_out=nullptr)
 Port of @@SolverFLD/getProbAggr: the probability that station ist holds the marginal population of the model's default state.

Detailed Description

SolverFluid: the closing method, a port of solver_fluid.m, solver_fluid_iteration.m and solver_fluid_closing.m.

WHAT THE SOLVER DOES. The fluid approximation replaces the integer queue lengths of the CTMC with real-valued masses and follows their mean drift. The drift is built in fluid_odes.h; this file integrates it and turns the end state into the usual Q/U/R/T/C/X table.

WHY THE INTEGRATION IS AN ITERATION RATHER THAN ONE LONG SOLVE. The steady state is the drift's fixed point, and how long it takes to get there is set by the SLOWEST rate in the model. The reference integrates to 10*iter/min(rate) on iteration iter, restarting from the previous end state: each pass buys another ten mean events of the slowest transition. A single solve to a guessed horizon either stops short on a stiff model or wastes most of its steps on one that settled early.

A NOTE ON THE CONVERGENCE TEST. movedMassRatio is the mass moved over ONE window, and for a mode relaxing at rate r it underestimates the distance still to go by (1-exp(-r*window)). On M/M/1 at rho = 0.9 with minnormal the fixed point is Q = 7.021524680 and stopping at iter_tol = 1e-4 lands on 7.014672, out by 0.1%. Both solver_fluid_iteration.m and this port therefore ran every one of their iter_max passes, which is what made a fluid solve cost a fixed 150 windows however close it started to the answer. The fix is to stop on what the ratio DROPS: summing the geometric tail, ratio*rho/(1-rho) with rho read off the iteration itself, bounds the distance left rather than the distance just travelled, and needs no rate to stand in for the slowest system mode – when one does, as a bare drift norm must, the stop lands 3% short. earlystop (default true, options.config.fluid_earlystop) selects it; iter_tol > 0 remains the caller's own cruder trade. A FINITE timespan_end is a transient request and is exempt from both: it integrates to its end time even once the state has settled.

THE PRICE OF RUNNING EVERY PASS is this port's own, and it is small: LSODA is restarted once per pass, so at the default tol = 1e-4 its error accumulates on a state that is already at the fixed point. On Delay(Z=1) -> PS(c=2), N=6, whose closing fixed point is exactly (2,4) and which the reference returns to nine digits, this port is right to 1e-8 by pass 8 and 7e-6 by pass 200. tol = 1e-6 removes it, at the cost of a different trajectory row count.

DOUBLE ONLY. The drift is integrated by LSODA, whose coefficients assume double (see util/lsoda.h), so a non-double backend is refused BY NAME rather than silently narrowed.

Definition in file solver_fluid.h.