32#ifndef OPENSWMM_ENGINE_TABLE_DATA_HPP
33#define OPENSWMM_ENGINE_TABLE_DATA_HPP
38#include <unordered_map>
111 std::vector<double>
x;
112 std::vector<double>
y;
116 std::size_t
num_rows() const noexcept {
return x.size(); }
117 bool empty() const noexcept {
return x.empty(); }
130 std::vector<double>
x;
131 std::vector<double>
y;
156 std::size_t
size() const noexcept {
return x.size(); }
159 bool empty() const noexcept {
return x.empty(); }
188 const int n =
static_cast<int>(tbl.x.size());
189 if (n == 0)
return 0.0;
190 if (n == 1)
return tbl.y[0];
193 if (x_query <= tbl.x[0]) {
194 tbl.cursor.index = 0;
195 tbl.cursor.direction = +1;
203 if (x_query > tbl.x[n - 1]) {
204 tbl.cursor.index = n - 1;
205 tbl.cursor.direction = -1;
210 int idx = std::clamp(tbl.cursor.index, 0, n - 2);
213 while (idx < n - 1 && tbl.x[idx + 1] < x_query) {
215 tbl.cursor.direction = +1;
222 while (idx > 0 && tbl.x[idx] >= x_query) {
224 tbl.cursor.direction = -1;
227 tbl.cursor.index = idx;
234 const double x1 = tbl.x[idx], y1 = tbl.y[idx];
235 const double x2 = tbl.x[idx + 1], y2 = tbl.y[idx + 1];
236 const double dx = x2 - x1;
237 if (std::fabs(dx) < 1.0e-20)
return (y1 + y2) / 2.;
238 return y1 + (x_query - x1) * (y2 - y1) / dx;
259 const int n =
static_cast<int>(tbl.x.size());
260 if (n == 0)
return 0.0;
263 if (x_query <= tbl.x[0]) {
264 tbl.cursor.index = 0;
265 tbl.cursor.direction = +1;
266 return (x_query < tbl.x[0]) ? 0.0 : tbl.y[0];
268 if (x_query >= tbl.x[n - 1]) {
269 tbl.cursor.index = n - 1;
270 tbl.cursor.direction = -1;
271 return (x_query > tbl.x[n - 1]) ? 0.0 : tbl.y[n - 1];
293 const int n =
static_cast<int>(tbl.x.size());
294 if (n == 0)
return 0.0;
295 if (n == 1)
return tbl.y[0];
298 if (x_query < tbl.x[0]) {
299 tbl.cursor.index = 0;
300 tbl.cursor.direction = +1;
308 if (x_query >= tbl.x[n - 1]) {
309 tbl.cursor.index = n - 1;
310 tbl.cursor.direction = -1;
315 int idx = std::clamp(tbl.cursor.index, 0, n - 2);
317 while (idx < n - 1 && tbl.x[idx + 1] <= x_query) {
319 tbl.cursor.direction = +1;
321 while (idx > 0 && tbl.x[idx] > x_query) {
323 tbl.cursor.direction = -1;
326 tbl.cursor.index = idx;
343 const int n =
static_cast<int>(tbl.x.size());
344 if (n == 0 || depth <= 0.0)
return 0.0;
346 double x1 = tbl.x[0];
347 double a1 = tbl.y[0];
351 if (x1 < 1.0e-6)
return 0.0;
352 return (a1 / x1) * depth * depth / 2.0;
357 double dx = 0.0, dy = 0.0;
358 for (
int i = 1; i < n; ++i) {
359 double x2 = tbl.x[i];
360 double a2 = tbl.y[i];
366 const double dxi = x2 - x1;
368 if (std::fabs(dxi) < 1.0e-20) a = (a1 + a2) / 2.;
369 else a = a1 + (depth - x1) * (a2 - a1) / dxi;
370 return v + (a1 + a) / 2.0 * (depth - x1);
374 v += (a1 + a2) / 2.0 * dx;
382 double a = a1 + s * (depth - x1);
384 v -= a1 * a1 / s / 2.0;
386 v += (a1 + a) / 2.0 * (depth - x1);
409 const int n =
static_cast<int>(tbl.x.size());
410 if (n == 0 || volume <= 0.0)
return 0.0;
412 double x1 = tbl.x[0];
413 double a1 = tbl.y[0];
414 double v_accum = 0.0;
416 for (
int i = 1; i < n; ++i) {
417 double x2 = tbl.x[i];
418 double a2 = tbl.y[i];
419 double dv = (a1 + a2) / 2.0 * (x2 - x1);
421 if (v_accum + dv >= volume) {
427 double dv_need = volume - v_accum;
428 if (dx < 1.0e-10)
return x1;
430 double s = (a2 - a1) / dx;
432 if (std::fabs(s) < 1.0e-10) {
434 depth = (a1 > 0.0) ? x1 + dv_need / a1 : x1;
437 double disc = a1 * a1 + 2.0 * s * dv_need;
438 if (disc < 0.0) disc = 0.0;
439 depth = x1 + (-a1 + std::sqrt(disc)) / s;
441 return std::min(depth, x2);
450 if (tbl.x.size() >= 2) {
452 double dx = tbl.x[last] - tbl.x[last - 1];
453 double da = tbl.y[last] - tbl.y[last - 1];
454 double s = (dx > 1.0e-10) ? da / dx : 0.0;
455 double dv_need = volume - v_accum;
456 double a1_ext = tbl.y[last];
458 if (std::fabs(s) < 1.0e-10) {
459 depth = (a1_ext > 0.0) ? tbl.x[last] + dv_need / a1_ext : tbl.x[last];
461 double disc = a1_ext * a1_ext + 2.0 * s * dv_need;
462 if (disc < 0.0) disc = 0.0;
463 depth = tbl.x[last] + (-a1_ext + std::sqrt(disc)) / s;
485 const int n =
static_cast<int>(tbl.x.size());
486 if (n == 0)
return 0.0;
487 if (n == 1)
return tbl.x[0];
489 if (y_query <= tbl.y[0])
return tbl.x[0];
490 if (y_query >= tbl.y[n - 1])
return tbl.x[n - 1];
492 for (
int i = 1; i < n; ++i) {
493 if (tbl.y[i] >= y_query) {
494 double dy = tbl.y[i] - tbl.y[i - 1];
495 if (dy <= 0.0)
return tbl.x[i - 1];
496 double t = (y_query - tbl.y[i - 1]) / dy;
497 return tbl.x[i - 1] + t * (tbl.x[i] - tbl.x[i - 1]);
529 const int n =
static_cast<int>(tbl.x.size());
530 if (n == 0)
return 0.0;
532 double x1 = tbl.x[0];
533 double y1 = tbl.y[0];
536 if (x1 > 0.0)
return x_query / x1 * y1;
539 for (
int i = 1; i < n; ++i) {
540 const double x2 = tbl.x[i];
541 const double y2 = tbl.y[i];
542 if (x2 != x1) s = (y2 - y1) / (x2 - x1);
544 const double dx = x2 - x1;
545 if (std::fabs(dx) < 1.0e-20)
return (y1 + y2) / 2.;
546 return y1 + (x_query - x1) * (y2 - y1) / dx;
551 if (s < 0.0) s = 0.0;
552 return y1 + s * (x_query - x1);
573 const int n =
static_cast<int>(tbl.x.size());
574 if (n == 0)
return 0.0;
576 for (
int i = 0; i < n; ++i) {
577 if (tbl.x[i] > x_query)
return tbl.y[i];
598 const int n =
static_cast<int>(tbl.x.size());
599 if (n < 2)
return 0.0;
602 if (x_query <= tbl.x[0]) {
603 double dx = tbl.x[1] - tbl.x[0];
604 return (dx > 0.0) ? (tbl.y[1] - tbl.y[0]) / dx : 0.0;
608 if (x_query >= tbl.x[n - 1]) {
609 double dx = tbl.x[n - 1] - tbl.x[n - 2];
610 return (dx > 0.0) ? (tbl.y[n - 1] - tbl.y[n - 2]) / dx : 0.0;
613 for (
int i = 1; i < n; ++i) {
614 if (tbl.x[i] >= x_query) {
615 double dx = tbl.x[i] - tbl.x[i - 1];
616 return (dx > 0.0) ? (tbl.y[i] - tbl.y[i - 1]) / dx : 0.0;
636 const int n =
static_cast<int>(tbl.x.size());
637 if (n == 0)
return 0.0;
638 double ymax = tbl.y[0];
639 for (
int i = 1; i < n; ++i) {
640 if (tbl.y[i] < ymax)
break;
671 tables.push_back({id, type, {}, {}, {}});
672 return static_cast<int>(
tables.size()) - 1;
679 for (
auto& t :
tables) t.cursor.reset();
Carrier for an external file reference in a SWMM model.
Definition NodeCoupling.cpp:15
double table_getStorageVolume(Table &tbl, double depth) noexcept
Compute storage volume by trapezoidal integration of an area-vs-depth curve, matching legacy table_ge...
Definition TableData.hpp:342
TableType
Type of data stored in a Table.
Definition TableData.hpp:55
@ CURVE_PUMP5
Pump curve type 5 (head vs flow, variable speed)
Definition TableData.hpp:67
@ CURVE_PUMP1
Pump curve type 1 (ON/OFF depth)
Definition TableData.hpp:63
@ CURVE_PUMP4
Pump curve type 4 (depth vs speed)
Definition TableData.hpp:66
@ CURVE_RATING
Outfall/weir rating curve.
Definition TableData.hpp:59
@ CURVE_TIDAL
Tidal stage curve.
Definition TableData.hpp:62
@ CURVE_SHAPE
Cross-section shape curve.
Definition TableData.hpp:60
@ CURVE_STORAGE
Storage node volume-depth curve.
Definition TableData.hpp:57
@ CURVE_DIVERSION
Diversion rating curve.
Definition TableData.hpp:58
@ CURVE_CONTROL
Control rule action curve.
Definition TableData.hpp:61
@ CURVE_PUMP2
Pump curve type 2 (head vs flow)
Definition TableData.hpp:64
@ CURVE_PUMP3
Pump curve type 3 (volume vs time)
Definition TableData.hpp:65
double table_getSlope(const Table &tbl, double x_query) noexcept
Compute the slope (dy/dx) at a given x value.
Definition TableData.hpp:597
double table_getStorageDepth(Table &tbl, double volume) noexcept
Invert a storage area-vs-depth curve to find depth from volume.
Definition TableData.hpp:408
double table_step_cursor(Table &tbl, double x_query) noexcept
Piecewise-constant (step function) table lookup with cursor.
Definition TableData.hpp:292
double table_lookup_column(Table &tbl, int col_idx, double x_query)
Definition TableData.cpp:641
TableValidation validate_table(Table &tbl)
Definition TableData.cpp:282
double table_getMaxY(const Table &tbl) noexcept
Return the maximum y value in the non-decreasing leading portion.
Definition TableData.hpp:635
bool table_open_file(Table &tbl, std::size_t boundary_rows)
Definition TableData.cpp:401
double table_intervalLookup(const Table &tbl, double x_query) noexcept
Step-function lookup: return y for the first x entry > x_query.
Definition TableData.hpp:572
@ TIMESERIES
Data from an in-file [TIMESERIES].
Definition GageData.hpp:42
double table_lookupEx(const Table &tbl, double x_query) noexcept
Linear-interpolating lookup with linear extrapolation outside bounds.
Definition TableData.hpp:519
double table_inverseLookup(const Table &tbl, double y_query) noexcept
Inverse lookup: given y, find corresponding x by linear interpolation.
Definition TableData.hpp:484
double table_lookup_cursor(Table &tbl, double x_query) noexcept
Look up a value in a Table using the bidirectional cursor.
Definition TableData.hpp:187
std::size_t table_load_cache(Table &tbl, std::size_t start_row)
Definition TableData.cpp:526
double table_tseries_lookup_cursor(Table &tbl, double x_query) noexcept
Time-series linear interpolation with out-of-range → 0 behaviour.
Definition TableData.hpp:258
double table_step_column(Table &tbl, int col_idx, double x_query)
Definition TableData.cpp:694
Two-string carrier for any external file path that appears in a SWMM .inp file.
Definition FilePathPair.hpp:47
A single time series or rating curve.
Definition TableData.hpp:110
bool empty() const noexcept
Definition TableData.hpp:117
std::size_t num_rows() const noexcept
Definition TableData.hpp:116
std::size_t file_row_start
Row offset in file (cache only)
Definition TableData.hpp:114
std::vector< double > x
Independent variable values.
Definition TableData.hpp:111
int num_cols
Number of value columns.
Definition TableData.hpp:113
std::vector< double > y
Dependent values (flat: row-major, num_cols per row)
Definition TableData.hpp:112
Bidirectional cursor tracking the last accessed index in a Table.
Definition TableData.hpp:85
int index
Index of the last successful lookup entry.
Definition TableData.hpp:86
int direction
Last seek direction: +1 = forward, -1 = backward.
Definition TableData.hpp:87
void reset() noexcept
Definition TableData.hpp:89
SoA collection of all time series and curves in the model.
Definition TableData.hpp:658
std::vector< Table > tables
All tables in index order.
Definition TableData.hpp:659
std::size_t count() const noexcept
Definition TableData.hpp:661
int add(const std::string &id, TableType type)
Add a new empty table with the given ID and type.
Definition TableData.hpp:670
void reset_cursors() noexcept
Reset all cursors (call before re-running a simulation).
Definition TableData.hpp:678
Table & operator[](int idx)
Definition TableData.hpp:663
const Table & operator[](int idx) const
Definition TableData.hpp:664
Definition TableData.hpp:120
long data_start_offset
File offset to first data row.
Definition TableData.hpp:148
std::size_t total_rows
Total data rows in file.
Definition TableData.hpp:146
TableBlock cache
Sliding cache window for file lookups.
Definition TableData.hpp:141
std::vector< long > row_offsets
Sparse byte-offset index into file.
Definition TableData.hpp:149
std::string comment
Object comment from the INP file (';'-prefixed lines immediately above the first row of this table),...
Definition TableData.hpp:129
std::size_t num_cache_rows
Cache window size (rows)
Definition TableData.hpp:147
std::unordered_map< std::string, int > column_map
Column name → index.
Definition TableData.hpp:151
TableCursor cursor
Bidirectional lookup cursor.
Definition TableData.hpp:132
TableType type
Table type (TIMESERIES, CURVE_*, etc.)
Definition TableData.hpp:122
bool empty() const noexcept
True if the table has at least one data point.
Definition TableData.hpp:159
double dx_min
Minimum inter-entry x spacing.
Definition TableData.hpp:142
std::string id
Table identifier (from input file)
Definition TableData.hpp:121
double x_max
Maximum x value in file.
Definition TableData.hpp:144
std::vector< double > y
Dependent variable (flow, volume, etc.)
Definition TableData.hpp:131
std::FILE * file_handle
Open file handle (owned)
Definition TableData.hpp:136
FilePathPair file_path
Definition TableData.hpp:137
bool is_file_based
True if data is read from external file.
Definition TableData.hpp:135
TableBlock last_boundary
Last rows from file (for validation)
Definition TableData.hpp:140
static constexpr std::size_t INDEX_STRIDE
Rows between offset index entries.
Definition TableData.hpp:153
std::vector< double > x
Independent variable (time, depth, etc.)
Definition TableData.hpp:130
double x_min
Minimum x value in file.
Definition TableData.hpp:143
TableBlock first_boundary
First rows from file (for validation)
Definition TableData.hpp:139
int num_cols
Number of value columns.
Definition TableData.hpp:145
std::size_t size() const noexcept
Number of data points.
Definition TableData.hpp:156
std::vector< std::string > column_ids
Column identifiers.
Definition TableData.hpp:150
Definition TableData.hpp:687
std::vector< std::string > errors
Definition TableData.hpp:689
std::vector< std::string > warnings
Definition TableData.hpp:690
bool valid
Definition TableData.hpp:688