75 const std::size_t M =
sn.nstations, K =
sn.nclasses;
76 for (std::size_t r = 0; r < K; ++r)
77 if (!std::isfinite(
sn.classes[r].population))
79 "fluid diffusion: the method supports closed networks only; class '" +
80 sn.classes[r].name +
"' is open");
81 for (std::size_t i = 0; i < M; ++i) {
84 throw UnsupportedError(
"fluid diffusion: a Source is not supported (station '" +
85 sn.stations[i].name +
"'); the method is for closed networks");
89 "fluid diffusion: scheduling at station '" +
sn.stations[i].name +
90 "' is outside the supported set {PS, FCFS, INF, SIRO}");
91 const double c =
sn.stations[i].nservers;
92 if (std::isfinite(c) && c > 1.0)
94 "fluid diffusion: only single-server or infinite-server stations are supported; "
95 "station '" +
sn.stations[i].name +
"' has more than one server");
99 Matrix<double> mu_inv(M, K, std::numeric_limits<double>::infinity());
100 for (std::size_t i = 0; i < M; ++i)
101 for (std::size_t r = 0; r < K; ++r) {
102 if (
sn.disabled[i][r] ||
sn.service[i][r].D0.rows() == 0)
continue;
104 if (rate > 0.0 && std::isfinite(rate)) mu_inv(i, r) = 1.0 / rate;
108 const std::size_t S =
sn.nof_stateful();
109 std::vector<std::size_t> keep;
111 for (std::size_t i = 0; i < M; ++i) {
112 const std::size_t isf =
sn.stateful_of_station(i + 1) - 1;
113 for (std::size_t r = 0; r < K; ++r) keep.push_back(isf * K + r);
116 if (
sn.rt.rows() == S * K)
117 for (std::size_t a = 0; a < S * K; ++a)
118 for (std::size_t b = 0; b < S * K; ++b)
122 const std::size_t steps = std::max<std::size_t>(2,
opt.steps);
123 std::mt19937_64
rng(
opt.seed);
124 std::normal_distribution<double> gauss(0.0, 1.0);
128 for (std::size_t r = 0; r < K; ++r)
129 for (std::size_t i = 0; i < M; ++i)
130 x(i, r) =
sn.classes[r].population /
static_cast<double>(M);
131 for (std::size_t i = 0; i < M; ++i)
132 for (std::size_t r = 0; r < K; ++r) avg(i, r) = x(i, r) /
static_cast<double>(steps);
135 for (std::size_t step = 1; step < steps; ++step) {
136 for (std::size_t i = 0; i < M; ++i)
137 for (std::size_t r = 0; r < K; ++r) {
140 std::isfinite(mu_inv(i, r)) && mu_inv(i, r) > 0.0 ? x(i, r) / mu_inv(i, r) : 0.0;
142 for (std::size_t j = 0; j < M; ++j)
143 for (std::size_t q = 0; q < K; ++q) {
144 if (!(std::isfinite(mu_inv(j, q)) && mu_inv(j, q) > 0.0))
continue;
145 in += (x(j, q) / mu_inv(j, q)) * P(j * K + q, i * K + r);
147 const double dW = std::sqrt(
opt.dt) * gauss(
rng);
148 double v = x(i, r) + (in - out) *
opt.dt + dW;
149 if (v < 0.0) v = 0.0;
153 for (std::size_t r = 0; r < K; ++r) {
155 for (std::size_t i = 0; i < M; ++i) tot += xn(i, r);
156 for (std::size_t i = 0; i < M; ++i)
157 xn(i, r) = (tot > 0.0) ? xn(i, r) *
sn.classes[r].population / tot
158 :
sn.classes[r].population /
static_cast<double>(M);
160 for (std::size_t i = 0; i < M; ++i)
161 for (std::size_t r = 0; r < K; ++r) {
163 avg(i, r) += x(i, r) /
static_cast<double>(steps);