OpenSWMM Engine  6.0.0-alpha.3
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.3)
Loading...
Searching...
No Matches
LinkData.hpp
Go to the documentation of this file.
1
23
24#ifndef OPENSWMM_ENGINE_LINK_DATA_HPP
25#define OPENSWMM_ENGINE_LINK_DATA_HPP
26
27#include <vector>
28#include <cstdint>
29#include <string>
30#include <algorithm>
31
32namespace openswmm {
33
34// ============================================================================
35// Link type enumerations
36// ============================================================================
37
42enum class LinkType : int8_t {
44 PUMP = 1,
46 WEIR = 3,
48};
49
82
87enum class FlowClass : int8_t {
88 DRY = 0,
89 UP_DRY = 1,
90 DN_DRY = 2,
95};
96
97// ============================================================================
98// LinkData — SoA layout
99// ============================================================================
100
109struct LinkData {
110
111 // -----------------------------------------------------------------------
112 // Static connectivity — set at parse time
113 // -----------------------------------------------------------------------
114
116 std::vector<LinkType> type;
117
122 std::vector<int> node1;
123
128 std::vector<int> node2;
129
134 std::vector<double> offset1;
135
140 std::vector<double> offset2;
141
146 std::vector<double> q0;
147
152 std::vector<double> q_limit;
153
154 // -----------------------------------------------------------------------
155 // Conduit-specific properties (valid when type[i] == CONDUIT)
156 // -----------------------------------------------------------------------
157
159 std::vector<XsectShape> xsect_shape;
160
162 std::vector<double> xsect_y_full;
163
165 std::vector<double> xsect_a_full;
166
168 std::vector<double> xsect_w_max;
169
185 std::vector<double> xsect_geom1;
186 std::vector<double> xsect_geom2;
187 std::vector<double> xsect_geom3;
188 std::vector<double> xsect_geom4;
189
194 std::vector<int> xsect_curve;
195
196 // Phase 6: conduit-config fields (roughness, length, slope, mod_length,
197 // barrels, beta, rough_factor, q_full, q_max) moved to ConduitData in
198 // LinkSubtypes.hpp — the relational link side-tables are the single store.
199
204 std::vector<double> xsect_r_full;
205
210 std::vector<double> xsect_s_full;
211
216 std::vector<double> xsect_s_max;
217
222 std::vector<double> xsect_y_bot;
223
228 std::vector<double> xsect_a_bot;
229
235 std::vector<double> xsect_s_bot;
236
241 std::vector<double> xsect_r_bot;
242
247 std::vector<double> xsect_yw_max;
248
254 std::vector<int> xsect_batch_shape;
255
260 std::vector<double> setting;
261
266 std::vector<double> target_setting;
267
276 std::vector<double> time_last_set;
277
282 std::vector<int> direction;
283
284 // -----------------------------------------------------------------------
285 // Pump-specific properties (valid when type[i] == PUMP)
286 // -----------------------------------------------------------------------
287
288 // Phase 6: pump-config fields (pump_curve, pump_init_state, pump_startup,
289 // pump_shutoff, pump_curve_type) moved to PumpData in LinkSubtypes.hpp.
290 // pump_curve_name stays on base (shared with outlet/conduit-IRREGULAR).
291
293 std::vector<std::string> pump_curve_name;
294
295 // -----------------------------------------------------------------------
296 // Conduit loss coefficients
297 // -----------------------------------------------------------------------
298
299 // Phase 6: conduit loss/seep/culvert + per-step state (loss_inlet,
300 // loss_outlet, loss_avg, seep_rate, evap_loss_rate, seep_loss_rate,
301 // culvert_code, normal_flow_limited, inlet_control) moved to ConduitData.
302 // has_flap_gate and dqdh stay on base (shared / multi-owner).
303
305 std::vector<uint8_t> has_flap_gate;
306
311 std::vector<double> dqdh;
312
313 // -----------------------------------------------------------------------
314 // Weir / Orifice / Outlet — shared geometric properties
315 // -----------------------------------------------------------------------
316
317 // Phase 6: weir/orifice/outlet config (crest_height, cd, param1, param2,
318 // orate) moved to OrificeData/WeirData/OutletData in LinkSubtypes.hpp.
319
320 // -----------------------------------------------------------------------
321 // State variables — updated each timestep
322 // -----------------------------------------------------------------------
323
328 std::vector<double> flow;
329
334 std::vector<double> depth;
335
340 std::vector<double> volume;
341
346 std::vector<double> froude;
347
349 std::vector<FlowClass> flow_class;
350
352 std::vector<uint8_t> is_closed;
353
354 // Phase 6: full_state (per-step up/down full bitmask) moved to ConduitData.
355
356 // -----------------------------------------------------------------------
357 // Previous-step state
358 // -----------------------------------------------------------------------
359
361 std::vector<double> old_flow;
362
364 std::vector<double> old_depth;
365
367 std::vector<double> old_volume;
368
369 // -----------------------------------------------------------------------
370 // Per-link quality state — flat 2D: [link * n_pollutants + pollutant]
371 // -----------------------------------------------------------------------
372
378 std::vector<double> conc;
379
381 std::vector<double> conc_old;
382
385
386 // -----------------------------------------------------------------------
387 // Per-object INP comment
388 // -----------------------------------------------------------------------
389
395 std::vector<std::string> comments;
396
403 std::vector<std::string> tags;
404
405 // -----------------------------------------------------------------------
406 // Report flag — per-object output filter
407 // -----------------------------------------------------------------------
408
411 std::vector<char> rpt_flag;
412
413 // -----------------------------------------------------------------------
414 // Cumulative statistics
415 // -----------------------------------------------------------------------
416
421 std::vector<double> stat_vol_flow;
422
427 std::vector<double> stat_max_flow;
428
433 std::vector<double> stat_max_veloc;
434
439 std::vector<double> stat_max_filling;
440
445 std::vector<double> stat_time_surcharged;
446
453 static constexpr int N_FLOW_CLASSES = 7;
454 std::vector<long> stat_flow_class;
455 std::vector<long> stat_norm_ltd;
456 std::vector<long> stat_inlet_ctrl;
457
460 std::vector<double> stat_max_flow_date;
461
464 std::vector<double> stat_time_full_upstream;
465
468 std::vector<double> stat_time_full_dnstream;
469
472 std::vector<double> stat_time_full_both;
473
476 std::vector<double> stat_time_capacity_limited;
477
484 std::vector<double> stat_total_load;
486
487 // -----------------------------------------------------------------------
488 // Pump utilization statistics (valid when type[i] == PUMP)
489 // -----------------------------------------------------------------------
490
492 std::vector<int> stat_pump_cycles;
493
495 std::vector<double> stat_pump_on_time;
496
498 std::vector<double> stat_pump_volume;
499
505 std::vector<double> stat_pump_energy;
506
508 std::vector<bool> stat_pump_was_on;
509
517 std::vector<long> stat_flow_turns;
518
525 std::vector<int> stat_flow_turn_sign;
526
533 std::vector<double> stat_time_courant_critical;
534
535 // -----------------------------------------------------------------------
536 // Capacity management
537 // -----------------------------------------------------------------------
538
539 int count() const noexcept { return static_cast<int>(type.size()); }
540
541 void resize(int n) {
542 const auto un = static_cast<std::size_t>(n);
543
544 type.assign(un, LinkType::CONDUIT);
545 node1.assign(un, -1);
546 node2.assign(un, -1);
547 offset1.assign(un, 0.0);
548 offset2.assign(un, 0.0);
549 q0.assign(un, 0.0);
550 q_limit.assign(un, 0.0);
551
553 xsect_y_full.assign(un, 0.0);
554 xsect_a_full.assign(un, 0.0);
555 xsect_w_max.assign(un, 0.0);
556 xsect_geom1.assign(un, 0.0);
557 xsect_geom2.assign(un, 0.0);
558 xsect_geom3.assign(un, 0.0);
559 xsect_geom4.assign(un, 0.0);
560 xsect_curve.assign(un, -1);
561 xsect_r_full.assign(un, 0.0);
562 xsect_s_full.assign(un, 0.0);
563 xsect_s_max.assign(un, 0.0);
564 xsect_y_bot.assign(un, 0.0);
565 xsect_a_bot.assign(un, 0.0);
566 xsect_s_bot.assign(un, 0.0);
567 xsect_r_bot.assign(un, 0.0);
568 xsect_yw_max.assign(un, 0.0);
569 xsect_batch_shape.assign(un, 0);
570 setting.assign(un, 1.0);
571 target_setting.assign(un, 1.0);
572 time_last_set.assign(un, 0.0);
573 direction.assign(un, 1);
574
575 has_flap_gate.assign(un, 0);
576 dqdh.assign(un, 0.0);
577 pump_curve_name.resize(un);
578
579 flow.assign(un, 0.0);
580 depth.assign(un, 0.0);
581 volume.assign(un, 0.0);
582 froude.assign(un, 0.0);
583 flow_class.assign(un, FlowClass::DRY);
584 is_closed.assign(un, 0);
585 old_flow.assign(un, 0.0);
586 old_depth.assign(un, 0.0);
587 old_volume.assign(un, 0.0);
588
589 comments.assign(un, std::string{});
590 tags.assign(un, std::string{});
591
592 rpt_flag.assign(un, 0);
593
594 stat_vol_flow.assign(un, 0.0);
595 stat_max_flow.assign(un, 0.0);
596 stat_max_veloc.assign(un, 0.0);
597 stat_max_filling.assign(un, 0.0);
598 stat_time_surcharged.assign(un, 0.0);
599 stat_flow_class.assign(un * N_FLOW_CLASSES, 0L);
600 stat_norm_ltd.assign(un, 0L);
601 stat_inlet_ctrl.assign(un, 0L);
602 stat_max_flow_date.assign(un, 0.0);
603 stat_time_full_upstream.assign(un, 0.0);
604 stat_time_full_dnstream.assign(un, 0.0);
605 stat_time_full_both.assign(un, 0.0);
606 stat_time_capacity_limited.assign(un, 0.0);
607 stat_pump_cycles.assign(un, 0);
608 stat_pump_on_time.assign(un, 0.0);
609 stat_pump_volume.assign(un, 0.0);
610 stat_pump_energy.assign(un, 0.0);
611 stat_pump_was_on.assign(un, false);
612 stat_flow_turns.assign(un, 0L);
613 stat_flow_turn_sign.assign(un, 0);
614 stat_time_courant_critical.assign(un, 0.0);
615 }
616
620 void grow_to(int n) {
621 if (n <= count()) return;
622 const auto un = static_cast<std::size_t>(n);
623 auto g = [&](auto& vec, auto def) { vec.resize(un, def); };
624 g(type, LinkType::CONDUIT); g(node1, -1); g(node2, -1);
625 g(offset1, 0.0); g(offset2, 0.0); g(q0, 0.0); g(q_limit, 0.0);
627 g(xsect_y_full, 0.0); g(xsect_a_full, 0.0); g(xsect_w_max, 0.0);
628 g(xsect_geom1, 0.0); g(xsect_geom2, 0.0); g(xsect_geom3, 0.0); g(xsect_geom4, 0.0);
629 g(xsect_curve, -1);
630 g(xsect_r_full, 0.0); g(xsect_s_full, 0.0); g(xsect_s_max, 0.0);
631 g(xsect_y_bot, 0.0); g(xsect_a_bot, 0.0);
632 g(xsect_s_bot, 0.0); g(xsect_r_bot, 0.0);
633 g(xsect_yw_max, 0.0); g(xsect_batch_shape, 0);
634 g(setting, 1.0); g(target_setting, 1.0); g(time_last_set, 0.0);
635 g(direction, 1);
636 g(has_flap_gate, uint8_t{0}); g(dqdh, 0.0);
637 pump_curve_name.resize(un);
638 g(flow, 0.0); g(depth, 0.0); g(volume, 0.0);
639 g(froude, 0.0); g(flow_class, FlowClass::DRY); g(is_closed, uint8_t{0});
640 g(old_flow, 0.0); g(old_depth, 0.0); g(old_volume, 0.0);
641 comments.resize(un, std::string{});
642 tags.resize(un, std::string{});
643
644 g(rpt_flag, static_cast<char>(0));
645 g(stat_vol_flow, 0.0); g(stat_max_flow, 0.0);
646 g(stat_max_veloc, 0.0); g(stat_max_filling, 0.0);
650 g(stat_pump_cycles, 0); g(stat_pump_on_time, 0.0);
651 g(stat_pump_volume, 0.0); g(stat_pump_energy, 0.0);
652 g(stat_pump_was_on, false);
655 g(stat_norm_ltd, 0L); g(stat_inlet_ctrl, 0L);
656 // stat_flow_class is flat 2D [n * N_FLOW_CLASSES]
657 stat_flow_class.resize(un * N_FLOW_CLASSES, 0L);
658 // Note: conc, conc_old handled by resize_quality()
659 // Note: stat_total_load handled by resize_loads()
660 }
661
670 void erase_at(int idx) {
671 const auto ui = static_cast<std::size_t>(idx);
672 auto e = [&](auto& v) { if (ui < v.size()) v.erase(v.begin() + static_cast<std::ptrdiff_t>(idx)); };
673
674 e(type); e(node1); e(node2); e(offset1); e(offset2); e(q0); e(q_limit);
675
680
682
683 e(has_flap_gate); e(dqdh);
684
685 e(flow); e(depth); e(volume); e(froude); e(flow_class); e(is_closed);
686 e(old_flow); e(old_depth); e(old_volume);
687 e(comments); e(tags); e(rpt_flag);
688
696
697 // Flat 2D: stat_flow_class [link * N_FLOW_CLASSES + class]
698 {
699 const auto base = ui * static_cast<std::size_t>(N_FLOW_CLASSES);
700 const auto end = base + static_cast<std::size_t>(N_FLOW_CLASSES);
701 if (end <= stat_flow_class.size())
702 stat_flow_class.erase(stat_flow_class.begin() + static_cast<std::ptrdiff_t>(base),
703 stat_flow_class.begin() + static_cast<std::ptrdiff_t>(end));
704 }
705
706 // Flat 2D quality arrays: [link * np + p]
707 if (conc_n_pollutants > 0) {
708 const auto np = static_cast<std::size_t>(conc_n_pollutants);
709 const auto base = ui * np;
710 auto erase2d = [&](auto& v) {
711 if (base + np <= v.size())
712 v.erase(v.begin() + static_cast<std::ptrdiff_t>(base),
713 v.begin() + static_cast<std::ptrdiff_t>(base + np));
714 };
715 erase2d(conc); erase2d(conc_old);
716 }
717
718 // Flat 2D stat load: [link * np + p]
719 if (stat_n_pollutants > 0) {
720 const auto np = static_cast<std::size_t>(stat_n_pollutants);
721 const auto base = ui * np;
722 if (base + np <= stat_total_load.size())
723 stat_total_load.erase(
724 stat_total_load.begin() + static_cast<std::ptrdiff_t>(base),
725 stat_total_load.begin() + static_cast<std::ptrdiff_t>(base + np));
726 }
727 }
728
732 void resize_loads(int n_pollutants) {
733 stat_n_pollutants = n_pollutants;
734 if (n_pollutants > 0) {
735 auto total = static_cast<std::size_t>(count()) *
736 static_cast<std::size_t>(n_pollutants);
737 stat_total_load.assign(total, 0.0);
738 }
739 }
740
744 void resize_quality(int n_pollutants) {
745 conc_n_pollutants = n_pollutants;
746 if (n_pollutants > 0) {
747 auto total = static_cast<std::size_t>(count()) *
748 static_cast<std::size_t>(n_pollutants);
749 conc.assign(total, 0.0);
750 conc_old.assign(total, 0.0);
751 }
752 }
753
758 type.shrink_to_fit();
759 node1.shrink_to_fit();
760 node2.shrink_to_fit();
761 offset1.shrink_to_fit();
762 offset2.shrink_to_fit();
763 q0.shrink_to_fit();
764 q_limit.shrink_to_fit();
765
766 xsect_shape.shrink_to_fit();
767 xsect_y_full.shrink_to_fit();
768 xsect_a_full.shrink_to_fit();
769 xsect_w_max.shrink_to_fit();
770 xsect_curve.shrink_to_fit();
771 xsect_r_full.shrink_to_fit();
772 xsect_s_full.shrink_to_fit();
773 xsect_s_max.shrink_to_fit();
774 xsect_y_bot.shrink_to_fit();
775 xsect_a_bot.shrink_to_fit();
776 xsect_s_bot.shrink_to_fit();
777 xsect_r_bot.shrink_to_fit();
778 xsect_yw_max.shrink_to_fit();
779 xsect_batch_shape.shrink_to_fit();
780 setting.shrink_to_fit();
781 target_setting.shrink_to_fit();
782 direction.shrink_to_fit();
783
784 has_flap_gate.shrink_to_fit();
785 dqdh.shrink_to_fit();
786 pump_curve_name.shrink_to_fit();
787
788 flow.shrink_to_fit();
789 depth.shrink_to_fit();
790 volume.shrink_to_fit();
791 froude.shrink_to_fit();
792 flow_class.shrink_to_fit();
793 is_closed.shrink_to_fit();
794 old_flow.shrink_to_fit();
795 old_depth.shrink_to_fit();
796 old_volume.shrink_to_fit();
797 conc.shrink_to_fit();
798 conc_old.shrink_to_fit();
799
800 comments.shrink_to_fit();
801 tags.shrink_to_fit();
802
803 rpt_flag.shrink_to_fit();
804
805 stat_vol_flow.shrink_to_fit();
806 stat_max_flow.shrink_to_fit();
807 stat_max_veloc.shrink_to_fit();
808 stat_max_filling.shrink_to_fit();
809 stat_time_surcharged.shrink_to_fit();
810 stat_flow_class.shrink_to_fit();
811 stat_norm_ltd.shrink_to_fit();
812 stat_inlet_ctrl.shrink_to_fit();
813 stat_max_flow_date.shrink_to_fit();
814 stat_time_full_upstream.shrink_to_fit();
815 stat_time_full_dnstream.shrink_to_fit();
816 stat_time_full_both.shrink_to_fit();
817 stat_time_capacity_limited.shrink_to_fit();
818 stat_pump_cycles.shrink_to_fit();
819 stat_pump_on_time.shrink_to_fit();
820 stat_pump_volume.shrink_to_fit();
821 stat_pump_energy.shrink_to_fit();
822 stat_pump_was_on.shrink_to_fit();
823 stat_total_load.shrink_to_fit();
824 }
825
826 void save_state() noexcept {
827 std::copy(flow.begin(), flow.end(), old_flow.begin());
828 std::copy(depth.begin(), depth.end(), old_depth.begin());
829 std::copy(volume.begin(), volume.end(), old_volume.begin());
830 std::copy(conc.begin(), conc.end(), conc_old.begin());
831 }
832
833 void reset_state() noexcept {
834 std::fill(flow.begin(), flow.end(), 0.0);
835 std::fill(depth.begin(), depth.end(), 0.0);
836 std::fill(volume.begin(), volume.end(), 0.0);
837 std::fill(froude.begin(), froude.end(), 0.0);
838 std::fill(flow_class.begin(), flow_class.end(), FlowClass::DRY);
839 std::fill(old_flow.begin(), old_flow.end(), 0.0);
840 std::fill(old_depth.begin(), old_depth.end(), 0.0);
841 std::fill(old_volume.begin(), old_volume.end(), 0.0);
842 std::fill(conc.begin(), conc.end(), 0.0);
843 std::fill(conc_old.begin(), conc_old.end(), 0.0);
844 }
845};
846
847} /* namespace openswmm */
848
849#endif /* OPENSWMM_ENGINE_LINK_DATA_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
FlowClass
Link flow state.
Definition LinkData.hpp:87
@ SUPERCRITICAL
Definition LinkData.hpp:92
@ DN_CRITICAL
Definition LinkData.hpp:94
@ SUBCRITICAL
Definition LinkData.hpp:91
@ UP_CRITICAL
Definition LinkData.hpp:93
@ DRY
Definition LinkData.hpp:88
@ UP_DRY
Definition LinkData.hpp:89
@ DN_DRY
Definition LinkData.hpp:90
XsectShape
Conduit cross-section shape code.
Definition LinkData.hpp:54
@ TRIANGULAR
Definition LinkData.hpp:60
@ RECT_CLOSED
Definition LinkData.hpp:57
@ ARCH
Arch pipe.
Definition LinkData.hpp:75
@ FORCE_MAIN
Circular force main (Hazen-Williams or D-W)
Definition LinkData.hpp:78
@ RECT_OPEN
Definition LinkData.hpp:58
@ BASKETHANDLE
Definition LinkData.hpp:69
@ STREET_XSECT
Street cross-section.
Definition LinkData.hpp:79
@ SEMICIRCULAR
Definition LinkData.hpp:70
@ IRREGULAR
User-supplied shape curve.
Definition LinkData.hpp:76
@ HORIZ_ELLIPSE
Horizontal elliptical pipe.
Definition LinkData.hpp:73
@ VERT_ELLIPSE
Vertical elliptical pipe.
Definition LinkData.hpp:74
@ CUSTOM
Shape from CURVE_SHAPE table.
Definition LinkData.hpp:77
@ RECT_ROUND
Rectangular-round bottom.
Definition LinkData.hpp:72
@ EGGSHAPED
Definition LinkData.hpp:64
@ SEMIELLIPTICAL
Definition LinkData.hpp:68
@ CATENARY
Definition LinkData.hpp:67
@ CIRCULAR
Definition LinkData.hpp:55
@ TRAPEZOIDAL
Definition LinkData.hpp:59
@ MODBASKETHANDLE
Definition LinkData.hpp:63
@ HORSESHOE
Definition LinkData.hpp:65
@ DUMMY
Dummy (no geometry)
Definition LinkData.hpp:80
@ PARABOLIC
Definition LinkData.hpp:61
@ POWER
Definition LinkData.hpp:62
@ RECT_TRIANG
Rectangular-triangular bottom.
Definition LinkData.hpp:71
@ FILLED_CIRCULAR
Definition LinkData.hpp:56
@ GOTHIC
Definition LinkData.hpp:66