OpenSWMM Engine  6.0.0-alpha.1
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.1)
Loading...
Searching...
No Matches
TableData.hpp
Go to the documentation of this file.
1
32#ifndef OPENSWMM_ENGINE_TABLE_DATA_HPP
33#define OPENSWMM_ENGINE_TABLE_DATA_HPP
34
35#include <string>
36#include <vector>
37#include <cstdint>
38#include <cassert>
39#include <algorithm>
40
41namespace openswmm {
42
43// ============================================================================
44// Table types (matching legacy SWMM enums.h)
45// ============================================================================
46
51enum class TableType : int {
52 TIMESERIES = 0,
53 CURVE_STORAGE = 1,
54 CURVE_DIVERSION = 2,
55 CURVE_RATING = 3,
56 CURVE_SHAPE = 4,
57 CURVE_CONTROL = 5,
58 CURVE_TIDAL = 6,
59 CURVE_PUMP1 = 7,
60 CURVE_PUMP2 = 8,
61 CURVE_PUMP3 = 9,
62 CURVE_PUMP4 = 10
63};
64
65// ============================================================================
66// TableCursor
67// ============================================================================
68
81 int index = 0;
82 int direction = +1;
83
84 void reset() noexcept { index = 0; direction = +1; }
85};
86
87// ============================================================================
88// Table
89// ============================================================================
90
102struct Table {
103 std::string id;
105 std::vector<double> x;
106 std::vector<double> y;
108
110 std::size_t size() const noexcept { return x.size(); }
111
113 bool empty() const noexcept { return x.empty(); }
114};
115
116// ============================================================================
117// Cursor-optimized lookup
118// ============================================================================
119
141inline double table_lookup_cursor(Table& tbl, double x_query) noexcept {
142 const int n = static_cast<int>(tbl.x.size());
143 if (n == 0) return 0.0;
144 if (n == 1) return tbl.y[0];
145
146 // Clamp below first entry
147 if (x_query <= tbl.x[0]) {
148 tbl.cursor.index = 0;
149 tbl.cursor.direction = +1;
150 return tbl.y[0];
151 }
152
153 // Clamp above last entry
154 if (x_query >= tbl.x[n - 1]) {
155 tbl.cursor.index = n - 1;
156 tbl.cursor.direction = -1;
157 return tbl.y[n - 1];
158 }
159
160 // Start from cursor position and seek in the most likely direction
161 int idx = std::clamp(tbl.cursor.index, 0, n - 2);
162
163 // Forward seek
164 while (idx < n - 1 && tbl.x[idx + 1] < x_query) {
165 ++idx;
166 tbl.cursor.direction = +1;
167 }
168
169 // Backward seek
170 while (idx > 0 && tbl.x[idx] > x_query) {
171 --idx;
172 tbl.cursor.direction = -1;
173 }
174
175 tbl.cursor.index = idx;
176
177 // Linear interpolation between x[idx] and x[idx+1]
178 const double dx = tbl.x[idx + 1] - tbl.x[idx];
179 if (dx <= 0.0) return tbl.y[idx]; // guard against duplicate x values
180 const double t = (x_query - tbl.x[idx]) / dx;
181 return tbl.y[idx] + t * (tbl.y[idx + 1] - tbl.y[idx]);
182}
183
198inline double table_step_cursor(Table& tbl, double x_query) noexcept {
199 const int n = static_cast<int>(tbl.x.size());
200 if (n == 0) return 0.0;
201 if (n == 1) return tbl.y[0];
202
203 // Before first entry → 0 (no rain before first recorded value)
204 if (x_query < tbl.x[0]) {
205 tbl.cursor.index = 0;
206 tbl.cursor.direction = +1;
207 return 0.0;
208 }
209
210 // At or past last entry → return last value.
211 // The caller (Gage.cpp) handles the rain interval cutoff and returns 0
212 // after entry_time + rainInterval. This allows the last entry's value to
213 // be used for its full recording interval before going to zero.
214 if (x_query >= tbl.x[n - 1]) {
215 tbl.cursor.index = n - 1;
216 tbl.cursor.direction = -1;
217 return tbl.y[n - 1];
218 }
219
220 // Seek to the interval containing x_query: x[idx] <= x_query < x[idx+1]
221 int idx = std::clamp(tbl.cursor.index, 0, n - 2);
222
223 while (idx < n - 1 && tbl.x[idx + 1] <= x_query) {
224 ++idx;
225 tbl.cursor.direction = +1;
226 }
227 while (idx > 0 && tbl.x[idx] > x_query) {
228 --idx;
229 tbl.cursor.direction = -1;
230 }
231
232 tbl.cursor.index = idx;
233 return tbl.y[idx];
234}
235
236// ============================================================================
237// TableData — SoA collection of all tables
238// ============================================================================
239
248struct TableData {
249 std::vector<Table> tables;
250
251 std::size_t count() const noexcept { return tables.size(); }
252
253 Table& operator[](int idx) { return tables[static_cast<std::size_t>(idx)]; }
254 const Table& operator[](int idx) const { return tables[static_cast<std::size_t>(idx)]; }
255
260 int add(const std::string& id, TableType type) {
261 tables.push_back({id, type, {}, {}, {}});
262 return static_cast<int>(tables.size()) - 1;
263 }
264
268 void reset_cursors() noexcept {
269 for (auto& t : tables) t.cursor.reset();
270 }
271};
272
273} /* namespace openswmm */
274
275#endif /* OPENSWMM_ENGINE_TABLE_DATA_HPP */
Definition Controls.cpp:24
TableType
Type of data stored in a Table.
Definition TableData.hpp:51
@ CURVE_PUMP1
Pump curve type 1 (ON/OFF depth)
@ CURVE_PUMP4
Pump curve type 4 (depth vs speed)
@ CURVE_RATING
Outfall/weir rating curve.
@ CURVE_TIDAL
Tidal stage curve.
@ CURVE_SHAPE
Cross-section shape curve.
@ CURVE_STORAGE
Storage node volume-depth curve.
@ CURVE_DIVERSION
Diversion rating curve.
@ CURVE_CONTROL
Control rule action curve.
@ CURVE_PUMP2
Pump curve type 2 (head vs flow)
@ CURVE_PUMP3
Pump curve type 3 (volume vs time)
double table_step_cursor(Table &tbl, double x_query) noexcept
Piecewise-constant (step function) table lookup with cursor.
Definition TableData.hpp:198
@ TIMESERIES
Data from an in-file [TIMESERIES].
double table_lookup_cursor(Table &tbl, double x_query) noexcept
Look up a value in a Table using the bidirectional cursor.
Definition TableData.hpp:141
Bidirectional cursor tracking the last accessed index in a Table.
Definition TableData.hpp:80
int index
Index of the last successful lookup entry.
Definition TableData.hpp:81
int direction
Last seek direction: +1 = forward, -1 = backward.
Definition TableData.hpp:82
void reset() noexcept
Definition TableData.hpp:84
SoA collection of all time series and curves in the model.
Definition TableData.hpp:248
std::vector< Table > tables
All tables in index order.
Definition TableData.hpp:249
std::size_t count() const noexcept
Definition TableData.hpp:251
int add(const std::string &id, TableType type)
Add a new empty table with the given ID and type.
Definition TableData.hpp:260
void reset_cursors() noexcept
Reset all cursors (call before re-running a simulation).
Definition TableData.hpp:268
Table & operator[](int idx)
Definition TableData.hpp:253
const Table & operator[](int idx) const
Definition TableData.hpp:254
A single time series or rating curve.
Definition TableData.hpp:102
TableCursor cursor
Bidirectional lookup cursor.
Definition TableData.hpp:107
TableType type
Table type (TIMESERIES, CURVE_*, etc.)
Definition TableData.hpp:104
bool empty() const noexcept
True if the table has at least one data point.
Definition TableData.hpp:113
std::string id
Table identifier (from input file)
Definition TableData.hpp:103
std::vector< double > y
Dependent variable (flow, volume, etc.)
Definition TableData.hpp:106
std::vector< double > x
Independent variable (time, depth, etc.)
Definition TableData.hpp:105
std::size_t size() const noexcept
Number of data points.
Definition TableData.hpp:110