1function [ode_h,q_indices] = solver_fluid_odes(sn, N, Mu, phi, PH,
P, nservers, sched, schedparam, options)
2% [ODE_H,Q_INDICES] = SOLVER_FLUID_ODES(sn, N, MU, PHI, PH,
P, NSERVERS, SCHED, SCHEDPARAM)
4% Copyright (c) 2012-2026, Imperial College London
7M = length(nservers); % number of stations
8K = length(Mu{1}); % number of
classes
11enabled =
false(M,K); % indicates whether a
class is served at a station
14% %enabled(i,c) = sum(
P(:,(i-1)*K+c) ) > 0;
15% %changed to consider rows instead of columns,
for response time
16% %analysis (first articial
class never returns to delay node)
17% enabled(i,c) = sum(
P((i-1)*K+c,:) ) > 0;
21q_indices = zeros(M,K);
29 q_indices(i,c) = cumsum;
30 elseif isempty(Mu{i}{c})
33 q_indices(i,c) = cumsum;
35 numphases = length(Mu{i}{c});
36 q_indices(i,c) = cumsum;
40 cumsum = cumsum + numphases;
44% to speed up convert sched strings in numerical values
46 switch sched(i) % source
47 case SchedStrategy.DPS
48 w(i,:) = schedparam(i,:);
52%% define ODE system to be returned
55 alpha = 20; % softmin parameter
56 ode_sm_h = @(t,x) ode_softmin(x, phi, Mu, PH, M, K, enabled, q_indices,
P, Kic, nservers, w, sched, alpha);
59 % p-norm smoothing method based on Ruuskanen et al., PEVA 151 (2021)
60 if isfield(options,
'pstar') && ~isempty(options.pstar)
61 pstar = options.pstar;
63 pstar = 20; % default p-norm parameter (similar behavior to softmin at alpha=20)
65 ode_pn_h = @(t,x) ode_pnorm(x, phi, Mu, PH, M, K, enabled, q_indices,
P, Kic, nservers, w, sched, pstar);
68 ode_sd_h = @(t,x) ode_statedep(x, phi, Mu, PH, M, K, enabled, q_indices,
P, Kic, nservers, w, sched);
71 % determine all the jumps, and saves them for later use
72 all_jumps = ode_jumps_new(M, K, enabled, q_indices,
P, Kic);
73 % determines a vector with the fixed part of the rates,
74 % and defines the indexes that correspond to the events that occur
75 [rateBase, eventIdx] = ode_rate_base(sn, phi, Mu, PH, M, K, enabled, q_indices,
P, Kic, sched, all_jumps);
77 % Eliminate immediate transitions if requested
78 if isfield(options.config, 'hide_immediate') && options.config.hide_immediate
79 if isfield(options, 'verbose') && options.verbose >= VerboseLevel.DEBUG
80 fprintf('[DEBUG] Calling immediate elimination (hide_immediate=true)\n');
82 [all_jumps, rateBase, eventIdx, state_map] = ...
83 ode_eliminate_immediate(all_jumps, rateBase, eventIdx, sn, options);
85 if isfield(options, 'verbose') && options.verbose >= VerboseLevel.DEBUG
86 fprintf('[DEBUG] Skipping immediate elimination (hide_immediate=false)\n');
90 ode_si_h = @(t,x) all_jumps * ode_rates_closing(x, M, K, enabled, q_indices, Kic, nservers, w, sched, rateBase, eventIdx);