OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
NodeSubtypes.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
53
54#ifndef OPENSWMM_ENGINE_NODE_SUBTYPES_HPP
55#define OPENSWMM_ENGINE_NODE_SUBTYPES_HPP
56
57#include "LidNodeData.hpp"
58#include <algorithm>
59#include <vector>
60#include <cstdint>
61#include <string>
62
63#include "NodeData.hpp"
64
65namespace openswmm {
66
67// ============================================================================
68// StorageData — side-table for STORAGE nodes
69// ============================================================================
70
77 std::vector<LidNodeConfig> lid;
78 std::vector<LidNodeState> lid_state;
80 std::vector<int> node_idx;
81
83 std::vector<int> curve;
85 std::vector<std::string> curve_name;
87 std::vector<StorageShape> shape;
90 std::vector<double> a;
93 std::vector<double> b;
95 std::vector<double> c;
99 std::vector<double> p1;
101 std::vector<double> p2;
103 std::vector<double> p3;
105 std::vector<double> seep_rate;
107 std::vector<double> evap_frac;
109 std::vector<double> evap_loss;
111 std::vector<double> exfil_loss;
116 std::vector<double> exfil_rate;
118 std::vector<double> exfil_suction;
120 std::vector<double> exfil_ksat;
122 std::vector<double> exfil_imd;
123
128 int count() const noexcept { return static_cast<int>(node_idx.size()); }
129
136 void clear() noexcept {
137 node_idx.clear();
138 curve.clear();
139 curve_name.clear();
140 shape.clear();
141 a.clear();
142 b.clear();
143 c.clear();
144 p1.clear();
145 p2.clear();
146 p3.clear();
147 seep_rate.clear();
148 evap_frac.clear();
149 evap_loss.clear();
150 exfil_loss.clear();
151 exfil_rate.clear();
152 exfil_suction.clear();
153 exfil_ksat.clear();
154 exfil_imd.clear();
155 lid.clear();
156 lid_state.clear();
157 }
158
167 void reserve(int n) {
168 const auto un = static_cast<std::size_t>(n);
169 node_idx.reserve(un);
170 curve.reserve(un);
171 curve_name.reserve(un);
172 shape.reserve(un);
173 a.reserve(un);
174 b.reserve(un);
175 c.reserve(un);
176 p1.reserve(un);
177 p2.reserve(un);
178 p3.reserve(un);
179 seep_rate.reserve(un);
180 evap_frac.reserve(un);
181 evap_loss.reserve(un);
182 exfil_loss.reserve(un);
183 exfil_rate.reserve(un);
184 exfil_suction.reserve(un);
185 exfil_ksat.reserve(un);
186 exfil_imd.reserve(un);
187 lid.reserve(un);
188 lid_state.reserve(un);
189 }
190
203 int add_default(int i) {
204 const auto p = static_cast<std::ptrdiff_t>(
205 std::lower_bound(node_idx.begin(), node_idx.end(), i) - node_idx.begin());
206 node_idx.insert(node_idx.begin() + p, i);
207 curve.insert(curve.begin() + p, -1);
208 curve_name.insert(curve_name.begin() + p, std::string{});
209 // FUNCTIONAL is the historical default for a curve-less storage row: it is what
210 // `curve < 0` has always meant, so existing callers see no behaviour change.
211 shape.insert(shape.begin() + p, StorageShape::FUNCTIONAL);
212 a.insert(a.begin() + p, 0.0);
213 b.insert(b.begin() + p, 0.0);
214 c.insert(c.begin() + p, 0.0);
215 p1.insert(p1.begin() + p, 0.0);
216 p2.insert(p2.begin() + p, 0.0);
217 p3.insert(p3.begin() + p, 0.0);
218 seep_rate.insert(seep_rate.begin() + p, 0.0);
219 evap_frac.insert(evap_frac.begin() + p, 0.0);
220 evap_loss.insert(evap_loss.begin() + p, 0.0);
221 exfil_loss.insert(exfil_loss.begin() + p, 0.0);
222 exfil_rate.insert(exfil_rate.begin() + p, 0.0);
223 exfil_suction.insert(exfil_suction.begin() + p, 0.0);
224 exfil_ksat.insert(exfil_ksat.begin() + p, 0.0);
225 exfil_imd.insert(exfil_imd.begin() + p, 0.0);
226 lid.insert(lid.begin() + p, LidNodeConfig{});
227 lid_state.insert(lid_state.begin() + p, LidNodeState{});
228 return static_cast<int>(p);
229 }
230
240 void erase_at(int r) {
241 const auto p = static_cast<std::ptrdiff_t>(r);
242 node_idx.erase(node_idx.begin() + p);
243 curve.erase(curve.begin() + p);
244 curve_name.erase(curve_name.begin() + p);
245 shape.erase(shape.begin() + p);
246 a.erase(a.begin() + p);
247 b.erase(b.begin() + p);
248 c.erase(c.begin() + p);
249 p1.erase(p1.begin() + p);
250 p2.erase(p2.begin() + p);
251 p3.erase(p3.begin() + p);
252 seep_rate.erase(seep_rate.begin() + p);
253 evap_frac.erase(evap_frac.begin() + p);
254 evap_loss.erase(evap_loss.begin() + p);
255 exfil_loss.erase(exfil_loss.begin() + p);
256 exfil_rate.erase(exfil_rate.begin() + p);
257 exfil_suction.erase(exfil_suction.begin() + p);
258 exfil_ksat.erase(exfil_ksat.begin() + p);
259 exfil_imd.erase(exfil_imd.begin() + p);
260 lid.erase(lid.begin() + p);
261 lid_state.erase(lid_state.begin() + p);
262 }
263};
264
265// ============================================================================
266// OutfallData — side-table for OUTFALL nodes
267// ============================================================================
268
275 std::vector<int> node_idx;
276
278 std::vector<OutfallType> bc_type;
282 std::vector<double> param;
285 std::vector<std::string> param_name;
287 std::vector<uint8_t> has_flap_gate;
289 std::vector<int> route_to;
291 std::vector<int> link_idx;
293 std::vector<double> link_offset;
295 std::vector<double> head_2d;
298 std::vector<double> ramp_2d;
299
304 int count() const noexcept { return static_cast<int>(node_idx.size()); }
305
312 void clear() noexcept {
313 node_idx.clear();
314 bc_type.clear();
315 param.clear();
316 param_name.clear();
317 has_flap_gate.clear();
318 route_to.clear();
319 link_idx.clear();
320 link_offset.clear();
321 head_2d.clear();
322 ramp_2d.clear();
323 }
324
333 void reserve(int n) {
334 const auto un = static_cast<std::size_t>(n);
335 node_idx.reserve(un);
336 bc_type.reserve(un);
337 param.reserve(un);
338 param_name.reserve(un);
339 has_flap_gate.reserve(un);
340 route_to.reserve(un);
341 link_idx.reserve(un);
342 link_offset.reserve(un);
343 head_2d.reserve(un);
344 ramp_2d.reserve(un);
345 }
346
359 int add_default(int i) {
360 const auto p = static_cast<std::ptrdiff_t>(
361 std::lower_bound(node_idx.begin(), node_idx.end(), i) - node_idx.begin());
362 node_idx.insert(node_idx.begin() + p, i);
363 bc_type.insert(bc_type.begin() + p, OutfallType::FREE);
364 param.insert(param.begin() + p, 0.0);
365 param_name.insert(param_name.begin() + p, std::string{});
366 has_flap_gate.insert(has_flap_gate.begin() + p, uint8_t{0});
367 route_to.insert(route_to.begin() + p, -1);
368 link_idx.insert(link_idx.begin() + p, -1);
369 link_offset.insert(link_offset.begin() + p, 0.0);
370 head_2d.insert(head_2d.begin() + p, -1.0e30);
371 ramp_2d.insert(ramp_2d.begin() + p, 0.0);
372 return static_cast<int>(p);
373 }
374
384 void erase_at(int r) {
385 const auto p = static_cast<std::ptrdiff_t>(r);
386 node_idx.erase(node_idx.begin() + p);
387 bc_type.erase(bc_type.begin() + p);
388 param.erase(param.begin() + p);
389 param_name.erase(param_name.begin() + p);
390 has_flap_gate.erase(has_flap_gate.begin() + p);
391 route_to.erase(route_to.begin() + p);
392 link_idx.erase(link_idx.begin() + p);
393 link_offset.erase(link_offset.begin() + p);
394 head_2d.erase(head_2d.begin() + p);
395 ramp_2d.erase(ramp_2d.begin() + p);
396 }
397};
398
399// ============================================================================
400// DividerData — side-table for DIVIDER nodes
401// ============================================================================
402
409 std::vector<int> node_idx;
410
412 std::vector<DividerType> method;
414 std::vector<double> cutoff;
416 std::vector<double> cd;
418 std::vector<double> max_depth;
420 std::vector<int> curve;
422 std::vector<int> link;
424 std::vector<std::string> link_name;
426 std::vector<std::string> curve_name;
427
432 int count() const noexcept { return static_cast<int>(node_idx.size()); }
433
440 void clear() noexcept {
441 node_idx.clear();
442 method.clear();
443 cutoff.clear();
444 cd.clear();
445 max_depth.clear();
446 curve.clear();
447 link.clear();
448 link_name.clear();
449 curve_name.clear();
450 }
451
460 void reserve(int n) {
461 const auto un = static_cast<std::size_t>(n);
462 node_idx.reserve(un);
463 method.reserve(un);
464 cutoff.reserve(un);
465 cd.reserve(un);
466 max_depth.reserve(un);
467 curve.reserve(un);
468 link.reserve(un);
469 link_name.reserve(un);
470 curve_name.reserve(un);
471 }
472
485 int add_default(int i) {
486 const auto p = static_cast<std::ptrdiff_t>(
487 std::lower_bound(node_idx.begin(), node_idx.end(), i) - node_idx.begin());
488 node_idx.insert(node_idx.begin() + p, i);
489 method.insert(method.begin() + p, DividerType::CUTOFF);
490 cutoff.insert(cutoff.begin() + p, 0.0);
491 cd.insert(cd.begin() + p, 0.0);
492 max_depth.insert(max_depth.begin() + p, 0.0);
493 curve.insert(curve.begin() + p, -1);
494 link.insert(link.begin() + p, -1);
495 link_name.insert(link_name.begin() + p, std::string{});
496 curve_name.insert(curve_name.begin() + p, std::string{});
497 return static_cast<int>(p);
498 }
499
509 void erase_at(int r) {
510 const auto p = static_cast<std::ptrdiff_t>(r);
511 node_idx.erase(node_idx.begin() + p);
512 method.erase(method.begin() + p);
513 cutoff.erase(cutoff.begin() + p);
514 cd.erase(cd.begin() + p);
515 max_depth.erase(max_depth.begin() + p);
516 curve.erase(curve.begin() + p);
517 link.erase(link.begin() + p);
518 link_name.erase(link_name.begin() + p);
519 curve_name.erase(curve_name.begin() + p);
520 }
521};
522
523// ============================================================================
524// NodeSubtypes — container + reverse map + build/verify
525// ============================================================================
526
539
541 std::vector<int> subtype_row;
542
549 void clear() noexcept {
550 storages.clear();
551 outfalls.clear();
552 dividers.clear();
553 subtype_row.clear();
554 }
555
566 void rebuild_index(int n_nodes) {
567 subtype_row.assign(static_cast<std::size_t>(n_nodes), -1);
568 for (int r = 0; r < storages.count(); ++r)
569 subtype_row[static_cast<std::size_t>(storages.node_idx[static_cast<std::size_t>(r)])] =
570 r;
571 for (int r = 0; r < outfalls.count(); ++r)
572 subtype_row[static_cast<std::size_t>(outfalls.node_idx[static_cast<std::size_t>(r)])] =
573 r;
574 for (int r = 0; r < dividers.count(); ++r)
575 subtype_row[static_cast<std::size_t>(dividers.node_idx[static_cast<std::size_t>(r)])] =
576 r;
577 }
578
594 int set_node_type(NodeData& nodes, int i, NodeType t) {
595 const auto ui = static_cast<std::size_t>(i);
596 if (i >= static_cast<int>(subtype_row.size()))
597 subtype_row.resize(static_cast<std::size_t>(i) + 1, -1);
598
599 // Contexts sized column by column may omit storage_area; unsized means no chamber.
600 if (t != NodeType::JUNCTION && ui < nodes.storage_area.size())
601 nodes.storage_area[ui] = 0.0;
602 const NodeType old = nodes.type[ui];
603 const int existing = subtype_row[ui];
604 if (old == t && existing >= 0)
605 return existing; // already this subtype with a row — idempotent.
606
607 bool shifted = false;
608 if (existing >= 0) { // remove the old subtype row (real re-type/convert).
609 switch (old) {
611 storages.erase_at(existing);
612 break;
614 outfalls.erase_at(existing);
615 break;
617 dividers.erase_at(existing);
618 break;
619 default:
620 break;
621 }
622 shifted = true;
623 }
624
625 nodes.type[ui] = t;
626
627 int row = -1;
628 switch (t) {
630 row = storages.add_default(i);
631 if (row != storages.count() - 1)
632 shifted = true;
633 break;
635 row = outfalls.add_default(i);
636 if (row != outfalls.count() - 1)
637 shifted = true;
638 break;
640 row = dividers.add_default(i);
641 if (row != dividers.count() - 1)
642 shifted = true;
643 break;
645 default:
646 break; // no subtype row
647 }
648
649 if (shifted) {
650 rebuild_index(nodes.count());
651 return (t == NodeType::JUNCTION) ? -1 : subtype_row[ui];
652 }
653 subtype_row[ui] = row; // O(1) ascending-parse / end-insert path
654 return row;
655 }
656
667 void erase_node(int i, int n_after) {
668 // Erase the row whose node_idx == i (in whichever table holds it).
669 auto drop = [i](auto& tbl) -> bool {
670 for (int r = 0; r < tbl.count(); ++r)
671 if (tbl.node_idx[static_cast<std::size_t>(r)] == i) {
672 tbl.erase_at(r);
673 return true;
674 }
675 return false;
676 };
677 drop(storages) || drop(outfalls) || drop(dividers);
678
679 auto shift = [i](std::vector<int>& keys) {
680 for (auto& k : keys)
681 if (k > i)
682 --k;
683 };
684 shift(storages.node_idx);
685 shift(outfalls.node_idx);
686 shift(dividers.node_idx);
687
688 rebuild_index(n_after);
689 }
690
701 int storage_row(int i) const noexcept {
702 if (i >= 0 && i < static_cast<int>(subtype_row.size())) {
703 const int r = subtype_row[static_cast<std::size_t>(i)];
704 if (r >= 0 && r < storages.count() &&
705 storages.node_idx[static_cast<std::size_t>(r)] == i)
706 return r;
707 }
708 return -1;
709 }
710
721 int outfall_row(int i) const noexcept {
722 if (i >= 0 && i < static_cast<int>(subtype_row.size())) {
723 const int r = subtype_row[static_cast<std::size_t>(i)];
724 if (r >= 0 && r < outfalls.count() &&
725 outfalls.node_idx[static_cast<std::size_t>(r)] == i)
726 return r;
727 }
728 return -1;
729 }
730
741 int divider_row(int i) const noexcept {
742 if (i >= 0 && i < static_cast<int>(subtype_row.size())) {
743 const int r = subtype_row[static_cast<std::size_t>(i)];
744 if (r >= 0 && r < dividers.count() &&
745 dividers.node_idx[static_cast<std::size_t>(r)] == i)
746 return r;
747 }
748 return -1;
749 }
750};
751
752} // namespace openswmm
753
754#endif // OPENSWMM_ENGINE_NODE_SUBTYPES_HPP
Data-oriented storage for LID node layers, properties, and state.
Structure-of-Arrays (SoA) storage for all node types.
Definition ExchangeLaw.hpp:60
@ FUNCTIONAL
Area = c + a*d^b.
Definition NodeData.hpp:101
@ FREE
Definition NodeData.hpp:71
NodeType
Node type codes.
Definition NodeData.hpp:65
@ JUNCTION
Definition NodeData.hpp:65
@ DIVIDER
Definition NodeData.hpp:65
@ STORAGE
Definition NodeData.hpp:65
@ OUTFALL
Definition NodeData.hpp:65
@ CUTOFF
Definition NodeData.hpp:78
Dense SoA for flow-divider properties (one row per DIVIDER node).
Definition NodeSubtypes.hpp:407
std::vector< double > cd
Weir discharge coefficient for WEIR dividers.
Definition NodeSubtypes.hpp:416
std::vector< std::string > link_name
Diversion link name (deferred resolution).
Definition NodeSubtypes.hpp:424
std::vector< int > curve
Diversion curve index for TABULAR dividers (-1 = none).
Definition NodeSubtypes.hpp:420
std::vector< double > cutoff
Cutoff flow for CUTOFF dividers.
Definition NodeSubtypes.hpp:414
void clear() noexcept
Erase all DividerData rows while retaining vector capacities.
Definition NodeSubtypes.hpp:440
std::vector< DividerType > method
Diversion method (CUTOFF/OVERFLOW/TABULAR/WEIR).
Definition NodeSubtypes.hpp:412
int count() const noexcept
Count DividerData rows from the base-object join-key column.
Definition NodeSubtypes.hpp:432
int add_default(int i)
Insert a default DividerData row at the sorted base-object key position.
Definition NodeSubtypes.hpp:485
std::vector< double > max_depth
Weir max depth for WEIR dividers.
Definition NodeSubtypes.hpp:418
void reserve(int n)
Request capacity for each DividerData column without changing row count.
Definition NodeSubtypes.hpp:460
std::vector< int > link
Diversion link index (-1 = not set).
Definition NodeSubtypes.hpp:422
std::vector< std::string > curve_name
Diversion curve name (deferred resolution, TABULAR only).
Definition NodeSubtypes.hpp:426
void erase_at(int r)
Erase dense DividerData row data and shift later dense rows down.
Definition NodeSubtypes.hpp:509
std::vector< int > node_idx
Base NodeData index this row belongs to (the join key).
Definition NodeSubtypes.hpp:409
Definition LidNodeData.hpp:91
Definition LidNodeData.hpp:54
Structure-of-Arrays storage for all nodes.
Definition NodeData.hpp:125
int count() const noexcept
Number of nodes.
Definition NodeData.hpp:754
std::vector< double > storage_area
Physical junction area (ft2); zero retains legacy behavior.
Definition NodeData.hpp:163
std::vector< NodeType > type
Node type for each node.
Definition NodeData.hpp:132
Owns the three node subtype side-tables plus the reverse index map.
Definition NodeSubtypes.hpp:535
int divider_row(int i) const noexcept
Resolve a base node key into the divider side table.
Definition NodeSubtypes.hpp:741
DividerData dividers
Definition NodeSubtypes.hpp:538
int storage_row(int i) const noexcept
Resolve a base node key into the storage side table.
Definition NodeSubtypes.hpp:701
int set_node_type(NodeData &nodes, int i, NodeType t)
Change one base node type and maintain its dense side-table row.
Definition NodeSubtypes.hpp:594
void erase_node(int i, int n_after)
Drop a deleted base node's subtype row and renumber later join keys.
Definition NodeSubtypes.hpp:667
void rebuild_index(int n_nodes)
Rebuild base node indices to dense subtype-row lookup.
Definition NodeSubtypes.hpp:566
void clear() noexcept
Erase all owned node subtype tables and reverse-map entries.
Definition NodeSubtypes.hpp:549
OutfallData outfalls
Definition NodeSubtypes.hpp:537
std::vector< int > subtype_row
base node index → row in its subtype table (-1 for junctions).
Definition NodeSubtypes.hpp:541
int outfall_row(int i) const noexcept
Resolve a base node key into the outfall side table.
Definition NodeSubtypes.hpp:721
StorageData storages
Definition NodeSubtypes.hpp:536
Dense SoA for outfall boundary-condition properties (one row per OUTFALL).
Definition NodeSubtypes.hpp:273
std::vector< OutfallType > bc_type
Boundary condition type (FREE/NORMAL/FIXED/TIDAL/TIMESERIES).
Definition NodeSubtypes.hpp:278
void erase_at(int r)
Erase dense OutfallData row data and shift later dense rows down.
Definition NodeSubtypes.hpp:384
std::vector< int > link_idx
Cached connected-conduit index (-1 = none).
Definition NodeSubtypes.hpp:291
std::vector< uint8_t > has_flap_gate
Flap gate present (0/1).
Definition NodeSubtypes.hpp:287
void reserve(int n)
Request capacity for each OutfallData column without changing row count.
Definition NodeSubtypes.hpp:333
std::vector< int > route_to
Subcatchment index to route discharge to (-1 = none).
Definition NodeSubtypes.hpp:289
int count() const noexcept
Count OutfallData rows from the base-object join-key column.
Definition NodeSubtypes.hpp:304
void clear() noexcept
Erase all OutfallData rows while retaining vector capacities.
Definition NodeSubtypes.hpp:312
std::vector< std::string > param_name
Stage-data table name for TIDAL/TIMESERIES, held for deferred name→index resolution in PostParseResol...
Definition NodeSubtypes.hpp:285
std::vector< double > ramp_2d
Cached wet/dry ramp factor [0,1] for the 2D tailwater override (0 = dry → free discharge,...
Definition NodeSubtypes.hpp:298
int add_default(int i)
Insert a default OutfallData row at the sorted base-object key position.
Definition NodeSubtypes.hpp:359
std::vector< double > param
Fixed stage, or tidal/timeseries table index (per bc_type). For TIDAL/TIMESERIES an unresolved refere...
Definition NodeSubtypes.hpp:282
std::vector< double > head_2d
Cached 2D surface head at the coupling point (sentinel -1e30).
Definition NodeSubtypes.hpp:295
std::vector< double > link_offset
Conduit offset at the outfall end.
Definition NodeSubtypes.hpp:293
std::vector< int > node_idx
Base NodeData index this row belongs to (the join key).
Definition NodeSubtypes.hpp:275
Dense SoA for storage-unit properties (one row per STORAGE node).
Definition NodeSubtypes.hpp:76
void clear() noexcept
Erase all StorageData rows while retaining vector capacities.
Definition NodeSubtypes.hpp:136
int add_default(int i)
Insert a default StorageData row at the sorted base-object key position.
Definition NodeSubtypes.hpp:203
int count() const noexcept
Count StorageData rows from the base-object join-key column.
Definition NodeSubtypes.hpp:128
std::vector< double > exfil_rate
Raw (uncapped) exfiltration rate this timestep (cfs), written by ExfilSolver::computeAll and consumed...
Definition NodeSubtypes.hpp:116
void reserve(int n)
Request capacity for each StorageData column without changing row count.
Definition NodeSubtypes.hpp:167
std::vector< double > exfil_imd
Green-Ampt initial moisture deficit for exfiltration (0-1).
Definition NodeSubtypes.hpp:122
std::vector< double > evap_frac
Fraction of potential evaporation realized (0-1).
Definition NodeSubtypes.hpp:107
std::vector< double > exfil_suction
Green-Ampt suction head for exfiltration.
Definition NodeSubtypes.hpp:118
std::vector< double > a
Area coefficient A (legacy a1). FUNCTIONAL: A·d^B; geometric shapes: the linear term of C + A·d + B·d...
Definition NodeSubtypes.hpp:90
std::vector< double > p3
Raw shape parameter 3 — side slope Z (run/rise), or height for PARABOLOID.
Definition NodeSubtypes.hpp:103
std::vector< double > b
Area coefficient B (legacy a2). FUNCTIONAL: the exponent; geometric shapes: the quadratic term.
Definition NodeSubtypes.hpp:93
std::vector< double > seep_rate
Seepage rate (project units/day).
Definition NodeSubtypes.hpp:105
std::vector< LidNodeState > lid_state
Definition NodeSubtypes.hpp:78
std::vector< int > node_idx
Base NodeData index this row belongs to (the join key).
Definition NodeSubtypes.hpp:80
std::vector< int > curve
Storage curve index into TableData (-1 = not tabulated).
Definition NodeSubtypes.hpp:83
std::vector< double > p2
Raw shape parameter 2 — minor axis / base width W.
Definition NodeSubtypes.hpp:101
std::vector< double > exfil_ksat
Green-Ampt saturated conductivity for exfiltration.
Definition NodeSubtypes.hpp:120
std::vector< double > c
Area coefficient C (legacy a0). Baseline area at zero depth.
Definition NodeSubtypes.hpp:95
std::vector< LidNodeConfig > lid
Definition NodeSubtypes.hpp:77
std::vector< std::string > curve_name
Curve name for deferred resolution.
Definition NodeSubtypes.hpp:85
std::vector< double > evap_loss
Evaporation loss this timestep (ft3).
Definition NodeSubtypes.hpp:109
std::vector< double > p1
Raw shape parameter 1 — major axis / base length L (geometric shapes only). Kept alongside the derive...
Definition NodeSubtypes.hpp:99
std::vector< double > exfil_loss
Exfiltration loss this timestep (ft3).
Definition NodeSubtypes.hpp:111
std::vector< StorageShape > shape
Surface-area relation. Selects how a/b/c below are interpreted.
Definition NodeSubtypes.hpp:87
void erase_at(int r)
Erase dense StorageData row data and shift later dense rows down.
Definition NodeSubtypes.hpp:240