![]() |
LINE Solver (C++)
Templated C++ port of the LINE queueing solver
|
Port of solver_fluid_initsol.m, and of the entry point of solver_fluid_closing.m that consumes it. More...
#include <cmath>#include <cstddef>#include <string>#include <type_traits>#include <vector>#include "line/lang/qn/network_struct.h"#include "line/solvers/fluid/fluid_odes.h"#include "line/solvers/fluid/solver_fluid.h"#include "line/util/error.h"Go to the source code of this file.
Namespaces | |
| namespace | line |
| namespace | line::fluid |
Functions | |
| template<class T> | |
| std::vector< double > | line::fluid::fluid_initsol (const qn::NetworkStruct< T > &sn, const FluidLayout &L) |
| Port of solver_fluid_initsol.m: the ODE's initial condition, in the layout the drift indexes. | |
| template<class T> | |
| std::vector< double > | line::fluid::fluid_initsol (const qn::NetworkStruct< T > &sn) |
| The same, for a caller that has not built the layout itself. | |
| template<class T> | |
| FluidSolution | line::fluid::solver_fluid_closing (const qn::NetworkStruct< T > &sn, const FluidOptions &opt) |
| Port of solver_fluid_closing.m: the closing family's entry point. | |
Port of solver_fluid_initsol.m, and of the entry point of solver_fluid_closing.m that consumes it.
WHY THE INITIAL CONDITION IS NOT AN IMPLEMENTATION DETAIL. The fluid answer is a fixed point of the drift, and a drift that is not convex has more than one: a closed model whose queue can either drain or saturate settles wherever it was pushed from. The integration therefore SELECTS a fixed point, and what selects it is y0. The reference does not guess: it decodes the model's own initial state, sn.state, into the fluid coordinates, so the ODE starts where the model says the system starts. Reproducing that exactly is the whole point of this file; a start that merely conserves the population is a different question with a possibly different answer.
WHERE sn.state WENT. This port's NetworkStruct carries no state field, so there is nothing to read. What the reference reads, however, is the state Network.initDefault wrote: every closed class at its reference station, one job per class in service at each Source, everything else empty, and every started job in PHASE ONE – State.fromMarginalAndStarted writes init(1) = si(r) and never enumerates the phase assignment.
THE ONE RULE THAT IS EASY TO MISS. Outside a Source, phase one of a block does NOT get kir(r,1): it gets nir(r) - sum_{k>=2} kir(r,k), the jobs in service in phase one PLUS everyone waiting in the buffer. The fluid state has no waiting room – a queue is one mass per phase – so the buffer has to land somewhere, and the reference restarts it in phase one. On the state initDefault writes every kir(r,k>=2) is zero, so that term returns the station's whole population to phase one and the decode collapses to the closed form detail::fluid_default_initsol computes directly. The rule is recorded because it is what makes the two the same vector, not because two of them are kept.
WHAT THIS FILE DOES NOT REDO. The drift, the restarting integration and the Q/U/R/T extraction of solver_fluid_closing.m are already ported in fluid_odes.h and solver_fluid.h (fluid_closing_metrics, detail::fluid_dispatch). solver_fluid_closing below is the reference function's SHAPE – seed the initial condition, gate the method, integrate – over that machinery, so there is one copy of the metric rules and not two. The reference's second output, the expanded state cell, is not ported: no caller in solver_fluid_analyzer.m reads it.
Definition in file fluid_closing.h.