OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
LinkSubtypes.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2//
3// Copyright 2026 Caleb Buahin
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
54
55#ifndef OPENSWMM_ENGINE_LINK_SUBTYPES_HPP
56#define OPENSWMM_ENGINE_LINK_SUBTYPES_HPP
57
58#include <algorithm>
59#include <vector>
60#include <cstdint>
61#include <string>
62#include <type_traits>
63
64#include "LinkData.hpp"
65
66namespace openswmm {
67
68// ============================================================================
69// ConduitData — side-table for CONDUIT links
70// ============================================================================
71
80 std::vector<int> link_idx;
81
82 std::vector<double> roughness;
83 std::vector<double> length;
84 std::vector<double> slope;
85 std::vector<double> mod_length;
86 std::vector<int> barrels;
87 std::vector<double> beta;
88 std::vector<double> rough_factor;
89 std::vector<double> q_full;
90 std::vector<double> q_max;
91 std::vector<double> loss_inlet;
92 std::vector<double> loss_outlet;
93 std::vector<double> loss_avg;
94 std::vector<double> seep_rate;
95 std::vector<int> culvert_code;
96
97 // Phase 6 Stage B: mutable per-step conduit state moved off wide LinkData.
98 std::vector<double> evap_loss_rate;
99 std::vector<double> seep_loss_rate;
100 std::vector<uint8_t> normal_flow_limited;
101 std::vector<uint8_t> inlet_control;
102 std::vector<int8_t> full_state;
103
104 int count() const noexcept { return static_cast<int>(link_idx.size()); }
105
106 void clear() noexcept {
107 link_idx.clear(); roughness.clear(); length.clear(); slope.clear();
108 mod_length.clear(); barrels.clear(); beta.clear(); rough_factor.clear();
109 q_full.clear(); q_max.clear(); loss_inlet.clear(); loss_outlet.clear();
110 loss_avg.clear(); seep_rate.clear(); culvert_code.clear();
111 evap_loss_rate.clear(); seep_loss_rate.clear(); normal_flow_limited.clear();
112 inlet_control.clear(); full_state.clear();
113 }
114
115 void reserve(int n) {
116 const auto un = static_cast<std::size_t>(n);
117 link_idx.reserve(un); roughness.reserve(un); length.reserve(un); slope.reserve(un);
118 mod_length.reserve(un); barrels.reserve(un); beta.reserve(un); rough_factor.reserve(un);
119 q_full.reserve(un); q_max.reserve(un); loss_inlet.reserve(un); loss_outlet.reserve(un);
120 loss_avg.reserve(un); seep_rate.reserve(un); culvert_code.reserve(un);
121 evap_loss_rate.reserve(un); seep_loss_rate.reserve(un); normal_flow_limited.reserve(un);
122 inlet_control.reserve(un); full_state.reserve(un);
123 }
124
127 int add_default(int i) {
128 const auto p = static_cast<std::ptrdiff_t>(
129 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
130 link_idx.insert(link_idx.begin() + p, i);
131 roughness.insert(roughness.begin() + p, 0.01);
132 length.insert(length.begin() + p, 0.0);
133 slope.insert(slope.begin() + p, 0.0);
134 mod_length.insert(mod_length.begin() + p, 0.0);
135 barrels.insert(barrels.begin() + p, 1);
136 beta.insert(beta.begin() + p, 0.0);
137 rough_factor.insert(rough_factor.begin() + p, 0.0);
138 q_full.insert(q_full.begin() + p, 0.0);
139 q_max.insert(q_max.begin() + p, 0.0);
140 loss_inlet.insert(loss_inlet.begin() + p, 0.0);
141 loss_outlet.insert(loss_outlet.begin() + p, 0.0);
142 loss_avg.insert(loss_avg.begin() + p, 0.0);
143 seep_rate.insert(seep_rate.begin() + p, 0.0);
144 culvert_code.insert(culvert_code.begin() + p, 0);
145 evap_loss_rate.insert(evap_loss_rate.begin() + p, 0.0);
146 seep_loss_rate.insert(seep_loss_rate.begin() + p, 0.0);
147 normal_flow_limited.insert(normal_flow_limited.begin() + p, uint8_t{0});
148 inlet_control.insert(inlet_control.begin() + p, uint8_t{0});
149 full_state.insert(full_state.begin() + p, int8_t{0});
150 return static_cast<int>(p);
151 }
152
153 void erase_at(int r) {
154 const auto p = static_cast<std::ptrdiff_t>(r);
155 link_idx.erase(link_idx.begin() + p);
156 roughness.erase(roughness.begin() + p);
157 length.erase(length.begin() + p);
158 slope.erase(slope.begin() + p);
159 mod_length.erase(mod_length.begin() + p);
160 barrels.erase(barrels.begin() + p);
161 beta.erase(beta.begin() + p);
162 rough_factor.erase(rough_factor.begin() + p);
163 q_full.erase(q_full.begin() + p);
164 q_max.erase(q_max.begin() + p);
165 loss_inlet.erase(loss_inlet.begin() + p);
166 loss_outlet.erase(loss_outlet.begin() + p);
167 loss_avg.erase(loss_avg.begin() + p);
168 seep_rate.erase(seep_rate.begin() + p);
169 culvert_code.erase(culvert_code.begin() + p);
170 evap_loss_rate.erase(evap_loss_rate.begin() + p);
171 seep_loss_rate.erase(seep_loss_rate.begin() + p);
172 normal_flow_limited.erase(normal_flow_limited.begin() + p);
173 inlet_control.erase(inlet_control.begin() + p);
174 full_state.erase(full_state.begin() + p);
175 }
176};
177
178// ============================================================================
179// PumpData — side-table for PUMP links
180// ============================================================================
181
182struct PumpData {
183 std::vector<int> link_idx;
184 std::vector<int> curve;
185 std::vector<uint8_t> init_state;
186 std::vector<double> startup;
187 std::vector<double> shutoff;
188 std::vector<int> curve_type;
189
190 int count() const noexcept { return static_cast<int>(link_idx.size()); }
191
192 void clear() noexcept {
193 link_idx.clear(); curve.clear(); init_state.clear();
194 startup.clear(); shutoff.clear(); curve_type.clear();
195 }
196
197 void reserve(int n) {
198 const auto un = static_cast<std::size_t>(n);
199 link_idx.reserve(un); curve.reserve(un); init_state.reserve(un);
200 startup.reserve(un); shutoff.reserve(un); curve_type.reserve(un);
201 }
202
203 int add_default(int i) {
204 const auto p = static_cast<std::ptrdiff_t>(
205 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
206 link_idx.insert(link_idx.begin() + p, i);
207 curve.insert(curve.begin() + p, -1);
208 init_state.insert(init_state.begin() + p, uint8_t{0});
209 startup.insert(startup.begin() + p, 0.0);
210 shutoff.insert(shutoff.begin() + p, 0.0);
211 curve_type.insert(curve_type.begin() + p, -1);
212 return static_cast<int>(p);
213 }
214
215 void erase_at(int r) {
216 const auto p = static_cast<std::ptrdiff_t>(r);
217 link_idx.erase(link_idx.begin() + p);
218 curve.erase(curve.begin() + p);
219 init_state.erase(init_state.begin() + p);
220 startup.erase(startup.begin() + p);
221 shutoff.erase(shutoff.begin() + p);
222 curve_type.erase(curve_type.begin() + p);
223 }
224};
225
226// ============================================================================
227// OrificeData — side-table for ORIFICE links (wide param1 → orifice_type)
228// ============================================================================
229
231 std::vector<int> link_idx;
232 std::vector<double> orifice_type;
233 std::vector<double> cd;
234 std::vector<double> orate;
238
239 int count() const noexcept { return static_cast<int>(link_idx.size()); }
240
241 void clear() noexcept {
242 link_idx.clear(); orifice_type.clear(); cd.clear(); orate.clear();
243 }
244 void reserve(int n) {
245 const auto un = static_cast<std::size_t>(n);
246 link_idx.reserve(un); orifice_type.reserve(un); cd.reserve(un); orate.reserve(un);
247 }
248 int add_default(int i) {
249 const auto p = static_cast<std::ptrdiff_t>(
250 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
251 link_idx.insert(link_idx.begin() + p, i);
252 orifice_type.insert(orifice_type.begin() + p, 0.0);
253 cd.insert(cd.begin() + p, 0.0);
254 orate.insert(orate.begin() + p, 0.0);
255 return static_cast<int>(p);
256 }
257 void erase_at(int r) {
258 const auto p = static_cast<std::ptrdiff_t>(r);
259 link_idx.erase(link_idx.begin() + p);
260 orifice_type.erase(orifice_type.begin() + p);
261 cd.erase(cd.begin() + p);
262 orate.erase(orate.begin() + p);
263 }
264};
265
266// ============================================================================
267// WeirData — side-table for WEIR links (param1 → weir_type, param2 → end_con)
268// ============================================================================
269
270struct WeirData {
271 std::vector<int> link_idx;
272 std::vector<double> weir_type;
273 std::vector<double> cd;
274 std::vector<double> end_contractions;
275 std::vector<double> crest_height;
276 std::vector<double> cd2;
277 std::vector<uint8_t> can_surcharge;
278
279 int count() const noexcept { return static_cast<int>(link_idx.size()); }
280
281 void clear() noexcept {
282 link_idx.clear(); weir_type.clear(); cd.clear();
283 end_contractions.clear(); crest_height.clear();
284 cd2.clear(); can_surcharge.clear();
285 }
286 void reserve(int n) {
287 const auto un = static_cast<std::size_t>(n);
288 link_idx.reserve(un); weir_type.reserve(un); cd.reserve(un);
289 end_contractions.reserve(un); crest_height.reserve(un);
290 cd2.reserve(un); can_surcharge.reserve(un);
291 }
292 int add_default(int i) {
293 const auto p = static_cast<std::ptrdiff_t>(
294 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
295 link_idx.insert(link_idx.begin() + p, i);
296 weir_type.insert(weir_type.begin() + p, 0.0);
297 cd.insert(cd.begin() + p, 0.0);
298 end_contractions.insert(end_contractions.begin() + p, 0.0);
299 crest_height.insert(crest_height.begin() + p, 0.0);
300 cd2.insert(cd2.begin() + p, 0.0);
301 can_surcharge.insert(can_surcharge.begin() + p, uint8_t{1});
302 return static_cast<int>(p);
303 }
304 void erase_at(int r) {
305 const auto p = static_cast<std::ptrdiff_t>(r);
306 link_idx.erase(link_idx.begin() + p);
307 weir_type.erase(weir_type.begin() + p);
308 cd.erase(cd.begin() + p);
309 end_contractions.erase(end_contractions.begin() + p);
310 crest_height.erase(crest_height.begin() + p);
311 cd2.erase(cd2.begin() + p);
312 can_surcharge.erase(can_surcharge.begin() + p);
313 }
314};
315
316// ============================================================================
317// OutletData — side-table for OUTLET links
318// param1 → outlet_type (rating: 0 FUNC/HEAD,1 FUNC/DEPTH,2 TAB/HEAD,3 TAB/DEPTH)
319// cd → coeff (functional C1), param2 → expon (functional C2)
320// ============================================================================
321
323 std::vector<int> link_idx;
324 std::vector<double> outlet_type;
325 std::vector<double> crest_height;
326 std::vector<double> coeff;
327 std::vector<double> expon;
328 std::vector<int> curve;
329
330 int count() const noexcept { return static_cast<int>(link_idx.size()); }
331
332 void clear() noexcept {
333 link_idx.clear(); outlet_type.clear(); crest_height.clear();
334 coeff.clear(); expon.clear(); curve.clear();
335 }
336 void reserve(int n) {
337 const auto un = static_cast<std::size_t>(n);
338 link_idx.reserve(un); outlet_type.reserve(un); crest_height.reserve(un);
339 coeff.reserve(un); expon.reserve(un); curve.reserve(un);
340 }
341 int add_default(int i) {
342 const auto p = static_cast<std::ptrdiff_t>(
343 std::lower_bound(link_idx.begin(), link_idx.end(), i) - link_idx.begin());
344 link_idx.insert(link_idx.begin() + p, i);
345 outlet_type.insert(outlet_type.begin() + p, 0.0);
346 crest_height.insert(crest_height.begin() + p, 0.0);
347 coeff.insert(coeff.begin() + p, 0.0);
348 expon.insert(expon.begin() + p, 0.0);
349 curve.insert(curve.begin() + p, -1);
350 return static_cast<int>(p);
351 }
352 void erase_at(int r) {
353 const auto p = static_cast<std::ptrdiff_t>(r);
354 link_idx.erase(link_idx.begin() + p);
355 outlet_type.erase(outlet_type.begin() + p);
356 crest_height.erase(crest_height.begin() + p);
357 coeff.erase(coeff.begin() + p);
358 expon.erase(expon.begin() + p);
359 curve.erase(curve.begin() + p);
360 }
361};
362
363// ============================================================================
364// LinkSubtypes — container + reverse map + incremental maintenance
365// ============================================================================
366
379
381 std::vector<int> subtype_row;
382
391 clear();
392 const int n = L.count();
393 for (int i = 0; i < n; ++i) {
394 switch (L.type[static_cast<std::size_t>(i)]) {
395 case LinkType::CONDUIT: conduits.add_default(i); break;
396 case LinkType::PUMP: pumps.add_default(i); break;
397 case LinkType::ORIFICE: orifices.add_default(i); break;
398 case LinkType::WEIR: weirs.add_default(i); break;
399 case LinkType::OUTLET: outlets.add_default(i); break;
400 }
401 }
402 rebuild_index(n);
403 }
404
405 void clear() noexcept {
406 conduits.clear(); pumps.clear(); orifices.clear();
407 weirs.clear(); outlets.clear(); subtype_row.clear();
408 }
409
411 void rebuild_index(int n_links) {
412 subtype_row.assign(static_cast<std::size_t>(n_links), -1);
413 auto idx = [&](const std::vector<int>& keys) {
414 for (int r = 0; r < static_cast<int>(keys.size()); ++r)
415 subtype_row[static_cast<std::size_t>(keys[static_cast<std::size_t>(r)])] = r;
416 };
417 idx(conduits.link_idx); idx(pumps.link_idx); idx(orifices.link_idx);
418 idx(weirs.link_idx); idx(outlets.link_idx);
419 }
420
424 int set_link_type(LinkData& links, int i, LinkType t) {
425 const auto ui = static_cast<std::size_t>(i);
426 if (i >= static_cast<int>(subtype_row.size()))
427 subtype_row.resize(static_cast<std::size_t>(i) + 1, -1);
428
429 const LinkType old = links.type[ui];
430 const int existing = subtype_row[ui];
431 if (old == t && existing >= 0)
432 return existing; // already this subtype with a row — idempotent
433
434 bool shifted = false;
435 if (existing >= 0) { // remove the old subtype row (real re-type/convert)
436 switch (old) {
437 case LinkType::CONDUIT: conduits.erase_at(existing); break;
438 case LinkType::PUMP: pumps.erase_at(existing); break;
439 case LinkType::ORIFICE: orifices.erase_at(existing); break;
440 case LinkType::WEIR: weirs.erase_at(existing); break;
441 case LinkType::OUTLET: outlets.erase_at(existing); break;
442 }
443 shifted = true;
444 }
445
446 links.type[ui] = t;
447
448 int row = -1;
449 switch (t) {
450 case LinkType::CONDUIT: row = conduits.add_default(i);
451 if (row != conduits.count() - 1) shifted = true; break;
452 case LinkType::PUMP: row = pumps.add_default(i);
453 if (row != pumps.count() - 1) shifted = true; break;
454 case LinkType::ORIFICE: row = orifices.add_default(i);
455 if (row != orifices.count() - 1) shifted = true; break;
456 case LinkType::WEIR: row = weirs.add_default(i);
457 if (row != weirs.count() - 1) shifted = true; break;
458 case LinkType::OUTLET: row = outlets.add_default(i);
459 if (row != outlets.count() - 1) shifted = true; break;
460 }
461
462 if (shifted) {
463 rebuild_index(links.count());
464 return subtype_row[ui];
465 }
466 subtype_row[ui] = row; // O(1) ascending-parse / end-insert path
467 return row;
468 }
469
472 void erase_link(int i, int n_after) {
473 auto drop = [i](auto& tbl) -> bool {
474 for (int r = 0; r < tbl.count(); ++r)
475 if (tbl.link_idx[static_cast<std::size_t>(r)] == i) { tbl.erase_at(r); return true; }
476 return false;
477 };
478 drop(conduits) || drop(pumps) || drop(orifices) || drop(weirs) || drop(outlets);
479
480 auto shift = [i](std::vector<int>& keys) { for (auto& k : keys) if (k > i) --k; };
481 shift(conduits.link_idx); shift(pumps.link_idx); shift(orifices.link_idx);
482 shift(weirs.link_idx); shift(outlets.link_idx);
483
484 rebuild_index(n_after);
485 }
486
487 // O(1) row helpers (validate link_idx[r] == i, like NodeSubtypes::*_row).
488 int conduit_row(int i) const noexcept { return row_in(i, conduits.link_idx); }
489 int pump_row(int i) const noexcept { return row_in(i, pumps.link_idx); }
490 int orifice_row(int i) const noexcept { return row_in(i, orifices.link_idx); }
491 int weir_row(int i) const noexcept { return row_in(i, weirs.link_idx); }
492 int outlet_row(int i) const noexcept { return row_in(i, outlets.link_idx); }
493
494private:
495 int row_in(int i, const std::vector<int>& keys) const noexcept {
496 if (i >= 0 && i < static_cast<int>(subtype_row.size())) {
497 const int r = subtype_row[static_cast<std::size_t>(i)];
498 if (r >= 0 && r < static_cast<int>(keys.size()) &&
499 keys[static_cast<std::size_t>(r)] == i)
500 return r;
501 }
502 return -1;
503 }
504};
505
506} // namespace openswmm
507
508#endif // OPENSWMM_ENGINE_LINK_SUBTYPES_HPP
Definition NodeCoupling.cpp:16
LinkType
Link type codes.
Definition LinkData.hpp:58
@ CONDUIT
Definition LinkData.hpp:59
@ PUMP
Definition LinkData.hpp:60
@ WEIR
Definition LinkData.hpp:62
@ ORIFICE
Definition LinkData.hpp:61
@ OUTLET
Definition LinkData.hpp:63
Dense SoA for conduit-only properties (one row per CONDUIT link).
Definition LinkSubtypes.hpp:79
std::vector< int > link_idx
Base LinkData index (join key)
Definition LinkSubtypes.hpp:80
int add_default(int i)
Definition LinkSubtypes.hpp:127
void erase_at(int r)
Definition LinkSubtypes.hpp:153
void clear() noexcept
Definition LinkSubtypes.hpp:106
std::vector< double > evap_loss_rate
per-step evaporation loss
Definition LinkSubtypes.hpp:98
std::vector< double > beta
Definition LinkSubtypes.hpp:87
std::vector< double > roughness
Definition LinkSubtypes.hpp:82
std::vector< int > culvert_code
Definition LinkSubtypes.hpp:95
std::vector< double > rough_factor
Definition LinkSubtypes.hpp:88
std::vector< double > q_full
Definition LinkSubtypes.hpp:89
std::vector< double > mod_length
Definition LinkSubtypes.hpp:85
int count() const noexcept
Definition LinkSubtypes.hpp:104
std::vector< int8_t > full_state
per-step up/down full bitmask
Definition LinkSubtypes.hpp:102
std::vector< double > loss_outlet
Definition LinkSubtypes.hpp:92
std::vector< int > barrels
Definition LinkSubtypes.hpp:86
std::vector< double > loss_avg
Definition LinkSubtypes.hpp:93
std::vector< double > q_max
Definition LinkSubtypes.hpp:90
void reserve(int n)
Definition LinkSubtypes.hpp:115
std::vector< double > loss_inlet
Definition LinkSubtypes.hpp:91
std::vector< double > seep_loss_rate
per-step seepage loss
Definition LinkSubtypes.hpp:99
std::vector< uint8_t > normal_flow_limited
per-step flag (reset each step)
Definition LinkSubtypes.hpp:100
std::vector< double > slope
Definition LinkSubtypes.hpp:84
std::vector< double > length
Definition LinkSubtypes.hpp:83
std::vector< double > seep_rate
Definition LinkSubtypes.hpp:94
std::vector< uint8_t > inlet_control
per-step culvert inlet-control flag
Definition LinkSubtypes.hpp:101
Definition LinkSubtypes.hpp:230
void reserve(int n)
Definition LinkSubtypes.hpp:244
std::vector< double > orate
Definition LinkSubtypes.hpp:234
void erase_at(int r)
Definition LinkSubtypes.hpp:257
int count() const noexcept
Definition LinkSubtypes.hpp:239
std::vector< int > link_idx
Definition LinkSubtypes.hpp:231
std::vector< double > orifice_type
0 = BOTTOM, 1 = SIDE (legacy param1)
Definition LinkSubtypes.hpp:232
void clear() noexcept
Definition LinkSubtypes.hpp:241
int add_default(int i)
Definition LinkSubtypes.hpp:248
std::vector< double > cd
Discharge coefficient.
Definition LinkSubtypes.hpp:233
Definition LinkSubtypes.hpp:322
std::vector< double > crest_height
Offset/crest.
Definition LinkSubtypes.hpp:325
int count() const noexcept
Definition LinkSubtypes.hpp:330
std::vector< int > link_idx
Definition LinkSubtypes.hpp:323
void erase_at(int r)
Definition LinkSubtypes.hpp:352
void reserve(int n)
Definition LinkSubtypes.hpp:336
std::vector< double > expon
Functional C2 exponent (legacy param2)
Definition LinkSubtypes.hpp:327
std::vector< double > outlet_type
Rating type (legacy param1)
Definition LinkSubtypes.hpp:324
std::vector< double > coeff
Functional C1 (legacy cd)
Definition LinkSubtypes.hpp:326
void clear() noexcept
Definition LinkSubtypes.hpp:332
int add_default(int i)
Definition LinkSubtypes.hpp:341
std::vector< int > curve
TABULAR rating-curve index (legacy pump_curve reuse; -1 = functional)
Definition LinkSubtypes.hpp:328
Definition LinkSubtypes.hpp:182
void reserve(int n)
Definition LinkSubtypes.hpp:197
std::vector< int > curve_type
Pump curve type (1-5, 6=ideal; -1 unset)
Definition LinkSubtypes.hpp:188
std::vector< uint8_t > init_state
Initial on/off (was vector<bool>)
Definition LinkSubtypes.hpp:185
void erase_at(int r)
Definition LinkSubtypes.hpp:215
std::vector< double > shutoff
Shutoff depth.
Definition LinkSubtypes.hpp:187
std::vector< double > startup
Startup depth.
Definition LinkSubtypes.hpp:186
std::vector< int > link_idx
Definition LinkSubtypes.hpp:183
int add_default(int i)
Definition LinkSubtypes.hpp:203
int count() const noexcept
Definition LinkSubtypes.hpp:190
void clear() noexcept
Definition LinkSubtypes.hpp:192
std::vector< int > curve
Pump curve table index (-1 = ideal)
Definition LinkSubtypes.hpp:184
Definition LinkSubtypes.hpp:270
void reserve(int n)
Definition LinkSubtypes.hpp:286
void clear() noexcept
Definition LinkSubtypes.hpp:281
std::vector< double > crest_height
Definition LinkSubtypes.hpp:275
void erase_at(int r)
Definition LinkSubtypes.hpp:304
std::vector< double > cd2
End-section discharge coeff (legacy cDisch2)
Definition LinkSubtypes.hpp:276
std::vector< uint8_t > can_surcharge
Surcharge YES/NO (legacy Weir.canSurcharge, default YES)
Definition LinkSubtypes.hpp:277
std::vector< double > weir_type
TRANSVERSE/SIDEFLOW/V-NOTCH/TRAPEZOIDAL (legacy param1)
Definition LinkSubtypes.hpp:272
std::vector< double > cd
Discharge coefficient.
Definition LinkSubtypes.hpp:273
int add_default(int i)
Definition LinkSubtypes.hpp:292
std::vector< int > link_idx
Definition LinkSubtypes.hpp:271
std::vector< double > end_contractions
End contractions (legacy param2)
Definition LinkSubtypes.hpp:274
int count() const noexcept
Definition LinkSubtypes.hpp:279