88 std::vector<std::size_t> covered;
89 for (std::size_t c = 0; c < cells.size(); ++c)
90 covered.insert(covered.end(), cells[c].begin(), cells[c].end());
91 std::sort(covered.begin(), covered.end());
92 bool ok = covered.size() ==
sn.nstations;
93 for (std::size_t i = 0; ok && i < covered.size(); ++i) ok = covered[i] == i;
95 throw InputError(
"tbi_partition: options.tbi_cells must be a partition of the station set "
96 "0.." + std::to_string(
sn.nstations == 0 ? 0 :
sn.nstations - 1) +
104 std::size_t cellsize = 5) {
105 const std::size_t M =
sn.nstations, K =
sn.nclasses;
106 std::vector<std::vector<std::size_t>> cells;
107 for (std::size_t i = 0; i < M; ++i) cells.push_back(std::vector<std::size_t>{i});
108 if (cellsize == 0)
return cells;
109 const std::size_t target = std::max<std::size_t>(1, (M + cellsize - 1) / cellsize);
110 if (cells.size() <= target)
return cells;
113 const std::size_t S =
sn.nof_stateful();
115 if (
sn.rt.rows() == S * K)
116 for (std::size_t i = 0; i < M; ++i) {
117 const std::size_t si =
sn.stateful_of_station(i + 1) - 1;
118 for (std::size_t j = 0; j < M; ++j) {
119 const std::size_t sj =
sn.stateful_of_station(j + 1) - 1;
121 for (std::size_t a = 0; a < K; ++a)
122 for (std::size_t b = 0; b < K; ++b)
128 for (std::size_t i = 0; i < M; ++i) C(i, i) = 0.0;
130 while (cells.size() > target) {
131 const std::size_t n = cells.size();
133 std::size_t
ba = n, bb = n;
134 for (std::size_t a = 0; a < n; ++a)
135 for (std::size_t b = a + 1; b < n; ++b) {
136 if (cells[a].size() + cells[b].size() > 2 * cellsize)
continue;
137 if (C(a, b) > best) {
144 std::vector<std::size_t> ord(n);
145 for (std::size_t i = 0; i < n; ++i) ord[i] = i;
146 std::sort(ord.begin(), ord.end(),
147 [&](std::size_t p, std::size_t q) { return cells[p].size() < cells[q].size(); });
148 ba = std::min(ord[0], ord[1]);
149 bb = std::max(ord[0], ord[1]);
151 cells[
ba].insert(cells[
ba].end(), cells[bb].begin(), cells[bb].end());
152 for (std::size_t k = 0; k < n; ++k) {
153 C(
ba, k) += C(bb, k);
154 C(k,
ba) += C(k, bb);
159 for (std::size_t a = 0, aa = 0; a < n; ++a) {
160 if (a == bb)
continue;
161 for (std::size_t b = 0, bbi = 0; b < n; ++b) {
162 if (b == bb)
continue;
163 C2(aa, bbi) = C(a, b);
169 cells.erase(cells.begin() +
static_cast<long>(bb));
171 for (std::vector<std::size_t>& c : cells) std::sort(c.begin(), c.end());
190 const std::vector<std::vector<std::size_t>>& cells,
191 const std::vector<double>& y0,
double t0,
double t1,
194 const std::size_t n = L.
nstates, ncells = cells.size();
195 const std::size_t K = L.
qidx.empty() ? 0 : L.
qidx[0].size();
200 std::vector<std::vector<std::size_t>> mask(ncells);
201 std::vector<std::vector<std::size_t>> eint(ncells), eext(ncells);
202 std::vector<std::vector<long>> g2l(ncells, std::vector<long>(n, -1));
203 for (std::size_t kc = 0; kc < ncells; ++kc) {
204 for (std::size_t i : cells[kc])
205 for (std::size_t r = 0; r < K; ++r)
206 for (std::size_t k = 0; k < L.
kic[i][r]; ++k) mask[kc].push_back(L.
qidx[i][r] + k);
207 std::sort(mask[kc].begin(), mask[kc].end());
208 for (std::size_t a = 0; a < mask[kc].size(); ++a) g2l[kc][mask[kc][a]] =
static_cast<long>(a);
209 for (std::size_t e = 0; e < sys.
events.size(); ++e) {
210 const bool inside = g2l[kc][sys.
events[e].event_idx] >= 0;
212 eint[kc].push_back(e);
213 }
else if (g2l[kc][sys.
events[e].minus] >= 0 || g2l[kc][sys.
events[e].plus] >= 0) {
214 eext[kc].push_back(e);
219 const std::size_t ng = std::max<std::size_t>(2, topt.
grid);
220 std::vector<double> tgrid(ng);
221 for (std::size_t j = 0; j < ng; ++j)
222 tgrid[j] = t0 + (t1 - t0) *
static_cast<double>(j) /
static_cast<double>(ng - 1);
225 std::vector<std::vector<double>> Y(ng, y0);
227 for (std::size_t sweep = 0; sweep < topt.
tbi_iter_max; ++sweep) {
228 std::vector<std::vector<double>> Ynew = Y;
230 for (std::size_t kc = 0; kc < ncells; ++kc) {
231 const std::size_t nl = mask[kc].size();
232 if (nl == 0)
continue;
235 std::vector<std::vector<double>> B(ng, std::vector<double>(nl, 0.0));
236 for (std::size_t j = 0; j < ng; ++j) {
237 std::vector<double> g(Y[j]);
239 for (std::size_t e : eext[kc]) {
242 if (rate == 0.0)
continue;
243 if (g2l[kc][ev.
minus] >= 0) B[j][
static_cast<std::size_t
>(g2l[kc][ev.
minus])] -= rate;
244 if (g2l[kc][ev.
plus] >= 0) B[j][
static_cast<std::size_t
>(g2l[kc][ev.
plus])] += rate;
250 const std::vector<std::size_t>& mk = mask[kc];
251 const std::vector<std::size_t>& ei = eint[kc];
252 const std::vector<long>& gl = g2l[kc];
253 std::vector<double> full(n, 0.0);
254 const LsodaRhs f = [&sys, &mk, &ei, &gl, &B, &tgrid, ng, nl, n,
255 &full](
double t,
const double* xc,
double* dxc) {
256 std::vector<double> x(n, 0.0);
257 for (std::size_t a = 0; a < nl; ++a) x[mk[a]] = xc[a];
258 std::vector<double> g(x);
260 for (std::size_t a = 0; a < nl; ++a) dxc[a] = 0.0;
261 for (std::size_t e : ei) {
264 if (rate == 0.0)
continue;
265 if (gl[ev.
minus] >= 0) dxc[
static_cast<std::size_t
>(gl[ev.
minus])] -= rate;
266 if (gl[ev.
plus] >= 0) dxc[
static_cast<std::size_t
>(gl[ev.
plus])] += rate;
269 double u = (t - tgrid.front()) / (tgrid.back() - tgrid.front() + 1e-300);
270 u = std::min(1.0, std::max(0.0, u)) *
static_cast<double>(ng - 1);
271 const std::size_t j0 = std::min<std::size_t>(ng - 2,
static_cast<std::size_t
>(u));
272 const double w = u -
static_cast<double>(j0);
273 for (std::size_t a = 0; a < nl; ++a)
274 dxc[a] += (1.0 - w) * B[j0][a] + w * B[j0 + 1][a];
277 std::vector<double> yl(nl, 0.0);
278 for (std::size_t a = 0; a < nl; ++a) yl[a] = y0[mk[a]];
280 for (std::size_t j = 0; j < s.
y.size() && j < ng; ++j)
281 for (std::size_t a = 0; a < nl; ++a) {
282 double v = s.
y[j][a];
283 if (v < 0.0) v = 0.0;
284 delta = std::max(delta, std::fabs(v - Ynew[j][mk[a]]));
291 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.