Class FluidRateFactors
ode_rates_closing_factors and of
the rate-factor part of fluid_drift_jacobian.
The two live in one class on purpose. The drift the ODE integrates and the
Jacobian the covariance (Lyapunov) equation reads must agree branch by branch,
or the fixed point of the mean solve is not the point at which the covariance
is linearised; keeping them in separate files is what makes that divergence
possible. PassageTimeODE and
FluidMomentTerms both delegate here, so the closing method and the
moment-closure methods evaluate literally the same shares.
sigma2 is the per-station closure variance (0: first-order
closure), lldscaling is sn.lldscaling (null: no load
dependence) and covblk carries the per-station coordinate covariance
blocks that close the capacity-share ratio at second order. All three leave
the legacy code path bit-identical when absent, so the untouched methods are
unaffected.
- See Also:
-
Constructor Summary
ConstructorsConstructorDescriptionFluidRateFactors(int M, int K, boolean[][] enabled, Matrix qIndices, Matrix Kic, Matrix nservers, Matrix w, SchedStrategy[] sched, Matrix lldscaling) -
Method Summary
Modifier and TypeMethodDescriptionvoidRefuses any station whose discipline has no drift branch, naming it.intdriftKinkStation(double[] x, double[] sigma2) First station whose population sits ON the saturation kink n_i = c_i of the first-order rate factor, or -1 when none does.int[]driftKinkStations(double[] x, double[] sigma2) Every station sitting on the saturation kink, empty when none does.Per-coordinate service share, before event indexing and before the constant rate factors are applied.static booleanScheduling disciplines with a branch below.Analytic Jacobian dg/dx of the rate factors, mirroringfactors(double[], double[], jline.util.matrix.Matrix[])branch by branch.double[]nudgedOffKink(double[] x, double[] sigma2, double rel) A copy ofxwith every station sitting on its saturation kink moved toc_i*(1+rel), i.e.
-
Constructor Details
-
FluidRateFactors
public FluidRateFactors(int M, int K, boolean[][] enabled, Matrix qIndices, Matrix Kic, Matrix nservers, Matrix w, SchedStrategy[] sched, Matrix lldscaling) - Parameters:
M- number of stationsK- number of classesenabled- per-(station,class) service flagqIndices- per-(station,class) first state coordinate (0-based)Kic- per-(station,class) phase countnservers- per-station server countw- per-(station,class) DPS/GPS weight, 1 elsewheresched- per-station scheduling strategylldscaling-sn.lldscaling, null when the model has none
-
-
Method Details
-
isSupported
Scheduling disciplines with a branch below. Anything else would keeprates = x, i.e. be integrated as an INFINITE SERVER, and the answer would be wrong without any warning: on Delay(Z=1) -> Queue(c=1), N=4, exact Q2 = 3.0154, the fall-through returns 2.0000. -
checkSupported
public void checkSupported()Refuses any station whose discipline has no drift branch, naming it.Called before the drift is built rather than left to a fall-through: the metric readers accept SIRO as FCFS, so an unguarded SIRO station was integrated as INF while its metrics were read as if it shared the server, and every closing-family method returned a wrong answer silently.
-
driftKinkStation
public int driftKinkStation(double[] x, double[] sigma2) First station whose population sits ON the saturation kink n_i = c_i of the first-order rate factor, or -1 when none does.With sigma2 = 0 the occupancy factor is min(n_i, c_i), whose derivative is the indicator of the unsaturated region: slope 1 below c_i, slope 0 above, and NO derivative at c_i itself.
jacobian(double[], double[], jline.util.matrix.Matrix[])resolves the tie with a strictn_i > c_i, as do the MATLAB and Python twins, so it silently returns the left slope there. That one-sided value is not the a.e. derivative, and which side a fixed point lands on is decided by the integrator's rounding residue rather than by the model: the same network at N=4 converges to n_i = c_i exactly here and to c_i + 3e-6 in Python, which flipped a Jacobian eigenvalue between -0.5 and 0 and hence the hyperbolicity verdict. Callers that need a differentiable drift must consult this instead of trusting the tie-break.Only the branches that take the indicator derivative can sit on a kink: a positive sigma2 or a load-dependent row makes the closure smooth, and an infinite server never saturates.
- Parameters:
x- phase-resolved statesigma2- per-station population variance, null or all-zero for the first-order closure- Returns:
- the station index, or -1 when every station is off its kink
-
driftKinkStations
public int[] driftKinkStations(double[] x, double[] sigma2) Every station sitting on the saturation kink, empty when none does. Same test asdriftKinkStation(double[], double[]), which is its first element.- Parameters:
x- phase-resolved statesigma2- per-station population variance, null or all-zero for the first-order closure- Returns:
- the station indices, in increasing order
-
nudgedOffKink
public double[] nudgedOffKink(double[] x, double[] sigma2, double rel) A copy ofxwith every station sitting on its saturation kink moved toc_i*(1+rel), i.e. strictly onto one side of it.The point of the copy is that the kink is a measure-zero event whose TIE-BREAK is arbitrary while its two one-sided Jacobians are both perfectly well defined. Evaluating the drift at the two nudged points is how a caller asks whether the side matters: if both sides agree on the verdict it wants, the tie-break is inconsequential and the reference's strict
n_i > c_imay be used; if they disagree, the answer would be decided by the integrator's rounding residue instead of by the model.The station's coordinates are scaled together, so the phase mix and every other station are untouched.
- Parameters:
x- phase-resolved staterel- signed relative offset from the server count, e.g. 1e-6- Returns:
- the nudged state, or
xitself when no station is on a kink
-
factors
Per-coordinate service share, before event indexing and before the constant rate factors are applied.- Parameters:
x- phase-resolved statesigma2- per-station population variance, null or zero for the first-order closurecovblk- per-station coordinate covariance blocks, null for the plug-in share- Returns:
- one share per state coordinate
-
jacobian
Analytic Jacobian dg/dx of the rate factors, mirroringfactors(double[], double[], jline.util.matrix.Matrix[])branch by branch.With sigma2 = 0 the derivative of the occupancy factor is the indicator of the unsaturated region, i.e. the a.e. derivative of the first-order closure. With sigma2 > 0 it is the smooth derivative of the Gaussian closure.
- Parameters:
x- phase-resolved statesigma2- per-station population variancecovblk- per-station coordinate covariance blocks- Returns:
- the (n x n) Jacobian of the rate factors
-