![]() |
LINE Solver (C++)
Templated C++ port of the LINE queueing solver
|
The tbi method: a port of solver_fluid_tbi_iteration.m and tbi_partition.m. More...
#include <algorithm>#include <cmath>#include <cstddef>#include <vector>#include "line/lang/qn/network_struct.h"#include "line/solvers/fluid/fluid_odes.h"#include "line/solvers/fluid/fluid_stiff.h"#include "line/util/lsoda.h"Go to the source code of this file.
Classes | |
| struct | line::fluid::TbiOptions |
| Controls of the time-based iteration, mirroring options.config.tbi_*. More... | |
Namespaces | |
| namespace | line |
| namespace | line::fluid |
Functions | |
| template<class T> | |
| std::vector< std::vector< std::size_t > > | line::fluid::tbi_partition (const qn::NetworkStruct< T > &sn, std::size_t cellsize=5) |
| Port of tbi_partition.m: stations grouped by routing coupling. | |
| std::vector< double > | line::fluid::tbi_advance (const FluidOdeSystem &sys, const std::vector< std::vector< std::size_t > > &cells, const std::vector< double > &y0, double t0, double t1, const TbiOptions &topt, const LsodaOptions &lopt) |
| Advance the state over [t0, t1] by time-based iteration. | |
The tbi method: a port of solver_fluid_tbi_iteration.m and tbi_partition.m.
WHAT TBI IS FOR. The closing drift couples every station to every other, so one integration works on the whole state vector at once and its cost grows with the model. Time-based iteration splits the stations into CELLS, solves each cell's sub-drift on its own, and treats the flow arriving from the other cells as a KNOWN FUNCTION OF TIME, frozen at the previous sweep's trajectories. Sweeping until the trajectories stop moving recovers the coupled solution, while each solve only ever sees one cell's states. It is a domain decomposition in time, and it pays off when the model is too large for one integration to be comfortable.
THE PARTITION is the reference's greedy merge: start with one station per cell and repeatedly merge the pair with the largest routing coupling (W + W', diagonal dropped) whose combined size stays within twice the target cell size, until the cell count reaches ceil(M / cellsize) with cellsize 5. When nothing can be merged within the cap, the two smallest cells are merged instead so the loop always terminates.
GAUSS-SEIDEL BY DEFAULT. After a cell is solved, the frozen rates of ITS events are refreshed immediately, so later cells in the same sweep already see the update. The reference offers a Jacobi variant for parallel runs; this port implements the sequential Gauss-Seidel default, which is what the reference selects when it is not asked for parallelism.
ONE DELIBERATE SIMPLIFICATION, and what it costs. The reference carries whatever output grid its ODE solver happens to produce, takes the union of the cells' grids and interpolates every cell onto it. This port integrates every cell on ONE FIXED GRID per segment instead, so the sweeps compare trajectories sampled at the same instants and no interpolation of one cell onto another's grid is needed. The frozen inbound drift is still linearly interpolated between grid points, exactly as fluid_interpcols does.
THE GRID IS THE ACCURACY KNOB, and the error it leaves is measurable. Only the EXTERNAL contribution is approximated – each cell's own drift is integrated exactly – so the residual behaves like the interpolation error, falling roughly quadratically as the grid is refined. On a ten-queue model whose exact population is 4, the closed-form closing solve gives 4.000000 and this decomposition gives
grid 16 65 129 257 pop 4.167 4.0222 4.00285 3.99936
so the default of 129 holds the population to under a tenth of a percent. A model that needs more can raise TbiOptions::grid; nothing else changes, because the fixed point being chased is the same coupled ODE either way.
A SINGLE CELL IS THE CLOSING METHOD. With M <= cellsize the partition has one cell, there are no external events, the inbound drift is identically zero and the cell drift IS the closing drift. That is the case the tests pin, because it is the one where TBI has an independent right answer to be checked against.
Definition in file fluid_tbi.h.