OpenSWMM Engine  6.0.0-alpha.1
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.1)
Loading...
Searching...
No Matches
Controls.hpp
Go to the documentation of this file.
1
21#ifndef OPENSWMM_CONTROLS_HPP
22#define OPENSWMM_CONTROLS_HPP
23
24#include <vector>
25#include <string>
26#include <unordered_map>
27#include "../math/MathExpr.hpp"
28
29namespace openswmm {
30
31struct SimulationContext;
32
33namespace controls {
34
35// ============================================================================
36// Comparison and logic operators
37// ============================================================================
38
39enum class CompareOp : int { EQ = 0, NE = 1, LT = 2, LE = 3, GT = 4, GE = 5 };
40enum class LogicOp : int { AND = 0, OR = 1 };
41
42// ============================================================================
43// Condition variable types (matching ALL legacy RuleAttrib values)
44// ============================================================================
45
46enum class ConditionVar : int {
47 // Node attributes
48 NODE_DEPTH = 0,
49 NODE_MAXDEPTH = 1,
50 NODE_HEAD = 2,
51 NODE_VOLUME = 3,
52 NODE_INFLOW = 4,
53
54 // Link attributes
55 LINK_FLOW = 10,
56 LINK_DEPTH = 11,
57 LINK_SETTING = 12,
58 LINK_STATUS = 13,
59 LINK_FULLFLOW = 14,
60 LINK_FULLDEPTH = 15,
61 LINK_VELOCITY = 16,
62 LINK_LENGTH = 17,
63 LINK_SLOPE = 18,
64 LINK_TIMEOPEN = 19,
66
67 // Gage attributes
68 GAGE_RAIN = 30,
69 GAGE_RAIN_PAST = 31,
70
71 // System / time
72 SIM_TIME = 40,
73 SIM_DATE = 41,
74 CLOCK_TIME = 42,
75 SIM_DAY = 43,
76 SIM_MONTH = 44,
77 SIM_DAYOFYEAR = 45
78};
79
80// ============================================================================
81// Action attribute (what is being set on the link)
82// ============================================================================
83
84enum class ActionType : int {
85 NUMERIC = 0,
86 CURVE = 1,
87 TIMESERIES = 2,
88 PID = 3
89};
90
91// ============================================================================
92// Rule premise (condition)
93// ============================================================================
94
111
112// ============================================================================
113// Rule action
114// ============================================================================
115
116struct Action {
117 int link_idx = -1;
118 int rule_idx = -1;
120 double value = 0.0;
121 int curve_idx = -1;
122 int tseries_idx = -1;
123};
124
125// ============================================================================
126// PID controller state (per action)
127// ============================================================================
128
129struct PIDState {
130 double kp = 0.0;
131 double ki = 0.0;
132 double kd = 0.0;
133 double setpoint = 0.0;
134 double e1 = 0.0;
135 double e2 = 0.0;
136 int action_idx = -1;
137};
138
139// ============================================================================
140// Named variable (for rule expressions)
141// ============================================================================
142
144 std::string name;
146 int idx = -1;
147};
148
149// ============================================================================
150// Control rule
151// ============================================================================
152
153struct Rule {
154 std::string name;
155 std::vector<Premise> premises;
156 std::vector<Action> then_actions;
157 std::vector<Action> else_actions;
158 double priority = 0.0;
159};
160
161// ============================================================================
162// Control engine
163// ============================================================================
164
166public:
167 void init(const std::vector<Rule>& rules);
168
184 int evaluate(SimulationContext& ctx, double current_time, double dt);
185
186 // Rule parsing (from [CONTROLS] text)
187 int parseRuleText(const std::string& text, SimulationContext& ctx);
188
189 // Named variables
190 void addNamedVariable(const std::string& name, ConditionVar var, int idx);
191
192 // Math expressions
193 int addExpression(const std::string& name, const std::string& formula);
194
195 std::vector<Rule>& rules() { return rules_; }
196
197 // ========================================================================
198 // SoA batch evaluation index (AD-14)
199 // ========================================================================
200
216 struct PremiseSoA {
218 int count = 0;
219
220 // Per-premise SoA (contiguous, aligned for SIMD)
221 std::vector<int> rule_idx;
222 std::vector<int> premise_idx;
223 std::vector<int> obj_idx;
224 std::vector<int> op;
225 std::vector<double> rhs_value;
226
227 // Per-premise flags
228 std::vector<bool> rhs_is_variable;
229 std::vector<bool> is_expression;
230
231 // Working buffer (reused each evaluate call)
232 std::vector<double> lhs_values;
233 std::vector<bool> results;
234 };
235
237 void buildPremiseSoA();
238
240 void batchEvaluateGroup(PremiseSoA& group,
241 const SimulationContext& ctx,
242 double current_time, double half_step);
243
244private:
245 std::vector<Rule> rules_;
246 std::vector<PIDState> pid_states_;
247 std::vector<NamedVariable> named_vars_;
248 std::vector<mathexpr::Expression> expressions_;
249 std::unordered_map<std::string, int> expr_index_;
250
251 // SoA premise groups (one per variable type that has premises)
252 std::vector<PremiseSoA> premise_groups_;
253
254 // Per-rule premise result tracking (for combining AND/OR)
255 std::vector<bool> rule_results_;
256
257 // TIMEOPEN/TIMECLOSED tracking: when each link's setting last changed.
258 // Stored as absolute date (decimal days) matching legacy Link[j].timeLastSet.
259 std::vector<double> link_time_last_set_;
260
261 // Tracked across a single evaluate() call
262 double control_value_ = 0.0;
263 double set_point_ = 0.0;
264
265 // Pending action list (for priority deduplication)
266 struct PendingAction {
267 int link_idx;
268 double value;
269 double priority;
270 int rule_idx;
271 };
272 std::vector<PendingAction> pending_actions_;
273
274 double getVariableValue(const SimulationContext& ctx,
275 ConditionVar var, int idx,
276 double current_time, int param = 0) const;
277
278 bool evaluatePremise(const SimulationContext& ctx,
279 const Premise& p, double current_time, double half_step);
280
281 bool compareValues(double lhs, CompareOp op, double rhs) const;
282 bool compareTimes(double lhs, CompareOp op, double rhs, double half_step) const;
283
284 double computePIDSetting(PIDState& pid, double control_value, double dt);
285
286 void updateActionValue(Action& a, SimulationContext& ctx,
287 double current_time, double dt);
288
290 int applyPendingActions(SimulationContext& ctx, double current_time);
291
293 double getNamedVariableValue(const std::string& name,
294 const SimulationContext& ctx,
295 double current_time) const;
296};
297
298} // namespace controls
299} // namespace openswmm
300
301#endif // OPENSWMM_CONTROLS_HPP
Definition Controls.hpp:165
int parseRuleText(const std::string &text, SimulationContext &ctx)
Definition Controls.cpp:677
std::vector< Rule > & rules()
Definition Controls.hpp:195
void buildPremiseSoA()
Build SoA index from rules. Called once at init().
Definition Controls.cpp:46
int addExpression(const std::string &name, const std::string &formula)
Definition Controls.cpp:513
void init(const std::vector< Rule > &rules)
Definition Controls.cpp:29
int evaluate(SimulationContext &ctx, double current_time, double dt)
Evaluate all control rules and set link target settings.
Definition Controls.cpp:159
void batchEvaluateGroup(PremiseSoA &group, const SimulationContext &ctx, double current_time, double half_step)
Batch evaluate all premises of one variable type.
Definition Controls.cpp:113
void addNamedVariable(const std::string &name, ConditionVar var, int idx)
Definition Controls.cpp:509
ConditionVar
Definition Controls.hpp:46
@ GAGE_RAIN_PAST
Past n-hours rainfall (n stored in idx field)
@ GAGE_RAIN
Current rainfall intensity.
@ SIM_DAYOFYEAR
Day of year (1-365)
@ SIM_DAY
Day of week (1-7, Sun=1)
LogicOp
Definition Controls.hpp:40
CompareOp
Definition Controls.hpp:39
ActionType
Definition Controls.hpp:84
@ CURVE
Setting from curve lookup(ControlValue)
@ PID
PID controller output.
@ TIMESERIES
Setting from timeseries lookup(currentTime)
@ NUMERIC
Direct numeric setting value.
Definition Controls.cpp:24
Central, reentrant simulation context.
Definition SimulationContext.hpp:141
Definition Controls.hpp:116
int rule_idx
Parent rule index (for priority lookup)
Definition Controls.hpp:118
int link_idx
Link being controlled.
Definition Controls.hpp:117
ActionType type
Definition Controls.hpp:119
int curve_idx
Curve index (for CURVE type)
Definition Controls.hpp:121
double value
Direct value or computed result.
Definition Controls.hpp:120
int tseries_idx
Timeseries index (for TIMESERIES type)
Definition Controls.hpp:122
Pre-sorted premise index for batch evaluation.
Definition Controls.hpp:216
ConditionVar var_type
All premises in this group test this variable.
Definition Controls.hpp:217
std::vector< bool > rhs_is_variable
True if RHS is a variable (not batch-able)
Definition Controls.hpp:228
std::vector< int > premise_idx
Position within the rule's premise list.
Definition Controls.hpp:222
std::vector< int > op
CompareOp as int.
Definition Controls.hpp:224
std::vector< bool > results
Comparison results.
Definition Controls.hpp:233
std::vector< bool > is_expression
True if LHS is an expression.
Definition Controls.hpp:229
std::vector< double > rhs_value
RHS threshold value.
Definition Controls.hpp:225
std::vector< double > lhs_values
Gathered LHS values.
Definition Controls.hpp:232
std::vector< int > obj_idx
Object index (node/link/gage)
Definition Controls.hpp:223
std::vector< int > rule_idx
Which rule this premise belongs to.
Definition Controls.hpp:221
int count
Definition Controls.hpp:218
Definition Controls.hpp:143
int idx
Definition Controls.hpp:146
ConditionVar var
Definition Controls.hpp:145
std::string name
Definition Controls.hpp:144
Definition Controls.hpp:129
double kd
Definition Controls.hpp:132
double kp
Definition Controls.hpp:130
double e2
Error two steps back.
Definition Controls.hpp:135
double ki
Integral time (minutes, 0=disable)
Definition Controls.hpp:131
int action_idx
Associated action index.
Definition Controls.hpp:136
double setpoint
Definition Controls.hpp:133
double e1
Previous error.
Definition Controls.hpp:134
Definition Controls.hpp:95
int lhs_param
Extra parameter (e.g. n-hours for GAGE_RAIN_PAST)
Definition Controls.hpp:102
double rhs_value
Definition Controls.hpp:109
ConditionVar lhs_var
Definition Controls.hpp:100
int expr_idx
Index into expressions_ (-1 if N/A)
Definition Controls.hpp:98
int lhs_idx
Object index (node/link/gage)
Definition Controls.hpp:101
bool is_expression
True if LHS is a math expression.
Definition Controls.hpp:97
ConditionVar rhs_var
Definition Controls.hpp:107
int rhs_idx
Definition Controls.hpp:108
bool rhs_is_variable
Definition Controls.hpp:106
LogicOp logic
Definition Controls.hpp:96
CompareOp op
Definition Controls.hpp:104
Definition Controls.hpp:153
std::string name
Definition Controls.hpp:154
double priority
Definition Controls.hpp:158
std::vector< Action > else_actions
Definition Controls.hpp:157
std::vector< Action > then_actions
Definition Controls.hpp:156
std::vector< Premise > premises
Definition Controls.hpp:155