12#ifndef OPENSWMM_GW_SOURCE_FORCING_HPP
13#define OPENSWMM_GW_SOURCE_FORCING_HPP
32 std::shared_ptr<const GwSourceSeries>
series;
50 const std::vector<double>&
ordinates() const noexcept {
63 double at(
double t)
const noexcept {
68 if (t <=
times.front())
70 if (t >=
times.back())
72 const auto hi = std::upper_bound(
times.begin(),
times.end(), t);
73 const auto i =
static_cast<std::size_t
>(hi -
times.begin());
88 std::vector<std::pair<int, double>>
cells;
89 std::vector<GwResolvedSourceTerm>
terms;
121 if (!(dt > 0) || !(weight > 0) || !(s.
scale > 0))
123 const double end = t + dt, scale = weight * s.
scale;
124 std::vector<double> knots{t, end};
126 const auto& times = v.timePoints();
127 for (
auto it = std::upper_bound(times.begin(), times.end(), t);
128 it != times.end() && *it < end; ++it)
129 knots.push_back(*it);
132 for (
const auto& term : s.
terms)
134 std::sort(knots.begin(), knots.end());
135 knots.erase(std::unique(knots.begin(), knots.end()), knots.end());
136 for (std::size_t i = 1; i < knots.size(); ++i) {
137 const double a = knots[i - 1], b = knots[i], qa = s.
flow.
at(a), qb = s.
flow.
at(b);
138 std::vector<double> cuts{a, b};
139 if ((qa < 0 && qb > 0) || (qa > 0 && qb < 0))
140 cuts.insert(cuts.begin() + 1, a + (b - a) * (-qa) / (qb - qa));
141 for (std::size_t k = 1; k < cuts.size(); ++k) {
142 const double lo = cuts[k - 1], hi = cuts[k], h = hi - lo, q0 = s.
flow.
at(lo),
144 const double volume = .5 * (q0 + q1) * h * scale;
149 for (
const auto& term : s.
terms) {
150 if (term.row < 0 ||
static_cast<std::size_t
>(term.row) >= pulse.
mass.size())
152 const double c0 = term.signal.at(lo), c1 = term.signal.at(hi);
155 m = .5 * (c0 + c1) * h * term.massScale;
157 m = h * (2 * q0 * c0 + q0 * c1 + q1 * c0 + 2 * q1 * c1) / 6;
158 pulse.
mass[
static_cast<std::size_t
>(term.row)] += m * scale;
Definition ExchangeLaw.hpp:60
void integrateGwSource(const GwResolvedSource &s, double t, double dt, double weight, GwSourcePulse &pulse)
Accumulate signed water and injection/load species forcing over linear intervals.
Definition GwSourceForcing.hpp:119
Definition GwSourceForcing.hpp:84
std::string name
Definition GwSourceForcing.hpp:85
std::vector< std::pair< int, double > > cells
Definition GwSourceForcing.hpp:88
GwSourceSignal flow
Definition GwSourceForcing.hpp:87
double scale
Definition GwSourceForcing.hpp:86
std::vector< GwResolvedSourceTerm > terms
Definition GwSourceForcing.hpp:89
Definition GwSourceForcing.hpp:78
bool massRate
Definition GwSourceForcing.hpp:80
double massScale
Definition GwSourceForcing.hpp:81
int row
Definition GwSourceForcing.hpp:79
GwSourceSignal signal
Definition GwSourceForcing.hpp:82
Definition GwSourceForcing.hpp:91
std::vector< double > mass
Definition GwSourceForcing.hpp:93
double out
Definition GwSourceForcing.hpp:92
double in
Definition GwSourceForcing.hpp:92
Definition GwSourceForcing.hpp:23
std::vector< double > values
Definition GwSourceForcing.hpp:24
bool hasNegative
Definition GwSourceForcing.hpp:25
std::vector< double > times
Definition GwSourceForcing.hpp:24
Definition GwSourceForcing.hpp:27
double at(double t) const noexcept
Evaluate a constant or piecewise-linear signal with endpoint hold.
Definition GwSourceForcing.hpp:63
const std::vector< double > & timePoints() const noexcept
Borrow the signal's elapsed-second knot vector.
Definition GwSourceForcing.hpp:40
double constant
Definition GwSourceForcing.hpp:28
const std::vector< double > & ordinates() const noexcept
Borrow ordinates associated with timePoints().
Definition GwSourceForcing.hpp:50
std::shared_ptr< const GwSourceSeries > series
Definition GwSourceForcing.hpp:32
std::vector< double > values
Definition GwSourceForcing.hpp:31
std::vector< double > times
Definition GwSourceForcing.hpp:31