OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
NodeData.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
40
46
47#ifndef OPENSWMM_ENGINE_NODE_DATA_HPP
48#define OPENSWMM_ENGINE_NODE_DATA_HPP
49
50#include <vector>
51#include <cstdint>
52#include <string>
53#include <algorithm>
54
55namespace openswmm {
56
57// ============================================================================
58// Node type enumeration
59// ============================================================================
60
65enum class NodeType : int8_t { JUNCTION = 0, OUTFALL = 1, DIVIDER = 2, STORAGE = 3 };
66
71enum class OutfallType : int8_t { FREE = 0, NORMAL = 1, FIXED = 2, TIDAL = 3, TIMESERIES = 4 };
72
77enum class DividerType : int8_t {
78 CUTOFF = 0,
81 WEIR = 3
82};
83
99enum class StorageShape : int8_t {
106};
107
108// ============================================================================
109// NodeData — SoA layout
110// ============================================================================
111
125struct NodeData {
126
127 // -----------------------------------------------------------------------
128 // Static properties — set at parse time
129 // -----------------------------------------------------------------------
130
132 std::vector<NodeType> type;
133
138 std::vector<double> invert_elev;
139
144 std::vector<double> full_depth;
145
150 std::vector<double> init_depth;
151
156 std::vector<double> sur_depth;
157
162 std::vector<double> ponded_area;
163 std::vector<double> storage_area;
164
174 std::vector<uint8_t> is_virtual;
175
186 std::vector<uint8_t> is_inlet;
187
202 std::vector<double> rim_depth;
203
204 // -----------------------------------------------------------------------
205 // Node subtype properties (storage / outfall / divider)
206 // -----------------------------------------------------------------------
207 // Relational node refactor (Phase 4): the wide per-node storage_* / outfall_*
208 // / divider_* / exfil_* arrays that used to live here have been REMOVED. They
209 // now live in the dense relational side-tables (StorageData / OutfallData /
210 // DividerData in NodeSubtypes.hpp), sized to the count of each subtype and
211 // joined to base nodes by node_idx — the memory win of the refactor. Only the
212 // base `type[i]` discriminator remains on NodeData. See
213 // docs/relational/RELATIONAL_NODE_REFACTOR_PLAN.md.
214
215 // -----------------------------------------------------------------------
216 // State variables — updated each timestep
217 // -----------------------------------------------------------------------
218
223 std::vector<double> depth;
224
229 std::vector<double> head;
230
235 std::vector<double> volume;
236
241 std::vector<double> lat_flow;
242
250 std::vector<double> user_lat_flow;
251
252 // -----------------------------------------------------------------------
253 // Decomposed lateral inflow sources
254 // Each source process writes to its own buffer.
255 // assembleLateralInflows() sums them all into lat_flow.
256 // -----------------------------------------------------------------------
257
259 std::vector<double> runoff_inflow;
260
262 std::vector<double> gw_inflow;
263
265 std::vector<double> ext_inflow;
266
268 std::vector<double> dwf_inflow;
269
271 std::vector<double> rdii_inflow;
272
274 std::vector<double> iface_inflow;
275
297 std::vector<double> coupling_inflow;
298
312 std::vector<double> coupling_volume;
318 std::vector<uint8_t> aquifer2d_bed;
319
336 std::vector<double> coupling_queue;
337
352 std::vector<double> coupling_qual_queue;
355 std::vector<double> coupling_qual_inflow;
356
367 std::vector<double> coupling_age_vol_queue;
368 std::vector<double> coupling_temp_vol_queue;
369 std::vector<double> coupling_age_vol_inflow;
370 std::vector<double> coupling_temp_vol_inflow;
371 bool coupling_tuple_age = false;
373
374 // -----------------------------------------------------------------------
375 // Quality mass inflow assembly arrays
376 // assembleQualityInflows() writes these; mixAtNodes() reads them.
377 // -----------------------------------------------------------------------
378
381 std::vector<double> qual_mass_in;
382
384 std::vector<double> qual_vol_in;
385
394 std::vector<double> iface_qual_mass;
395
408 std::vector<double> ext_qual_mass;
409
419 std::vector<double> dwf_qual_mass;
420
430 std::vector<double> lid_drain_qual_load;
431
438 std::vector<double> lid_drain_qual_vol;
444 std::vector<double> lid_drain_qual_load_old;
446 std::vector<double> lid_drain_qual_vol_old;
459 std::vector<double> lid_drain_inflow;
460
461 // -----------------------------------------------------------------------
462 // Per-node quality state — flat 2D: [node * n_pollutants + pollutant]
463 // -----------------------------------------------------------------------
464
470 std::vector<double> conc;
471
473 std::vector<double> conc_old;
474
476 std::vector<double> hrt;
477
487 std::vector<double> user_conc_mass_flux;
488
491
496 std::vector<double> inflow;
497
502 std::vector<double> outflow;
503
508 std::vector<double> overflow;
509
514 std::vector<double> losses;
515
520 std::vector<double> crown_elev;
521
532 std::vector<int> degree;
533
538 std::vector<double> old_net_inflow;
539
544 std::vector<double> full_volume;
545
558 std::vector<double> rpt_full_volume;
559
560 // -----------------------------------------------------------------------
561 // Previous-step state (for output interpolation / CFL checks)
562 // -----------------------------------------------------------------------
563
565 std::vector<double> old_depth;
566
568 std::vector<double> old_volume;
569
571 std::vector<double> old_lat_flow;
572
577 std::vector<double> old_inflow;
578
579 // -----------------------------------------------------------------------
580 // Per-object INP comment
581 // -----------------------------------------------------------------------
582
592 std::vector<std::string> comments;
593
605 std::vector<std::string> tags;
606
607 // -----------------------------------------------------------------------
608 // Report flag — per-object output filter
609 // -----------------------------------------------------------------------
610
613 std::vector<char> rpt_flag;
614
615 // -----------------------------------------------------------------------
616 // Cumulative statistics
617 // -----------------------------------------------------------------------
618
623 std::vector<double> stat_vol_flooded;
624
629 std::vector<double> stat_time_flooded;
630
635 std::vector<double> stat_max_depth;
636
641 std::vector<double> stat_max_overflow;
642
644 std::vector<double> stat_max_overflow_date;
645
648 std::vector<double> stat_sum_depth;
649
655 std::vector<double> stat_sum_volume;
656 std::vector<double>
658 std::vector<double> stat_storage_max_volume_date;
659
662 std::vector<double> stat_max_depth_date;
663
666 std::vector<double> stat_max_rpt_depth;
667
670 std::vector<double> stat_max_inflow_date;
671
674 std::vector<double> stat_time_surcharged;
675
678 std::vector<double> stat_max_surcharge_height;
679
684 std::vector<double> stat_outfall_avg_flow;
685
688 std::vector<double> stat_max_lat_inflow;
689
692 std::vector<double> stat_max_total_inflow;
693
698 std::vector<double> stat_storage_max_outflow;
699
702 std::vector<double> stat_lat_inflow_vol;
703
705 std::vector<double> stat_total_inflow_vol;
706
709 std::vector<double> stat_total_outflow_vol;
710
715 std::vector<double> stat_outfall_max_flow;
716
721 std::vector<long> stat_outfall_periods;
722
729 std::vector<int> stat_non_converged_count;
730
738 std::vector<double> stat_time_courant_critical;
739
746 std::vector<double> stat_total_load;
748
749 // -----------------------------------------------------------------------
750 // Capacity management
751 // -----------------------------------------------------------------------
752
754 int count() const noexcept { return static_cast<int>(type.size()); }
755
768 void resize(int n) {
769 const auto un = static_cast<std::size_t>(n);
770 type.assign(un, NodeType::JUNCTION);
771 invert_elev.assign(un, 0.0);
772 full_depth.assign(un, 0.0);
773 init_depth.assign(un, 0.0);
774 sur_depth.assign(un, 0.0);
775 ponded_area.assign(un, 0.0);
776 storage_area.assign(un, 0.0);
777 is_virtual.assign(un, 0);
778 is_inlet.assign(un, 0);
779 rim_depth.assign(un, 0.0);
780
781 // Subtype config (storage/outfall/divider) lives in NodeSubtypes side-tables.
782 depth.assign(un, 0.0);
783 head.assign(un, 0.0);
784 volume.assign(un, 0.0);
785 lat_flow.assign(un, 0.0);
786 user_lat_flow.assign(un, 0.0);
787 runoff_inflow.assign(un, 0.0);
788 gw_inflow.assign(un, 0.0);
789 ext_inflow.assign(un, 0.0);
790 dwf_inflow.assign(un, 0.0);
791 rdii_inflow.assign(un, 0.0);
792 iface_inflow.assign(un, 0.0);
793 coupling_inflow.assign(un, 0.0);
794 coupling_volume.assign(un, 0.0);
795 coupling_queue.assign(un, 0.0);
796 coupling_age_vol_queue.assign(un, 0.0);
797 coupling_temp_vol_queue.assign(un, 0.0);
798 coupling_age_vol_inflow.assign(un, 0.0);
799 coupling_temp_vol_inflow.assign(un, 0.0);
800 qual_mass_in.clear();
801 iface_qual_mass.clear();
802 coupling_qual_queue.clear();
803 coupling_qual_inflow.clear();
804 ext_qual_mass.clear();
805 dwf_qual_mass.clear();
806 qual_vol_in.assign(un, 0.0);
807 lid_drain_qual_load.clear();
808 lid_drain_qual_vol.assign(un, 0.0);
810 lid_drain_qual_vol_old.assign(un, 0.0);
811 lid_drain_inflow.assign(un, 0.0);
812 inflow.assign(un, 0.0);
813 outflow.assign(un, 0.0);
814 overflow.assign(un, 0.0);
815 losses.assign(un, 0.0);
816 crown_elev.assign(un, 0.0);
817 degree.assign(un, 0);
818 old_net_inflow.assign(un, 0.0);
819 full_volume.assign(un, 0.0);
820 rpt_full_volume.assign(un, 0.0);
821 old_depth.assign(un, 0.0);
822 old_volume.assign(un, 0.0);
823 old_lat_flow.assign(un, 0.0);
824 old_inflow.assign(un, 0.0);
825
826 comments.assign(un, std::string{});
827 tags.assign(un, std::string{});
828
829 rpt_flag.assign(un, 0);
830
831 stat_vol_flooded.assign(un, 0.0);
832 stat_time_flooded.assign(un, 0.0);
833 stat_max_depth.assign(un, 0.0);
834 stat_max_overflow.assign(un, 0.0);
835 stat_max_overflow_date.assign(un, 0.0);
836 stat_sum_depth.assign(un, 0.0);
837 stat_sum_volume.assign(un, 0.0);
838 stat_storage_max_volume_date.assign(un, 0.0);
839 stat_storage_max_volume.assign(un, 0.0);
840 stat_max_depth_date.assign(un, 0.0);
841 stat_max_rpt_depth.assign(un, 0.0);
842 stat_max_inflow_date.assign(un, 0.0);
843 stat_time_surcharged.assign(un, 0.0);
844 stat_max_surcharge_height.assign(un, 0.0);
845 stat_max_lat_inflow.assign(un, 0.0);
846 stat_max_total_inflow.assign(un, 0.0);
847 stat_storage_max_outflow.assign(un, 0.0);
848 stat_lat_inflow_vol.assign(un, 0.0);
849 stat_total_inflow_vol.assign(un, 0.0);
850 stat_total_outflow_vol.assign(un, 0.0);
851 stat_outfall_avg_flow.assign(un, 0.0);
852 stat_outfall_max_flow.assign(un, 0.0);
853 stat_outfall_periods.assign(un, 0);
854 stat_non_converged_count.assign(un, 0);
855 stat_time_courant_critical.assign(un, 0.0);
856 }
857
867 void grow_to(int n) {
868 if (n <= count())
869 return;
870 const auto un = static_cast<std::size_t>(n);
871 auto g = [&](auto& vec, auto def) { vec.resize(un, def); };
873 g(invert_elev, 0.0);
874 g(full_depth, 0.0);
875 g(init_depth, 0.0);
876 g(sur_depth, 0.0);
877 g(ponded_area, 0.0);
878 g(storage_area, 0.0);
879 g(is_virtual, static_cast<uint8_t>(0));
880 g(is_inlet, static_cast<uint8_t>(0));
881 g(rim_depth, 0.0);
882 // Subtype config (storage/outfall/divider) lives in NodeSubtypes side-tables.
883 g(depth, 0.0);
884 g(head, 0.0);
885 g(volume, 0.0);
886 g(lat_flow, 0.0);
887 g(user_lat_flow, 0.0);
888 g(runoff_inflow, 0.0);
889 g(gw_inflow, 0.0);
890 g(ext_inflow, 0.0);
891 g(dwf_inflow, 0.0);
892 g(rdii_inflow, 0.0);
893 g(iface_inflow, 0.0);
894 g(coupling_inflow, 0.0);
895 g(coupling_volume, 0.0);
896 g(coupling_queue, 0.0);
901 qual_vol_in.resize(un, 0.0);
902 lid_drain_qual_vol.resize(un, 0.0);
903 lid_drain_qual_vol_old.resize(un, 0.0);
904 lid_drain_inflow.resize(un, 0.0);
905 g(inflow, 0.0);
906 g(outflow, 0.0);
907 g(overflow, 0.0);
908 g(losses, 0.0);
909 g(crown_elev, 0.0);
910 g(degree, 0);
911 g(old_net_inflow, 0.0);
912 g(full_volume, 0.0);
913 g(rpt_full_volume, 0.0);
914 g(old_depth, 0.0);
915 g(old_volume, 0.0);
916 g(old_lat_flow, 0.0);
917 g(old_inflow, 0.0);
918 comments.resize(un, std::string{});
919 tags.resize(un, std::string{});
920
921 g(rpt_flag, static_cast<char>(0));
922 g(stat_vol_flooded, 0.0);
923 g(stat_time_flooded, 0.0);
924 g(stat_max_depth, 0.0);
925 g(stat_max_overflow, 0.0);
927 g(stat_sum_depth, 0.0);
928 g(stat_sum_volume, 0.0);
931 g(stat_max_depth_date, 0.0);
932 g(stat_max_rpt_depth, 0.0);
933 g(stat_max_inflow_date, 0.0);
934 g(stat_time_surcharged, 0.0);
936 g(stat_max_lat_inflow, 0.0);
937 g(stat_max_total_inflow, 0.0);
939 g(stat_lat_inflow_vol, 0.0);
940 g(stat_total_inflow_vol, 0.0);
942 g(stat_outfall_avg_flow, 0.0);
943 g(stat_outfall_max_flow, 0.0);
947 // Note: qual_mass_in, conc, conc_old, hrt handled by resize_quality()
948 }
949
971 void reserve_to(int n) {
972 if (n <= 0)
973 return;
974 const auto un = static_cast<std::size_t>(n);
975 if (type.capacity() >= un)
976 return;
977 auto r = [&](auto& vec) { vec.reserve(un); };
978 r(type);
979 r(invert_elev);
980 r(full_depth);
981 r(init_depth);
982 r(sur_depth);
983 r(ponded_area);
984 r(storage_area);
985 r(is_virtual);
986 r(is_inlet);
987 r(rim_depth);
988 r(depth);
989 r(head);
990 r(volume);
991 r(lat_flow);
992 r(user_lat_flow);
993 r(runoff_inflow);
994 r(gw_inflow);
995 r(ext_inflow);
996 r(dwf_inflow);
997 r(rdii_inflow);
998 r(iface_inflow);
1000 r(coupling_volume);
1001 r(coupling_queue);
1002 r(inflow);
1003 r(outflow);
1004 r(overflow);
1009 r(losses);
1010 r(crown_elev);
1011 r(degree);
1012 r(old_net_inflow);
1013 r(full_volume);
1014 r(rpt_full_volume);
1015 r(old_depth);
1016 r(old_volume);
1017 r(old_lat_flow);
1018 r(old_inflow);
1019 r(rpt_flag);
1022 r(stat_max_depth);
1025 r(stat_sum_depth);
1026 r(stat_sum_volume);
1045 r(qual_vol_in);
1048 r(comments);
1049 r(tags);
1050 }
1051
1064 void erase_at(int idx) {
1065 const auto ui = static_cast<std::size_t>(idx);
1066 auto e = [&](auto& v) {
1067 if (ui < v.size())
1068 v.erase(v.begin() + static_cast<std::ptrdiff_t>(idx));
1069 };
1070
1071 e(type);
1072 e(invert_elev);
1073 e(full_depth);
1074 e(init_depth);
1075 e(sur_depth);
1076 e(ponded_area);
1077 e(storage_area);
1078 e(is_virtual);
1079 e(is_inlet);
1080 e(rim_depth);
1081
1082 // Subtype config (storage/outfall/divider) lives in NodeSubtypes side-tables;
1083 // its rows are erased/renumbered by NodeSubtypes::erase_node (called by the
1084 // node-delete path), not here.
1085 e(depth);
1086 e(head);
1087 e(volume);
1088 e(lat_flow);
1089 e(user_lat_flow);
1090 e(runoff_inflow);
1091 e(gw_inflow);
1092 e(ext_inflow);
1093 e(dwf_inflow);
1094 e(rdii_inflow);
1095 e(iface_inflow);
1096 e(coupling_inflow);
1097 e(coupling_volume);
1098 e(coupling_queue);
1103 e(qual_vol_in);
1106 e(inflow);
1107 e(outflow);
1108 e(overflow);
1109 e(losses);
1110 e(crown_elev);
1111 e(degree);
1112 e(old_net_inflow);
1113 e(full_volume);
1114 e(rpt_full_volume);
1115 e(old_depth);
1116 e(old_volume);
1117 e(old_lat_flow);
1118 e(old_inflow);
1119 e(comments);
1120 e(tags);
1121 e(rpt_flag);
1122
1125 e(stat_max_depth);
1128 e(stat_sum_depth);
1129 e(stat_sum_volume);
1148
1149 // Flat 2D quality arrays: [node * np + p] → erase the stride for idx
1150 if (conc_n_pollutants > 0) {
1151 const auto np = static_cast<std::size_t>(conc_n_pollutants);
1152 const auto base = ui * np;
1153 auto erase2d = [&](auto& v) {
1154 if (base + np <= v.size())
1155 v.erase(v.begin() + static_cast<std::ptrdiff_t>(base),
1156 v.begin() + static_cast<std::ptrdiff_t>(base + np));
1157 };
1158 erase2d(conc);
1159 erase2d(conc_old);
1160 erase2d(qual_mass_in);
1161 erase2d(iface_qual_mass);
1162 erase2d(coupling_qual_queue);
1163 erase2d(coupling_qual_inflow);
1164 erase2d(ext_qual_mass);
1165 erase2d(dwf_qual_mass);
1166 erase2d(lid_drain_qual_load);
1167 erase2d(user_conc_mass_flux);
1168 if (ui < hrt.size())
1169 hrt.erase(hrt.begin() + static_cast<std::ptrdiff_t>(idx));
1170 }
1171
1172 // Flat 2D stat load: [node * np + p]
1173 if (stat_n_pollutants > 0) {
1174 const auto np = static_cast<std::size_t>(stat_n_pollutants);
1175 const auto base = ui * np;
1176 if (base + np <= stat_total_load.size())
1177 stat_total_load.erase(stat_total_load.begin() + static_cast<std::ptrdiff_t>(base),
1178 stat_total_load.begin() +
1179 static_cast<std::ptrdiff_t>(base + np));
1180 }
1181 }
1182
1192 void resize_loads(int n_pollutants) {
1193 stat_n_pollutants = n_pollutants;
1194 if (n_pollutants > 0) {
1195 auto total = static_cast<std::size_t>(count()) * static_cast<std::size_t>(n_pollutants);
1196 stat_total_load.assign(total, 0.0);
1197 }
1198 }
1199
1211 void resize_quality(int n_pollutants) {
1212 conc_n_pollutants = n_pollutants;
1213 if (n_pollutants > 0) {
1214 auto total = static_cast<std::size_t>(count()) * static_cast<std::size_t>(n_pollutants);
1215 conc.assign(total, 0.0);
1216 conc_old.assign(total, 0.0);
1217 hrt.assign(static_cast<std::size_t>(count()), 0.0);
1218 user_conc_mass_flux.assign(total, 0.0);
1219 qual_mass_in.assign(total, 0.0);
1220 iface_qual_mass.assign(total, 0.0);
1221 coupling_qual_queue.assign(total, 0.0);
1222 coupling_qual_inflow.assign(total, 0.0);
1223 ext_qual_mass.assign(total, 0.0);
1224 dwf_qual_mass.assign(total, 0.0);
1225 lid_drain_qual_load.assign(total, 0.0);
1226 }
1227 }
1228
1237 type.shrink_to_fit();
1238 invert_elev.shrink_to_fit();
1239 full_depth.shrink_to_fit();
1240 init_depth.shrink_to_fit();
1241 sur_depth.shrink_to_fit();
1242 ponded_area.shrink_to_fit();
1243 storage_area.shrink_to_fit();
1244 is_virtual.shrink_to_fit();
1245 is_inlet.shrink_to_fit();
1246 rim_depth.shrink_to_fit();
1247
1248 // Subtype config (storage/outfall/divider) lives in NodeSubtypes side-tables.
1249 depth.shrink_to_fit();
1250 head.shrink_to_fit();
1251 volume.shrink_to_fit();
1252 lat_flow.shrink_to_fit();
1253 user_lat_flow.shrink_to_fit();
1254 runoff_inflow.shrink_to_fit();
1255 gw_inflow.shrink_to_fit();
1256 ext_inflow.shrink_to_fit();
1257 dwf_inflow.shrink_to_fit();
1258 rdii_inflow.shrink_to_fit();
1259 iface_inflow.shrink_to_fit();
1260 coupling_inflow.shrink_to_fit();
1261 coupling_volume.shrink_to_fit();
1262 coupling_queue.shrink_to_fit();
1263 coupling_age_vol_queue.shrink_to_fit();
1264 coupling_temp_vol_queue.shrink_to_fit();
1265 coupling_age_vol_inflow.shrink_to_fit();
1266 coupling_temp_vol_inflow.shrink_to_fit();
1267 qual_mass_in.shrink_to_fit();
1268 iface_qual_mass.shrink_to_fit();
1269 coupling_qual_queue.shrink_to_fit();
1270 coupling_qual_inflow.shrink_to_fit();
1271 ext_qual_mass.shrink_to_fit();
1272 dwf_qual_mass.shrink_to_fit();
1273 qual_vol_in.shrink_to_fit();
1274 conc.shrink_to_fit();
1275 conc_old.shrink_to_fit();
1276 user_conc_mass_flux.shrink_to_fit();
1277 inflow.shrink_to_fit();
1278 outflow.shrink_to_fit();
1279 overflow.shrink_to_fit();
1280 losses.shrink_to_fit();
1281 crown_elev.shrink_to_fit();
1282 degree.shrink_to_fit();
1283 old_net_inflow.shrink_to_fit();
1284 full_volume.shrink_to_fit();
1285 rpt_full_volume.shrink_to_fit();
1286 old_depth.shrink_to_fit();
1287 old_volume.shrink_to_fit();
1288 old_lat_flow.shrink_to_fit();
1289 old_inflow.shrink_to_fit();
1290
1291 comments.shrink_to_fit();
1292 tags.shrink_to_fit();
1293
1294 rpt_flag.shrink_to_fit();
1295
1296 stat_vol_flooded.shrink_to_fit();
1297 stat_time_flooded.shrink_to_fit();
1298 stat_max_depth.shrink_to_fit();
1299 stat_max_overflow.shrink_to_fit();
1300 stat_max_overflow_date.shrink_to_fit();
1301 stat_sum_depth.shrink_to_fit();
1302 stat_max_depth_date.shrink_to_fit();
1303 stat_max_rpt_depth.shrink_to_fit();
1304 stat_max_inflow_date.shrink_to_fit();
1305 stat_time_surcharged.shrink_to_fit();
1306 stat_max_surcharge_height.shrink_to_fit();
1307 stat_max_lat_inflow.shrink_to_fit();
1308 stat_max_total_inflow.shrink_to_fit();
1309 stat_storage_max_outflow.shrink_to_fit();
1310 stat_lat_inflow_vol.shrink_to_fit();
1311 stat_total_inflow_vol.shrink_to_fit();
1312 stat_total_outflow_vol.shrink_to_fit();
1313 stat_outfall_avg_flow.shrink_to_fit();
1314 stat_outfall_max_flow.shrink_to_fit();
1315 stat_outfall_periods.shrink_to_fit();
1316 stat_total_load.shrink_to_fit();
1317 }
1318
1322 void save_state() noexcept {
1325 }
1326
1334 void save_hyd_state() noexcept {
1335 std::copy(depth.begin(), depth.end(), old_depth.begin());
1336 std::copy(volume.begin(), volume.end(), old_volume.begin());
1337 std::copy(inflow.begin(), inflow.end(), old_inflow.begin());
1338 // Save net inflow for trapezoidal averaging in next step
1339 for (std::size_t i = 0; i < inflow.size(); ++i) {
1340 old_net_inflow[i] = inflow[i] - outflow[i];
1341 }
1342 }
1343
1351 void save_lat_qual_state() noexcept {
1352 std::copy(lat_flow.begin(), lat_flow.end(), old_lat_flow.begin());
1353 std::copy(conc.begin(), conc.end(), conc_old.begin());
1354 }
1355
1364 void reset_state() noexcept {
1365 const auto n = depth.size();
1366 // Apply initial depths from input (matching legacy node_initState)
1367 for (std::size_t i = 0; i < n; ++i) {
1368 depth[i] = init_depth[i];
1369 old_depth[i] = init_depth[i];
1370 head[i] = invert_elev[i] + init_depth[i];
1371 }
1372 // Volumes must be computed from init_depth by caller (needs table data)
1373 std::fill(volume.begin(), volume.end(), 0.0);
1374 std::fill(old_volume.begin(), old_volume.end(), 0.0);
1375 // Zero flows
1376 std::fill(lat_flow.begin(), lat_flow.end(), 0.0);
1377 std::fill(inflow.begin(), inflow.end(), 0.0);
1378 std::fill(outflow.begin(), outflow.end(), 0.0);
1379 std::fill(overflow.begin(), overflow.end(), 0.0);
1380 std::fill(losses.begin(), losses.end(), 0.0);
1381 std::fill(old_net_inflow.begin(), old_net_inflow.end(), 0.0);
1382 std::fill(old_lat_flow.begin(), old_lat_flow.end(), 0.0);
1383 std::fill(old_inflow.begin(), old_inflow.end(), 0.0);
1384 // coupling_inflow / coupling_volume / coupling_queue are NOT cleared by
1385 // clearInflowSources (coupling_volume and coupling_queue are the
1386 // carry-across-steps fields — their end-of-step values must persist into
1387 // the next step's assembly), so zero them explicitly on cold start.
1388 std::fill(coupling_inflow.begin(), coupling_inflow.end(), 0.0);
1389 std::fill(coupling_volume.begin(), coupling_volume.end(), 0.0);
1390 std::fill(coupling_queue.begin(), coupling_queue.end(), 0.0);
1391 std::fill(coupling_qual_queue.begin(), coupling_qual_queue.end(), 0.0);
1392 std::fill(coupling_qual_inflow.begin(), coupling_qual_inflow.end(), 0.0);
1393 std::fill(coupling_age_vol_queue.begin(), coupling_age_vol_queue.end(), 0.0);
1394 std::fill(coupling_temp_vol_queue.begin(), coupling_temp_vol_queue.end(), 0.0);
1395 std::fill(coupling_age_vol_inflow.begin(), coupling_age_vol_inflow.end(), 0.0);
1396 std::fill(coupling_temp_vol_inflow.begin(), coupling_temp_vol_inflow.end(), 0.0);
1398 std::fill(conc.begin(), conc.end(), 0.0);
1399 std::fill(conc_old.begin(), conc_old.end(), 0.0);
1400 (void)n;
1401 }
1402
1412 void clearInflowSources() noexcept {
1413 // runoff_inflow and gw_inflow: zeroed in stepRunoff() Phase 2
1414 std::fill(ext_inflow.begin(), ext_inflow.end(), 0.0);
1415 std::fill(dwf_inflow.begin(), dwf_inflow.end(), 0.0);
1416 std::fill(rdii_inflow.begin(), rdii_inflow.end(), 0.0);
1417 std::fill(iface_inflow.begin(), iface_inflow.end(), 0.0);
1418 std::fill(iface_qual_mass.begin(), iface_qual_mass.end(), 0.0);
1419 std::fill(ext_qual_mass.begin(), ext_qual_mass.end(), 0.0);
1420 std::fill(dwf_qual_mass.begin(), dwf_qual_mass.end(), 0.0);
1421 std::fill(qual_mass_in.begin(), qual_mass_in.end(), 0.0);
1422 std::fill(qual_vol_in.begin(), qual_vol_in.end(), 0.0);
1423 }
1424};
1425
1426} /* namespace openswmm */
1427
1428#endif /* OPENSWMM_ENGINE_NODE_DATA_HPP */
Definition ExchangeLaw.hpp:60
StorageShape
Storage-unit surface-area relation.
Definition NodeData.hpp:99
@ CONICAL
Elliptical cone (p1, p2 = base axes, p3 = side slope)
Definition NodeData.hpp:103
@ PYRAMIDAL
Rectangular pyramid (p1 = length, p2 = width, p3 = side slope)
Definition NodeData.hpp:105
@ PARABOLOID
Elliptical paraboloid(p1, p2 = top axes, p3 = height ≠ 0)
Definition NodeData.hpp:104
@ CYLINDRICAL
Elliptical cylinder (p1 = major axis, p2 = minor axis)
Definition NodeData.hpp:102
@ FUNCTIONAL
Area = c + a*d^b.
Definition NodeData.hpp:101
@ STORAGE
Definition LidLayerSpeciesData.hpp:52
@ WEIR
Definition LinkData.hpp:58
OutfallType
Outfall boundary condition type.
Definition NodeData.hpp:71
@ NORMAL
Definition NodeData.hpp:71
@ FREE
Definition NodeData.hpp:71
@ FIXED
Definition NodeData.hpp:71
@ TIDAL
Definition NodeData.hpp:71
NodeType
Node type codes.
Definition NodeData.hpp:65
@ JUNCTION
Definition NodeData.hpp:65
@ DIVIDER
Definition NodeData.hpp:65
DividerType
Flow divider type.
Definition NodeData.hpp:77
@ CUTOFF
Definition NodeData.hpp:78
@ TABULAR
Definition NodeData.hpp:80
@ OVERFLOW_DIV
Renamed from OVERFLOW to avoid macOS math.h macro collision.
Definition NodeData.hpp:79
@ TIMESERIES
Data from an in-file [TIMESERIES].
Definition GageData.hpp:58
@ OUTFALL
tailwater + discharge mechanism, not an exchange law
Definition NodeCoupling2DData.hpp:42
Structure-of-Arrays storage for all nodes.
Definition NodeData.hpp:125
std::vector< double > coupling_inflow
2D ↔ 1D coupling exchange flow at the node (project flow units).
Definition NodeData.hpp:297
std::vector< double > stat_lat_inflow_vol
Definition NodeData.hpp:702
bool coupling_tuple_temp
Definition NodeData.hpp:372
int count() const noexcept
Number of nodes.
Definition NodeData.hpp:754
std::vector< double > depth
Current water depth above invert (project length units).
Definition NodeData.hpp:223
std::vector< double > invert_elev
Invert elevation (project length units).
Definition NodeData.hpp:138
std::vector< double > ext_inflow
External (timeseries/baseline) inflows (project flow units).
Definition NodeData.hpp:265
std::vector< double > conc_old
Previous-step quality at each node.
Definition NodeData.hpp:473
std::vector< double > iface_inflow
Interface file (upstream model coupling) inflows (project flow units).
Definition NodeData.hpp:274
std::vector< double > coupling_queue
Delivery queue for the 1D↔2D junction exchange (1D units, ft³).
Definition NodeData.hpp:336
std::vector< double > qual_mass_in
Accumulated quality mass inflow rate per (node, pollutant).
Definition NodeData.hpp:381
void save_hyd_state() noexcept
Snapshot depth, volume, inflow and net inflow for a routed hydraulic step.
Definition NodeData.hpp:1334
std::vector< double > stat_vol_flooded
Total volume of water lost as overflow (project volume units).
Definition NodeData.hpp:623
std::vector< double > stat_time_courant_critical
CFL time-step critical count per node.
Definition NodeData.hpp:738
std::vector< double > old_inflow
Total inflow at the previous timestep (for output interpolation).
Definition NodeData.hpp:577
void erase_at(int idx)
Erase one node row from the columns visited by this helper.
Definition NodeData.hpp:1064
std::vector< double > coupling_age_vol_inflow
Definition NodeData.hpp:369
std::vector< double > hrt
Hydraulic residence time for storage nodes (seconds).
Definition NodeData.hpp:476
std::vector< double > old_depth
Depth at the previous timestep.
Definition NodeData.hpp:565
void reset_state() noexcept
Apply initial node depths and clear the hydraulic/quality state visited here.
Definition NodeData.hpp:1364
std::vector< double > qual_vol_in
Accumulated volume inflow rate per node (ft3/sec).
Definition NodeData.hpp:384
std::vector< double > coupling_volume
Pending 1D↔2D exchange VOLUME for the next routing step (1D units, ft³).
Definition NodeData.hpp:312
std::vector< double > old_volume
Volume at the previous timestep.
Definition NodeData.hpp:568
std::vector< double > stat_total_outflow_vol
Definition NodeData.hpp:709
std::vector< uint8_t > aquifer2d_bed
Definition NodeData.hpp:318
std::vector< double > user_conc_mass_flux
User-forced quality mass flux at each node (mass/sec).
Definition NodeData.hpp:487
void reserve_to(int n)
Reserve capacity for n nodes without changing count().
Definition NodeData.hpp:971
std::vector< double > coupling_temp_vol_inflow
Definition NodeData.hpp:370
std::vector< double > coupling_age_vol_queue
S4 — the tuple's age-volume and temperature-volume halves, per node (age·ft³ / °C·ft³ queued; age·ft³...
Definition NodeData.hpp:367
bool coupling_tuple_age
set by SurfaceRouter2D at initialize
Definition NodeData.hpp:371
void shrink_to_fit()
Release excess vector capacity accumulated during parsing.
Definition NodeData.hpp:1236
std::vector< double > stat_max_surcharge_height
Definition NodeData.hpp:678
std::vector< double > lid_drain_qual_vol_old
Previous runoff step's lid_drain_qual_vol (the q half of the pair).
Definition NodeData.hpp:446
std::vector< double > stat_max_overflow
Maximum reported overflow rate (project flow units).
Definition NodeData.hpp:641
std::vector< char > rpt_flag
Whether this node is included in report/output (0=no, 1=yes).
Definition NodeData.hpp:613
std::vector< double > outflow
Current total outflow from the node (project flow units).
Definition NodeData.hpp:502
void clearInflowSources() noexcept
Zero routing-phase inflow source arrays.
Definition NodeData.hpp:1412
std::vector< double > dwf_qual_mass
Per-node DWF pollutant mass-rate ADJUSTMENT (mass/sec), net of the global default: row mass (q·patter...
Definition NodeData.hpp:419
std::vector< double > overflow
Current overflow / ponded flow (project flow units).
Definition NodeData.hpp:508
std::vector< double > old_net_inflow
Net inflow from previous timestep (inflow - outflow) for averaging.
Definition NodeData.hpp:538
std::vector< double > stat_storage_max_outflow
Definition NodeData.hpp:698
std::vector< uint8_t > is_virtual
Virtual-junction flag (0 = regular node, 1 = virtual junction).
Definition NodeData.hpp:174
std::vector< double > stat_max_depth_date
Definition NodeData.hpp:662
std::vector< double > stat_max_lat_inflow
Definition NodeData.hpp:688
std::vector< double > stat_outfall_max_flow
Outfall maximum flow (project flow units).
Definition NodeData.hpp:715
std::vector< double > volume
Current water volume (project volume units).
Definition NodeData.hpp:235
std::vector< double > rpt_full_volume
Full volume in the LEGACY convention (legacy Node.fullVolume as node_validate leaves it): 0 for junct...
Definition NodeData.hpp:558
int conc_n_pollutants
Number of pollutants in the quality arrays.
Definition NodeData.hpp:490
std::vector< double > iface_qual_mass
Routing interface file quality mass rate per (node, pollutant) (mass/sec).
Definition NodeData.hpp:394
std::vector< double > lat_flow
Current lateral inflow (project flow units).
Definition NodeData.hpp:241
std::vector< double > ponded_area
Ponding area at the surface (sq project length units).
Definition NodeData.hpp:162
std::vector< double > storage_area
Physical junction area (ft2); zero retains legacy behavior.
Definition NodeData.hpp:163
std::vector< double > stat_total_inflow_vol
Cumulative total inflow volume at each node (ft3).
Definition NodeData.hpp:705
std::vector< double > stat_storage_max_volume
Maximum stored volume, capped at full volume (ft3).
Definition NodeData.hpp:657
std::vector< double > coupling_temp_vol_queue
Definition NodeData.hpp:368
std::vector< double > sur_depth
Maximum depth allowed at the node (ponding or surcharge limit).
Definition NodeData.hpp:156
std::vector< double > stat_storage_max_volume_date
Date of the first maximum stored volume.
Definition NodeData.hpp:658
std::vector< double > crown_elev
Crown elevation — top of highest connecting conduit (project length units).
Definition NodeData.hpp:520
std::vector< double > stat_max_inflow_date
Definition NodeData.hpp:670
std::vector< double > old_lat_flow
Lateral flow at the previous timestep.
Definition NodeData.hpp:571
std::vector< double > stat_outfall_avg_flow
Outfall cumulative average flow (flow units × reporting periods).
Definition NodeData.hpp:684
std::vector< double > inflow
Current total inflow to the node (project flow units).
Definition NodeData.hpp:496
void save_state() noexcept
Snapshot current state into old-step arrays before solving.
Definition NodeData.hpp:1322
std::vector< double > stat_time_surcharged
Definition NodeData.hpp:674
std::vector< double > stat_max_depth
Maximum reported depth (project length units).
Definition NodeData.hpp:635
std::vector< double > coupling_qual_queue
S3 — species MASS queue for the 2D→1D junction drain, per (node, pollutant), 1D mass units (conc × ft...
Definition NodeData.hpp:352
std::vector< double > lid_drain_qual_load_old
Definition NodeData.hpp:444
std::vector< long > stat_outfall_periods
Outfall number of non-zero flow periods.
Definition NodeData.hpp:721
void resize_loads(int n_pollutants)
Set the pollutant load stride and zero positive-sized load storage.
Definition NodeData.hpp:1192
std::vector< double > conc
Current quality concentration at each node.
Definition NodeData.hpp:470
std::vector< double > ext_qual_mass
Direct external inflow quality mass rate per (node, pollutant) (mass/sec).
Definition NodeData.hpp:408
std::vector< int > degree
legacy Node.degree: the OUTFLOW-link count (toposort_sortLinks, a reversed conduit counted from its o...
Definition NodeData.hpp:532
std::vector< uint8_t > is_inlet
Inlet-junction flag (0 = plain node, 1 = inlet junction).
Definition NodeData.hpp:186
std::vector< double > lid_drain_qual_vol
LID drain volume inflow rate per node (ft3/sec).
Definition NodeData.hpp:438
std::vector< double > runoff_inflow
Interpolated surface runoff from subcatchments (project flow units).
Definition NodeData.hpp:259
std::vector< double > rim_depth
Rendering-only rim (ground) depth above the invert, project length units. 0 = unset.
Definition NodeData.hpp:202
std::vector< double > dwf_inflow
Dry weather flow inflows (project flow units).
Definition NodeData.hpp:268
std::vector< double > stat_time_flooded
Total duration the node was flooded (seconds).
Definition NodeData.hpp:629
std::vector< std::string > tags
Per-object tag from the INP [TAGS] section.
Definition NodeData.hpp:605
std::vector< double > lid_drain_qual_load
LID drain quality mass rate per (node, pollutant) (mass/sec).
Definition NodeData.hpp:430
std::vector< double > stat_sum_volume
Definition NodeData.hpp:655
std::vector< double > stat_sum_depth
Definition NodeData.hpp:648
std::vector< double > stat_max_rpt_depth
Definition NodeData.hpp:666
std::vector< double > init_depth
Initial water depth (project length units).
Definition NodeData.hpp:150
std::vector< double > stat_total_load
Cumulative pollutant loads at each node.
Definition NodeData.hpp:746
void resize(int n)
Replace the base node store with a requested row count.
Definition NodeData.hpp:768
void save_lat_qual_state() noexcept
Snapshot lateral inflow and pollutant concentrations every routing step.
Definition NodeData.hpp:1351
std::vector< double > coupling_qual_inflow
S3 — this step's delivered 2D→1D species mass RATE per (node, pollutant) (mass/sec); read by QualityS...
Definition NodeData.hpp:355
std::vector< int > stat_non_converged_count
Count of non-converging steps per node.
Definition NodeData.hpp:729
std::vector< double > full_volume
Full volume at node (project volume units).
Definition NodeData.hpp:544
std::vector< double > stat_max_overflow_date
Date/time when maximum overflow occurred (OADate (days since 12/30/1899)).
Definition NodeData.hpp:644
std::vector< std::string > comments
Object comment from the INP file (lines with a single ';' prefix immediately above this object's data...
Definition NodeData.hpp:592
std::vector< double > losses
Node losses (evaporation + seepage) (project flow units).
Definition NodeData.hpp:514
std::vector< double > lid_drain_inflow
LID drain WATER inflow rate per node (ft3/sec) — the routing twin of lid_drain_qual_vol.
Definition NodeData.hpp:459
void grow_to(int n)
Extend base node columns while preserving existing prefixes.
Definition NodeData.hpp:867
std::vector< NodeType > type
Node type for each node.
Definition NodeData.hpp:132
std::vector< double > full_depth
Full depth of the node (project length units).
Definition NodeData.hpp:144
std::vector< double > stat_max_total_inflow
Definition NodeData.hpp:692
std::vector< double > rdii_inflow
RDII unit hydrograph inflows (project flow units).
Definition NodeData.hpp:271
void resize_quality(int n_pollutants)
Set the pollutant stride and replace positive-sized quality arrays.
Definition NodeData.hpp:1211
std::vector< double > head
Current water surface head (project length units = invert + depth).
Definition NodeData.hpp:229
std::vector< double > gw_inflow
Interpolated groundwater flow from subcatchments (project flow units).
Definition NodeData.hpp:262
std::vector< double > user_lat_flow
User-forced lateral inflow set via the API (project flow units).
Definition NodeData.hpp:250
int stat_n_pollutants
Definition NodeData.hpp:747