81 std::size_t cellsize = 5) {
82 const std::size_t M =
sn.nstations, K =
sn.nclasses;
83 std::vector<std::vector<std::size_t>> cells;
84 for (std::size_t i = 0; i < M; ++i) cells.push_back(std::vector<std::size_t>{i});
85 if (cellsize == 0)
return cells;
86 const std::size_t target = std::max<std::size_t>(1, (M + cellsize - 1) / cellsize);
87 if (cells.size() <= target)
return cells;
90 const std::size_t S =
sn.nof_stateful();
92 if (
sn.rt.rows() == S * K)
93 for (std::size_t i = 0; i < M; ++i) {
94 const std::size_t si =
sn.stateful_of_station(i + 1) - 1;
95 for (std::size_t j = 0; j < M; ++j) {
96 const std::size_t sj =
sn.stateful_of_station(j + 1) - 1;
98 for (std::size_t a = 0; a < K; ++a)
99 for (std::size_t b = 0; b < K; ++b)
105 for (std::size_t i = 0; i < M; ++i) C(i, i) = 0.0;
107 while (cells.size() > target) {
108 const std::size_t n = cells.size();
110 std::size_t
ba = n, bb = n;
111 for (std::size_t a = 0; a < n; ++a)
112 for (std::size_t b = a + 1; b < n; ++b) {
113 if (cells[a].size() + cells[b].size() > 2 * cellsize)
continue;
114 if (C(a, b) > best) {
121 std::vector<std::size_t> ord(n);
122 for (std::size_t i = 0; i < n; ++i) ord[i] = i;
123 std::sort(ord.begin(), ord.end(),
124 [&](std::size_t p, std::size_t q) { return cells[p].size() < cells[q].size(); });
125 ba = std::min(ord[0], ord[1]);
126 bb = std::max(ord[0], ord[1]);
128 cells[
ba].insert(cells[
ba].end(), cells[bb].begin(), cells[bb].end());
129 for (std::size_t k = 0; k < n; ++k) {
130 C(
ba, k) += C(bb, k);
131 C(k,
ba) += C(k, bb);
136 for (std::size_t a = 0, aa = 0; a < n; ++a) {
137 if (a == bb)
continue;
138 for (std::size_t b = 0, bbi = 0; b < n; ++b) {
139 if (b == bb)
continue;
140 C2(aa, bbi) = C(a, b);
146 cells.erase(cells.begin() +
static_cast<long>(bb));
148 for (std::vector<std::size_t>& c : cells) std::sort(c.begin(), c.end());
167 const std::vector<std::vector<std::size_t>>& cells,
168 const std::vector<double>& y0,
double t0,
double t1,
171 const std::size_t n = L.
nstates, ncells = cells.size();
172 const std::size_t K = L.
qidx.empty() ? 0 : L.
qidx[0].size();
177 std::vector<std::vector<std::size_t>> mask(ncells);
178 std::vector<std::vector<std::size_t>> eint(ncells), eext(ncells);
179 std::vector<std::vector<long>> g2l(ncells, std::vector<long>(n, -1));
180 for (std::size_t kc = 0; kc < ncells; ++kc) {
181 for (std::size_t i : cells[kc])
182 for (std::size_t r = 0; r < K; ++r)
183 for (std::size_t k = 0; k < L.
kic[i][r]; ++k) mask[kc].push_back(L.
qidx[i][r] + k);
184 std::sort(mask[kc].begin(), mask[kc].end());
185 for (std::size_t a = 0; a < mask[kc].size(); ++a) g2l[kc][mask[kc][a]] =
static_cast<long>(a);
186 for (std::size_t e = 0; e < sys.
events.size(); ++e) {
187 const bool inside = g2l[kc][sys.
events[e].event_idx] >= 0;
189 eint[kc].push_back(e);
190 }
else if (g2l[kc][sys.
events[e].minus] >= 0 || g2l[kc][sys.
events[e].plus] >= 0) {
191 eext[kc].push_back(e);
196 const std::size_t ng = std::max<std::size_t>(2, topt.
grid);
197 std::vector<double> tgrid(ng);
198 for (std::size_t j = 0; j < ng; ++j)
199 tgrid[j] = t0 + (t1 - t0) *
static_cast<double>(j) /
static_cast<double>(ng - 1);
202 std::vector<std::vector<double>> Y(ng, y0);
204 for (std::size_t sweep = 0; sweep < topt.
tbi_iter_max; ++sweep) {
205 std::vector<std::vector<double>> Ynew = Y;
207 for (std::size_t kc = 0; kc < ncells; ++kc) {
208 const std::size_t nl = mask[kc].size();
209 if (nl == 0)
continue;
212 std::vector<std::vector<double>> B(ng, std::vector<double>(nl, 0.0));
213 for (std::size_t j = 0; j < ng; ++j) {
214 std::vector<double> g(Y[j]);
216 for (std::size_t e : eext[kc]) {
219 if (rate == 0.0)
continue;
220 if (g2l[kc][ev.
minus] >= 0) B[j][
static_cast<std::size_t
>(g2l[kc][ev.
minus])] -= rate;
221 if (g2l[kc][ev.
plus] >= 0) B[j][
static_cast<std::size_t
>(g2l[kc][ev.
plus])] += rate;
227 const std::vector<std::size_t>& mk = mask[kc];
228 const std::vector<std::size_t>& ei = eint[kc];
229 const std::vector<long>& gl = g2l[kc];
230 std::vector<double> full(n, 0.0);
231 const LsodaRhs f = [&sys, &mk, &ei, &gl, &B, &tgrid, ng, nl, n,
232 &full](
double t,
const double* xc,
double* dxc) {
233 std::vector<double> x(n, 0.0);
234 for (std::size_t a = 0; a < nl; ++a) x[mk[a]] = xc[a];
235 std::vector<double> g(x);
237 for (std::size_t a = 0; a < nl; ++a) dxc[a] = 0.0;
238 for (std::size_t e : ei) {
241 if (rate == 0.0)
continue;
242 if (gl[ev.
minus] >= 0) dxc[
static_cast<std::size_t
>(gl[ev.
minus])] -= rate;
243 if (gl[ev.
plus] >= 0) dxc[
static_cast<std::size_t
>(gl[ev.
plus])] += rate;
246 double u = (t - tgrid.front()) / (tgrid.back() - tgrid.front() + 1e-300);
247 u = std::min(1.0, std::max(0.0, u)) *
static_cast<double>(ng - 1);
248 const std::size_t j0 = std::min<std::size_t>(ng - 2,
static_cast<std::size_t
>(u));
249 const double w = u -
static_cast<double>(j0);
250 for (std::size_t a = 0; a < nl; ++a)
251 dxc[a] += (1.0 - w) * B[j0][a] + w * B[j0 + 1][a];
254 std::vector<double> yl(nl, 0.0);
255 for (std::size_t a = 0; a < nl; ++a) yl[a] = y0[mk[a]];
257 for (std::size_t j = 0; j < s.
y.size() && j < ng; ++j)
258 for (std::size_t a = 0; a < nl; ++a) {
259 double v = s.
y[j][a];
260 if (v < 0.0) v = 0.0;
261 delta = std::max(delta, std::fabs(v - Ynew[j][mk[a]]));
268 if (delta < topt.
tbi_tol)
break;
LsodaSolution fluid_integrate_grid(const std::function< void(double, const double *, double *)> &f, const std::vector< double > &y0, const std::vector< double > &grid, const LsodaOptions &lopt)
The same retry over a whole output grid, for the callers that ask LSODA for a trajectory rather than ...
std::vector< double > tbi_advance(const FluidOdeSystem &sys, const std::vector< std::vector< std::size_t > > &cells, const std::vector< double > &y0, double t0, double t1, const TbiOptions &topt, const LsodaOptions &lopt)
Advance the state over [t0, t1] by time-based iteration.