OpenSWMM Engine  6.0.0-alpha.1
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.1)
Loading...
Searching...
No Matches
LinkSubtypes.hpp
Go to the documentation of this file.
1
38
39#ifndef OPENSWMM_ENGINE_LINK_SUBTYPES_HPP
40#define OPENSWMM_ENGINE_LINK_SUBTYPES_HPP
41
42#include <algorithm>
43#include <vector>
44#include <cstdint>
45#include <string>
46#include <type_traits>
47
48#include "LinkData.hpp"
49
50namespace openswmm {
51
52// ============================================================================
53// ConduitData — side-table for CONDUIT links
54// ============================================================================
55
64 std::vector<int> link_idx;
65
66 std::vector<double> roughness;
67 std::vector<double> length;
68 std::vector<double> slope;
69 std::vector<double> mod_length;
70 std::vector<int> barrels;
71 std::vector<double> beta;
72 std::vector<double> rough_factor;
73 std::vector<double> q_full;
74 std::vector<double> q_max;
75 std::vector<double> loss_inlet;
76 std::vector<double> loss_outlet;
77 std::vector<double> loss_avg;
78 std::vector<double> seep_rate;
79 std::vector<int> culvert_code;
80
81 // Phase 6 Stage B: mutable per-step conduit state moved off wide LinkData.
82 std::vector<double> evap_loss_rate;
83 std::vector<double> seep_loss_rate;
84 std::vector<uint8_t> normal_flow_limited;
85 std::vector<uint8_t> inlet_control;
86 std::vector<int8_t> full_state;
87
88 int count() const noexcept { return static_cast<int>(link_idx.size()); }
89
90 void clear() noexcept {
91 link_idx.clear(); roughness.clear(); length.clear(); slope.clear();
92 mod_length.clear(); barrels.clear(); beta.clear(); rough_factor.clear();
93 q_full.clear(); q_max.clear(); loss_inlet.clear(); loss_outlet.clear();
94 loss_avg.clear(); seep_rate.clear(); culvert_code.clear();
95 evap_loss_rate.clear(); seep_loss_rate.clear(); normal_flow_limited.clear();
96 inlet_control.clear(); full_state.clear();
97 }
98
99 void reserve(int n) {
100 const auto un = static_cast<std::size_t>(n);
101 link_idx.reserve(un); roughness.reserve(un); length.reserve(un); slope.reserve(un);
102 mod_length.reserve(un); barrels.reserve(un); beta.reserve(un); rough_factor.reserve(un);
103 q_full.reserve(un); q_max.reserve(un); loss_inlet.reserve(un); loss_outlet.reserve(un);
104 loss_avg.reserve(un); seep_rate.reserve(un); culvert_code.reserve(un);
105 evap_loss_rate.reserve(un); seep_loss_rate.reserve(un); normal_flow_limited.reserve(un);
106 inlet_control.reserve(un); full_state.reserve(un);
107 }
108
111 int add_default(int i) {
112 const auto p = static_cast<std::ptrdiff_t>(
113 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
114 link_idx.insert(link_idx.begin() + p, i);
115 roughness.insert(roughness.begin() + p, 0.01);
116 length.insert(length.begin() + p, 0.0);
117 slope.insert(slope.begin() + p, 0.0);
118 mod_length.insert(mod_length.begin() + p, 0.0);
119 barrels.insert(barrels.begin() + p, 1);
120 beta.insert(beta.begin() + p, 0.0);
121 rough_factor.insert(rough_factor.begin() + p, 0.0);
122 q_full.insert(q_full.begin() + p, 0.0);
123 q_max.insert(q_max.begin() + p, 0.0);
124 loss_inlet.insert(loss_inlet.begin() + p, 0.0);
125 loss_outlet.insert(loss_outlet.begin() + p, 0.0);
126 loss_avg.insert(loss_avg.begin() + p, 0.0);
127 seep_rate.insert(seep_rate.begin() + p, 0.0);
128 culvert_code.insert(culvert_code.begin() + p, 0);
129 evap_loss_rate.insert(evap_loss_rate.begin() + p, 0.0);
130 seep_loss_rate.insert(seep_loss_rate.begin() + p, 0.0);
131 normal_flow_limited.insert(normal_flow_limited.begin() + p, uint8_t{0});
132 inlet_control.insert(inlet_control.begin() + p, uint8_t{0});
133 full_state.insert(full_state.begin() + p, int8_t{0});
134 return static_cast<int>(p);
135 }
136
137 void erase_at(int r) {
138 const auto p = static_cast<std::ptrdiff_t>(r);
139 link_idx.erase(link_idx.begin() + p);
140 roughness.erase(roughness.begin() + p);
141 length.erase(length.begin() + p);
142 slope.erase(slope.begin() + p);
143 mod_length.erase(mod_length.begin() + p);
144 barrels.erase(barrels.begin() + p);
145 beta.erase(beta.begin() + p);
146 rough_factor.erase(rough_factor.begin() + p);
147 q_full.erase(q_full.begin() + p);
148 q_max.erase(q_max.begin() + p);
149 loss_inlet.erase(loss_inlet.begin() + p);
150 loss_outlet.erase(loss_outlet.begin() + p);
151 loss_avg.erase(loss_avg.begin() + p);
152 seep_rate.erase(seep_rate.begin() + p);
153 culvert_code.erase(culvert_code.begin() + p);
154 evap_loss_rate.erase(evap_loss_rate.begin() + p);
155 seep_loss_rate.erase(seep_loss_rate.begin() + p);
156 normal_flow_limited.erase(normal_flow_limited.begin() + p);
157 inlet_control.erase(inlet_control.begin() + p);
158 full_state.erase(full_state.begin() + p);
159 }
160};
161
162// ============================================================================
163// PumpData — side-table for PUMP links
164// ============================================================================
165
166struct PumpData {
167 std::vector<int> link_idx;
168 std::vector<int> curve;
169 std::vector<uint8_t> init_state;
170 std::vector<double> startup;
171 std::vector<double> shutoff;
172 std::vector<int> curve_type;
173
174 int count() const noexcept { return static_cast<int>(link_idx.size()); }
175
176 void clear() noexcept {
177 link_idx.clear(); curve.clear(); init_state.clear();
178 startup.clear(); shutoff.clear(); curve_type.clear();
179 }
180
181 void reserve(int n) {
182 const auto un = static_cast<std::size_t>(n);
183 link_idx.reserve(un); curve.reserve(un); init_state.reserve(un);
184 startup.reserve(un); shutoff.reserve(un); curve_type.reserve(un);
185 }
186
187 int add_default(int i) {
188 const auto p = static_cast<std::ptrdiff_t>(
189 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
190 link_idx.insert(link_idx.begin() + p, i);
191 curve.insert(curve.begin() + p, -1);
192 init_state.insert(init_state.begin() + p, uint8_t{0});
193 startup.insert(startup.begin() + p, 0.0);
194 shutoff.insert(shutoff.begin() + p, 0.0);
195 curve_type.insert(curve_type.begin() + p, -1);
196 return static_cast<int>(p);
197 }
198
199 void erase_at(int r) {
200 const auto p = static_cast<std::ptrdiff_t>(r);
201 link_idx.erase(link_idx.begin() + p);
202 curve.erase(curve.begin() + p);
203 init_state.erase(init_state.begin() + p);
204 startup.erase(startup.begin() + p);
205 shutoff.erase(shutoff.begin() + p);
206 curve_type.erase(curve_type.begin() + p);
207 }
208};
209
210// ============================================================================
211// OrificeData — side-table for ORIFICE links (wide param1 → orifice_type)
212// ============================================================================
213
215 std::vector<int> link_idx;
216 std::vector<double> orifice_type;
217 std::vector<double> cd;
218 std::vector<double> orate;
219
220 int count() const noexcept { return static_cast<int>(link_idx.size()); }
221
222 void clear() noexcept {
223 link_idx.clear(); orifice_type.clear(); cd.clear(); orate.clear();
224 }
225 void reserve(int n) {
226 const auto un = static_cast<std::size_t>(n);
227 link_idx.reserve(un); orifice_type.reserve(un); cd.reserve(un); orate.reserve(un);
228 }
229 int add_default(int i) {
230 const auto p = static_cast<std::ptrdiff_t>(
231 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
232 link_idx.insert(link_idx.begin() + p, i);
233 orifice_type.insert(orifice_type.begin() + p, 0.0);
234 cd.insert(cd.begin() + p, 0.0);
235 orate.insert(orate.begin() + p, 0.0);
236 return static_cast<int>(p);
237 }
238 void erase_at(int r) {
239 const auto p = static_cast<std::ptrdiff_t>(r);
240 link_idx.erase(link_idx.begin() + p);
241 orifice_type.erase(orifice_type.begin() + p);
242 cd.erase(cd.begin() + p);
243 orate.erase(orate.begin() + p);
244 }
245};
246
247// ============================================================================
248// WeirData — side-table for WEIR links (param1 → weir_type, param2 → end_con)
249// ============================================================================
250
251struct WeirData {
252 std::vector<int> link_idx;
253 std::vector<double> weir_type;
254 std::vector<double> cd;
255 std::vector<double> end_contractions;
256 std::vector<double> crest_height;
257 std::vector<double> cd2;
258 std::vector<uint8_t> can_surcharge;
259
260 int count() const noexcept { return static_cast<int>(link_idx.size()); }
261
262 void clear() noexcept {
263 link_idx.clear(); weir_type.clear(); cd.clear();
264 end_contractions.clear(); crest_height.clear();
265 cd2.clear(); can_surcharge.clear();
266 }
267 void reserve(int n) {
268 const auto un = static_cast<std::size_t>(n);
269 link_idx.reserve(un); weir_type.reserve(un); cd.reserve(un);
270 end_contractions.reserve(un); crest_height.reserve(un);
271 cd2.reserve(un); can_surcharge.reserve(un);
272 }
273 int add_default(int i) {
274 const auto p = static_cast<std::ptrdiff_t>(
275 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
276 link_idx.insert(link_idx.begin() + p, i);
277 weir_type.insert(weir_type.begin() + p, 0.0);
278 cd.insert(cd.begin() + p, 0.0);
279 end_contractions.insert(end_contractions.begin() + p, 0.0);
280 crest_height.insert(crest_height.begin() + p, 0.0);
281 cd2.insert(cd2.begin() + p, 0.0);
282 can_surcharge.insert(can_surcharge.begin() + p, uint8_t{1});
283 return static_cast<int>(p);
284 }
285 void erase_at(int r) {
286 const auto p = static_cast<std::ptrdiff_t>(r);
287 link_idx.erase(link_idx.begin() + p);
288 weir_type.erase(weir_type.begin() + p);
289 cd.erase(cd.begin() + p);
290 end_contractions.erase(end_contractions.begin() + p);
291 crest_height.erase(crest_height.begin() + p);
292 cd2.erase(cd2.begin() + p);
293 can_surcharge.erase(can_surcharge.begin() + p);
294 }
295};
296
297// ============================================================================
298// OutletData — side-table for OUTLET links
299// param1 → outlet_type (rating: 0 FUNC/HEAD,1 FUNC/DEPTH,2 TAB/HEAD,3 TAB/DEPTH)
300// cd → coeff (functional C1), param2 → expon (functional C2)
301// ============================================================================
302
304 std::vector<int> link_idx;
305 std::vector<double> outlet_type;
306 std::vector<double> crest_height;
307 std::vector<double> coeff;
308 std::vector<double> expon;
309 std::vector<int> curve;
310
311 int count() const noexcept { return static_cast<int>(link_idx.size()); }
312
313 void clear() noexcept {
314 link_idx.clear(); outlet_type.clear(); crest_height.clear();
315 coeff.clear(); expon.clear(); curve.clear();
316 }
317 void reserve(int n) {
318 const auto un = static_cast<std::size_t>(n);
319 link_idx.reserve(un); outlet_type.reserve(un); crest_height.reserve(un);
320 coeff.reserve(un); expon.reserve(un); curve.reserve(un);
321 }
322 int add_default(int i) {
323 const auto p = static_cast<std::ptrdiff_t>(
324 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
325 link_idx.insert(link_idx.begin() + p, i);
326 outlet_type.insert(outlet_type.begin() + p, 0.0);
327 crest_height.insert(crest_height.begin() + p, 0.0);
328 coeff.insert(coeff.begin() + p, 0.0);
329 expon.insert(expon.begin() + p, 0.0);
330 curve.insert(curve.begin() + p, -1);
331 return static_cast<int>(p);
332 }
333 void erase_at(int r) {
334 const auto p = static_cast<std::ptrdiff_t>(r);
335 link_idx.erase(link_idx.begin() + p);
336 outlet_type.erase(outlet_type.begin() + p);
337 crest_height.erase(crest_height.begin() + p);
338 coeff.erase(coeff.begin() + p);
339 expon.erase(expon.begin() + p);
340 curve.erase(curve.begin() + p);
341 }
342};
343
344// ============================================================================
345// LinkSubtypes — container + reverse map + incremental maintenance
346// ============================================================================
347
360
362 std::vector<int> subtype_row;
363
372 clear();
373 const int n = L.count();
374 for (int i = 0; i < n; ++i) {
375 switch (L.type[static_cast<std::size_t>(i)]) {
376 case LinkType::CONDUIT: conduits.add_default(i); break;
377 case LinkType::PUMP: pumps.add_default(i); break;
378 case LinkType::ORIFICE: orifices.add_default(i); break;
379 case LinkType::WEIR: weirs.add_default(i); break;
380 case LinkType::OUTLET: outlets.add_default(i); break;
381 }
382 }
383 rebuild_index(n);
384 }
385
386 void clear() noexcept {
387 conduits.clear(); pumps.clear(); orifices.clear();
388 weirs.clear(); outlets.clear(); subtype_row.clear();
389 }
390
392 void rebuild_index(int n_links) {
393 subtype_row.assign(static_cast<std::size_t>(n_links), -1);
394 auto idx = [&](const std::vector<int>& keys) {
395 for (int r = 0; r < static_cast<int>(keys.size()); ++r)
396 subtype_row[static_cast<std::size_t>(keys[static_cast<std::size_t>(r)])] = r;
397 };
398 idx(conduits.link_idx); idx(pumps.link_idx); idx(orifices.link_idx);
399 idx(weirs.link_idx); idx(outlets.link_idx);
400 }
401
405 int set_link_type(LinkData& links, int i, LinkType t) {
406 const auto ui = static_cast<std::size_t>(i);
407 if (i >= static_cast<int>(subtype_row.size()))
408 subtype_row.resize(static_cast<std::size_t>(i) + 1, -1);
409
410 const LinkType old = links.type[ui];
411 const int existing = subtype_row[ui];
412 if (old == t && existing >= 0)
413 return existing; // already this subtype with a row — idempotent
414
415 bool shifted = false;
416 if (existing >= 0) { // remove the old subtype row (real re-type/convert)
417 switch (old) {
418 case LinkType::CONDUIT: conduits.erase_at(existing); break;
419 case LinkType::PUMP: pumps.erase_at(existing); break;
420 case LinkType::ORIFICE: orifices.erase_at(existing); break;
421 case LinkType::WEIR: weirs.erase_at(existing); break;
422 case LinkType::OUTLET: outlets.erase_at(existing); break;
423 }
424 shifted = true;
425 }
426
427 links.type[ui] = t;
428
429 int row = -1;
430 switch (t) {
431 case LinkType::CONDUIT: row = conduits.add_default(i);
432 if (row != conduits.count() - 1) shifted = true; break;
433 case LinkType::PUMP: row = pumps.add_default(i);
434 if (row != pumps.count() - 1) shifted = true; break;
435 case LinkType::ORIFICE: row = orifices.add_default(i);
436 if (row != orifices.count() - 1) shifted = true; break;
437 case LinkType::WEIR: row = weirs.add_default(i);
438 if (row != weirs.count() - 1) shifted = true; break;
439 case LinkType::OUTLET: row = outlets.add_default(i);
440 if (row != outlets.count() - 1) shifted = true; break;
441 }
442
443 if (shifted) {
444 rebuild_index(links.count());
445 return subtype_row[ui];
446 }
447 subtype_row[ui] = row; // O(1) ascending-parse / end-insert path
448 return row;
449 }
450
453 void erase_link(int i, int n_after) {
454 auto drop = [i](auto& tbl) -> bool {
455 for (int r = 0; r < tbl.count(); ++r)
456 if (tbl.link_idx[static_cast<std::size_t>(r)] == i) { tbl.erase_at(r); return true; }
457 return false;
458 };
459 drop(conduits) || drop(pumps) || drop(orifices) || drop(weirs) || drop(outlets);
460
461 auto shift = [i](std::vector<int>& keys) { for (auto& k : keys) if (k > i) --k; };
462 shift(conduits.link_idx); shift(pumps.link_idx); shift(orifices.link_idx);
463 shift(weirs.link_idx); shift(outlets.link_idx);
464
465 rebuild_index(n_after);
466 }
467
468 // O(1) row helpers (validate link_idx[r] == i, like NodeSubtypes::*_row).
469 int conduit_row(int i) const noexcept { return row_in(i, conduits.link_idx); }
470 int pump_row(int i) const noexcept { return row_in(i, pumps.link_idx); }
471 int orifice_row(int i) const noexcept { return row_in(i, orifices.link_idx); }
472 int weir_row(int i) const noexcept { return row_in(i, weirs.link_idx); }
473 int outlet_row(int i) const noexcept { return row_in(i, outlets.link_idx); }
474
475private:
476 int row_in(int i, const std::vector<int>& keys) const noexcept {
477 if (i >= 0 && i < static_cast<int>(subtype_row.size())) {
478 const int r = subtype_row[static_cast<std::size_t>(i)];
479 if (r >= 0 && r < static_cast<int>(keys.size()) &&
480 keys[static_cast<std::size_t>(r)] == i)
481 return r;
482 }
483 return -1;
484 }
485};
486
487} // namespace openswmm
488
489#endif // OPENSWMM_ENGINE_LINK_SUBTYPES_HPP
Definition NodeCoupling.cpp:15
LinkType
Link type codes.
Definition LinkData.hpp:42
@ CONDUIT
Definition LinkData.hpp:43
@ PUMP
Definition LinkData.hpp:44
@ WEIR
Definition LinkData.hpp:46
@ ORIFICE
Definition LinkData.hpp:45
@ OUTLET
Definition LinkData.hpp:47
Dense SoA for conduit-only properties (one row per CONDUIT link).
Definition LinkSubtypes.hpp:63
std::vector< int > link_idx
Base LinkData index (join key)
Definition LinkSubtypes.hpp:64
int add_default(int i)
Definition LinkSubtypes.hpp:111
void erase_at(int r)
Definition LinkSubtypes.hpp:137
void clear() noexcept
Definition LinkSubtypes.hpp:90
std::vector< double > evap_loss_rate
per-step evaporation loss
Definition LinkSubtypes.hpp:82
std::vector< double > beta
Definition LinkSubtypes.hpp:71
std::vector< double > roughness
Definition LinkSubtypes.hpp:66
std::vector< int > culvert_code
Definition LinkSubtypes.hpp:79
std::vector< double > rough_factor
Definition LinkSubtypes.hpp:72
std::vector< double > q_full
Definition LinkSubtypes.hpp:73
std::vector< double > mod_length
Definition LinkSubtypes.hpp:69
int count() const noexcept
Definition LinkSubtypes.hpp:88
std::vector< int8_t > full_state
per-step up/down full bitmask
Definition LinkSubtypes.hpp:86
std::vector< double > loss_outlet
Definition LinkSubtypes.hpp:76
std::vector< int > barrels
Definition LinkSubtypes.hpp:70
std::vector< double > loss_avg
Definition LinkSubtypes.hpp:77
std::vector< double > q_max
Definition LinkSubtypes.hpp:74
void reserve(int n)
Definition LinkSubtypes.hpp:99
std::vector< double > loss_inlet
Definition LinkSubtypes.hpp:75
std::vector< double > seep_loss_rate
per-step seepage loss
Definition LinkSubtypes.hpp:83
std::vector< uint8_t > normal_flow_limited
per-step flag (reset each step)
Definition LinkSubtypes.hpp:84
std::vector< double > slope
Definition LinkSubtypes.hpp:68
std::vector< double > length
Definition LinkSubtypes.hpp:67
std::vector< double > seep_rate
Definition LinkSubtypes.hpp:78
std::vector< uint8_t > inlet_control
per-step culvert inlet-control flag
Definition LinkSubtypes.hpp:85
Definition LinkSubtypes.hpp:214
void reserve(int n)
Definition LinkSubtypes.hpp:225
std::vector< double > orate
Open/close time (s)
Definition LinkSubtypes.hpp:218
void erase_at(int r)
Definition LinkSubtypes.hpp:238
int count() const noexcept
Definition LinkSubtypes.hpp:220
std::vector< int > link_idx
Definition LinkSubtypes.hpp:215
std::vector< double > orifice_type
0 = BOTTOM, 1 = SIDE (legacy param1)
Definition LinkSubtypes.hpp:216
void clear() noexcept
Definition LinkSubtypes.hpp:222
int add_default(int i)
Definition LinkSubtypes.hpp:229
std::vector< double > cd
Discharge coefficient.
Definition LinkSubtypes.hpp:217
Definition LinkSubtypes.hpp:303
std::vector< double > crest_height
Offset/crest.
Definition LinkSubtypes.hpp:306
int count() const noexcept
Definition LinkSubtypes.hpp:311
std::vector< int > link_idx
Definition LinkSubtypes.hpp:304
void erase_at(int r)
Definition LinkSubtypes.hpp:333
void reserve(int n)
Definition LinkSubtypes.hpp:317
std::vector< double > expon
Functional C2 exponent (legacy param2)
Definition LinkSubtypes.hpp:308
std::vector< double > outlet_type
Rating type (legacy param1)
Definition LinkSubtypes.hpp:305
std::vector< double > coeff
Functional C1 (legacy cd)
Definition LinkSubtypes.hpp:307
void clear() noexcept
Definition LinkSubtypes.hpp:313
int add_default(int i)
Definition LinkSubtypes.hpp:322
std::vector< int > curve
TABULAR rating-curve index (legacy pump_curve reuse; -1 = functional)
Definition LinkSubtypes.hpp:309
Definition LinkSubtypes.hpp:166
void reserve(int n)
Definition LinkSubtypes.hpp:181
std::vector< int > curve_type
Pump curve type (1-5, 6=ideal; -1 unset)
Definition LinkSubtypes.hpp:172
std::vector< uint8_t > init_state
Initial on/off (was vector<bool>)
Definition LinkSubtypes.hpp:169
void erase_at(int r)
Definition LinkSubtypes.hpp:199
std::vector< double > shutoff
Shutoff depth.
Definition LinkSubtypes.hpp:171
std::vector< double > startup
Startup depth.
Definition LinkSubtypes.hpp:170
std::vector< int > link_idx
Definition LinkSubtypes.hpp:167
int add_default(int i)
Definition LinkSubtypes.hpp:187
int count() const noexcept
Definition LinkSubtypes.hpp:174
void clear() noexcept
Definition LinkSubtypes.hpp:176
std::vector< int > curve
Pump curve table index (-1 = ideal)
Definition LinkSubtypes.hpp:168
Definition LinkSubtypes.hpp:251
void reserve(int n)
Definition LinkSubtypes.hpp:267
void clear() noexcept
Definition LinkSubtypes.hpp:262
std::vector< double > crest_height
Definition LinkSubtypes.hpp:256
void erase_at(int r)
Definition LinkSubtypes.hpp:285
std::vector< double > cd2
End-section discharge coeff (legacy cDisch2)
Definition LinkSubtypes.hpp:257
std::vector< uint8_t > can_surcharge
Surcharge YES/NO (legacy Weir.canSurcharge, default YES)
Definition LinkSubtypes.hpp:258
std::vector< double > weir_type
TRANSVERSE/SIDEFLOW/V-NOTCH/TRAPEZOIDAL (legacy param1)
Definition LinkSubtypes.hpp:253
std::vector< double > cd
Discharge coefficient.
Definition LinkSubtypes.hpp:254
int add_default(int i)
Definition LinkSubtypes.hpp:273
std::vector< int > link_idx
Definition LinkSubtypes.hpp:252
std::vector< double > end_contractions
End contractions (legacy param2)
Definition LinkSubtypes.hpp:255
int count() const noexcept
Definition LinkSubtypes.hpp:260