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

The second-order fluid methods: fluid_moment_terms.m, fluid_lyapunov.m, fluid_drift_jacobian.m, fluid_refine_meanfield.m and solver_fluid_moments.m, which back options.method minnormal and refined. More...

#include "line/util/line_console.h"
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <limits>
#include <string>
#include <vector>
#include "line/lang/qn/network_struct.h"
#include "line/solvers/fluid/fluid_closures.h"
#include "line/solvers/fluid/fluid_nonhyperbolic.h"
#include "line/solvers/fluid/fluid_odes.h"
#include "line/solvers/fluid/solver_fluid.h"
#include "line/util/eig.h"
#include "line/util/error.h"
#include "line/util/linalg.h"
#include "line/util/matrix.h"
#include "line/util/svd.h"
#include "line/util/sylvester.h"
Include dependency graph for fluid_moments.h:

Go to the source code of this file.

Classes

struct  line::fluid::FluidLyapunovInfo
 The reference's MException('LINE:FluidNonHyperbolic'), as a type. More...
struct  line::fluid::FluidMomentTerms
 Port of fluid_moment_terms.m: the event representation of the fluid population process, plus the drift, rate and Jacobian handles the covariance equation needs. More...
struct  line::fluid::FluidRefineInfo
 What fluid_refine_meanfield reports about the correction it computed. More...

Namespaces

namespace  line
namespace  line::fluid

Functions

FluidClosure line::fluid::fluid_blend_closure (const FluidClosure &a, const FluidClosure &b, double step)
 a + step*(b - a) for a closure, entry by entry.
Matrix< double > line::fluid::fluid_lyapunov (const Matrix< double > &A, const Matrix< double > &Qdiff, const Matrix< double > &D, FluidLyapunovInfo &info, double tol=-1.0)
 Port of fluid_lyapunov.m: the stationary covariance of the linear noise approximation.
bool line::fluid::fluid_coord_eliminated (const FluidMomentTerms &t, std::size_t s)
 True when the immediate reduction folded coordinate s away, so the reduced drift holds no mass there and no event lands on it.
template<class T>
FluidMomentTerms line::fluid::fluid_moment_terms (const qn::NetworkStruct< T > &sn, const FluidOptions &opt)
std::vector< double > line::fluid::fluid_moment_factors (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl)
 The rate factors g(x) under a closure: terms.factorFcn.
std::vector< double > line::fluid::fluid_moment_rates (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl)
 The event rates r(x) under a closure: terms.ratesFcn.
std::vector< double > line::fluid::fluid_moment_drift (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl)
 The drift F(x) = D r(x) under a closure: terms.driftFcn.
Matrix< double > line::fluid::fluid_drift_jacobian (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl)
 Port of fluid_drift_jacobian.m: the analytic Jacobian of the fluid drift.
std::vector< std::size_t > line::fluid::fluid_kink_stations (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl)
 Every station whose population sits ON the saturation kink n_i = c_i of the first-order rate factor, in increasing order, empty when none does.
std::vector< double > line::fluid::fluid_nudge_off_kink (const FluidMomentTerms &t, const std::vector< double > &x, const std::vector< std::size_t > &kink, double rel)
 A copy of x with every station in kink moved to c_i*(1 + rel), i.e.
Matrix< double > line::fluid::fluid_moment_lyapunov (const FluidMomentTerms &t, const Matrix< double > &A, const std::vector< double > &r, const Matrix< double > *clampT=nullptr)
 local_lyapunov of solver_fluid_moments.m: the covariance on the coordinates that carry a real population, scattered back to full size.
std::vector< double > line::fluid::fluid_refine_meanfield (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl, const Matrix< double > &Sigma, FluidRefineInfo &info, double epsrel=1e-4)
 Port of fluid_refine_meanfield.m: the O(1/N) refined mean field correction of Gast (POMACS 2017).
template<class T>
FluidSolution line::fluid::solver_fluid_moments (const qn::NetworkStruct< T > &sn, const FluidOptions &opt)
 Port of solver_fluid_moments.m: the second-order fluid analysis backing minnormal and refined.

Detailed Description

The second-order fluid methods: fluid_moment_terms.m, fluid_lyapunov.m, fluid_drift_jacobian.m, fluid_refine_meanfield.m and solver_fluid_moments.m, which back options.method minnormal and refined.

WHY THE PORT NEEDED THESE AT ALL, given that the first-order methods already answered every model. minnormal is what the REFERENCE'S default resolves to wherever it applies (fluid_resolve_default_method.m), so without it the port answered a different method than the reference under the same name – and answered it less accurately, since the first-order closure replaces E[min(X,c)] by min(E[X],c) and is worst exactly at rho ~ 1. On the reference's own sweep (Delay(Z=1) -> Queue(PS, c=2), N=6) the exact CTMC queue length is 1.95137, closing returns 2.00000 and minnormal 1.96063.

WHAT THE SECOND MOMENT IS, and why a fluid solver has one. The closing ODEs are a density-dependent Markov population process

dx/dt = F(x) = D r(x),     r_e(x) = rateBase_e g_e(x)

whose fluctuation process Z = X - x* obeys, to leading order, dZ = A Z dt + sqrt(D diag(r) D') dW with A = dF/dx. That linear noise approximation has a stationary covariance, the solution of the Lyapunov equation A Sigma + Sigma A' + D diag(r) D' = 0, and THAT is the second moment reported through getMoments. solver_fluid_odes.m throws D and r away once it has composed F, which is why fluid_moment_terms rebuilds them: the diffusion matrix cannot be recovered from F alone.

THE TWO METHODS DIFFER IN WHICH FIXED POINT THEY EXPAND ABOUT, and mixing them would count the same term twice. minnormal solves mean and covariance self-consistently, so its fixed point already RESUMS the O(1/N) correction – expanding E[F(X)] to second order and setting it to zero reproduces the Gast correction equation exactly. refined therefore recomputes the base point with the FIRST-order closure and adds the correction to that.

Definition in file fluid_moments.h.