12#ifndef OPENSWMM_RUNTIME_COUPLING_HPP
13#define OPENSWMM_RUNTIME_COUPLING_HPP
16#include <unordered_map>
39 double until = std::numeric_limits<double>::infinity();
45 std::vector<RuntimeSource>
rows;
46 std::vector<std::vector<std::size_t>>
cells;
47 std::unordered_map<std::string, std::unordered_map<int, std::size_t>>
index;
57 const auto a =
index.find(
id);
60 const auto b = a->second.find(cell);
61 return b == a->second.end() ? nullptr : &
rows[b->second];
86 cells.assign(count, {});
87 for (std::size_t k = 0; k <
rows.size(); ++k)
103 if (
auto* row =
find(value.id, value.cell)) {
104 value.receipt = std::move(row->receipt);
105 *row = std::move(value);
108 index[value.id][value.cell] =
rows.size();
109 value.receipt.requested_mass.assign(value.concentrations.size(), 0.0);
110 value.receipt.applied_mass.assign(value.concentrations.size(), 0.0);
111 rows.push_back(std::move(value));
120 for (
auto& cell :
cells)
121 cell.erase(std::remove_if(cell.begin(), cell.end(),
122 [
this](
auto k) { return !rows[k].enabled; }),
135 bool clear(
const std::string&
id,
int cell = -1) noexcept {
136 const auto found =
index.find(
id);
137 if (found ==
index.end())
140 auto* row =
find(
id, cell);
143 row->enabled =
false;
144 if (cell <
static_cast<int>(
cells.size())) {
147 [
this](
auto k) { return !rows[k].enabled; }),
152 for (
const auto& entry : found->second)
153 rows[entry.second].enabled =
false;
167 for (
auto& row :
rows)
168 if (
const auto* previous = old.
find(row.id, row.cell))
169 row.receipt = previous->receipt;
178 for (
const auto& r :
rows)
192 double next = std::numeric_limits<double>::infinity();
193 for (
const auto& r :
rows)
194 if (r.enabled && r.until > now)
195 next = std::min(next, r.until);
206 bool changed =
false;
208 if (r.enabled && r.until <= now) {
220 double rate = 0.0,
until = std::numeric_limits<double>::infinity();
227 std::vector<RuntimeForcing>
rows;
228 std::vector<std::array<int, 4>>
cells;
230 std::unordered_map<int, std::unordered_map<int, std::size_t>>
index;
240 auto a =
index.find(channel);
241 if (a ==
index.end())
243 auto b = a->second.find(cell);
244 return b == a->second.end() ? nullptr : &
rows[b->second];
257 int k = cell >= 0 && cell < static_cast<int>(
cells.size()) ?
cells[cell][channel - 1] : -1;
258 if (k < 0 || !
rows[k].enabled)
260 return k >= 0 &&
rows[k].enabled ? &
rows[k] :
nullptr;
271 double rate(
int channel,
int cell,
double native)
const noexcept {
272 const auto* row =
get(channel, cell);
273 return !row ? native : row->mode == 2 ? native + row->rate : row->rate;
287 row.
receipt = std::move(old->receipt);
288 *old = std::move(row);
291 rows.push_back(std::move(row));
305 cells.assign(count, {{-1, -1, -1, -1}});
307 for (std::size_t k = 0; k <
rows.size(); ++k)
308 if (
rows[k].enabled) {
309 const auto& row =
rows[k];
311 uniform[row.channel - 1] =
static_cast<int>(k);
313 cells.at(row.cell)[row.channel - 1] =
static_cast<int>(k);
323 for (
const auto& row :
rows)
337 double time = std::numeric_limits<double>::infinity();
338 for (
const auto& row :
rows)
339 if (row.enabled && row.until > now)
340 time = std::min(time, row.until);
351 for (
auto& row :
rows)
352 if (row.enabled && row.until <= now)
Definition ExchangeLaw.hpp:60
constexpr double runtimeWaterHeatCapacity
Definition RuntimeCoupling.hpp:25
Definition RuntimeCoupling.hpp:218
int cell
Definition RuntimeCoupling.hpp:219
std::vector< double > concentrations
Definition RuntimeCoupling.hpp:223
double until
Definition RuntimeCoupling.hpp:220
std::string owner
Definition RuntimeCoupling.hpp:222
RuntimeReceipt receipt
Definition RuntimeCoupling.hpp:224
int mode
Definition RuntimeCoupling.hpp:219
double rate
Definition RuntimeCoupling.hpp:220
bool enabled
Definition RuntimeCoupling.hpp:221
int channel
Definition RuntimeCoupling.hpp:219
Definition RuntimeCoupling.hpp:226
std::vector< std::array< int, 4 > > cells
Definition RuntimeCoupling.hpp:228
double rate(int channel, int cell, double native) const noexcept
Resolve a forced scalar rate from a native value.
Definition RuntimeCoupling.hpp:271
const RuntimeForcing * get(int channel, int cell) const noexcept
Resolve enabled cell-specific forcing with uniform fallback.
Definition RuntimeCoupling.hpp:256
std::vector< RuntimeForcing > rows
Definition RuntimeCoupling.hpp:227
void expire(double now) noexcept
Disable all enabled prescriptions whose expiry has been reached.
Definition RuntimeCoupling.hpp:350
bool active() const noexcept
Test whether any retained runtime prescription is enabled.
Definition RuntimeCoupling.hpp:322
void rebuild(int count)
Rebuild channel/cell and uniform forcing gather indices.
Definition RuntimeCoupling.hpp:304
std::unordered_map< int, std::unordered_map< int, std::size_t > > index
Definition RuntimeCoupling.hpp:230
std::array< int, 4 > uniform
Definition RuntimeCoupling.hpp:229
double nextTime(double now) const noexcept
Find the next enabled prescription expiry strictly after now.
Definition RuntimeCoupling.hpp:336
RuntimeForcing * find(int channel, int cell)
Find an exact channel/cell forcing row, including disabled retained rows.
Definition RuntimeCoupling.hpp:239
void replace(RuntimeForcing row)
Upsert one forcing prescription while retaining its accumulated receipt.
Definition RuntimeCoupling.hpp:285
Definition RuntimeCoupling.hpp:26
double last_dt
Definition RuntimeCoupling.hpp:30
double last_flow
Definition RuntimeCoupling.hpp:30
std::vector< double > requested_mass
Definition RuntimeCoupling.hpp:31
double requested
Definition RuntimeCoupling.hpp:27
double applied
Definition RuntimeCoupling.hpp:27
double heat_requested
Definition RuntimeCoupling.hpp:29
double water_out
Definition RuntimeCoupling.hpp:28
double heat_applied
Definition RuntimeCoupling.hpp:29
double water_in
Definition RuntimeCoupling.hpp:28
std::vector< double > applied_mass
Definition RuntimeCoupling.hpp:31
Definition RuntimeCoupling.hpp:33
double flow
Definition RuntimeCoupling.hpp:36
bool enabled
Definition RuntimeCoupling.hpp:40
double boundary_head
Definition RuntimeCoupling.hpp:38
int boundary_edge
Definition RuntimeCoupling.hpp:37
std::vector< double > rates
Definition RuntimeCoupling.hpp:41
RuntimeReceipt receipt
Definition RuntimeCoupling.hpp:42
int cell
Definition RuntimeCoupling.hpp:35
std::vector< double > concentrations
Definition RuntimeCoupling.hpp:41
std::string owner
Definition RuntimeCoupling.hpp:34
double until
Definition RuntimeCoupling.hpp:39
std::string id
Definition RuntimeCoupling.hpp:34
double heat
Definition RuntimeCoupling.hpp:36
Definition RuntimeCoupling.hpp:44
bool clear(const std::string &id, int cell=-1) noexcept
Disable one source-cell key or every cell belonging to a source id.
Definition RuntimeCoupling.hpp:135
std::unordered_map< std::string, std::unordered_map< int, std::size_t > > index
Definition RuntimeCoupling.hpp:47
const RuntimeSource * find(const std::string &id, int cell) const
Find a source prescription by its exact registry key.
Definition RuntimeCoupling.hpp:71
bool expire(double now)
Disable all enabled prescriptions whose expiry has been reached.
Definition RuntimeCoupling.hpp:205
void syncReceipts(const RuntimeSources &old)
Copy matching accepted receipts into a staged source registry.
Definition RuntimeCoupling.hpp:166
bool active() const
Test whether any retained runtime prescription is enabled.
Definition RuntimeCoupling.hpp:177
void rebuild(int count)
Recreate enabled source-to-cell gather indices.
Definition RuntimeCoupling.hpp:85
void replace(RuntimeSource value)
Upsert a source prescription while preserving accumulated receipts.
Definition RuntimeCoupling.hpp:102
double nextTime(double now) const
Find the next enabled prescription expiry strictly after now.
Definition RuntimeCoupling.hpp:191
RuntimeSource * find(const std::string &id, int cell)
Find a source prescription by its exact registry key.
Definition RuntimeCoupling.hpp:56
std::vector< std::vector< std::size_t > > cells
Definition RuntimeCoupling.hpp:46
std::vector< RuntimeSource > rows
Definition RuntimeCoupling.hpp:45
void prune() noexcept
Remove disabled row offsets from every cell gather list.
Definition RuntimeCoupling.hpp:119