66
77#pragma once
88
9+ #include < array>
910#include < cstddef>
1011#include < memory>
1112#include < vector>
1213
14+ #include < GridKit/Definitions.hpp>
1315#include < GridKit/Model/PhasorDynamics/Component.hpp>
1416#include < GridKit/Model/PhasorDynamics/ComponentSignals.hpp>
1517#include < GridKit/Model/VariableMonitor.hpp>
@@ -36,34 +38,176 @@ namespace GridKit
3638 {
3739 namespace Stabilizer
3840 {
39- // / Internal variables of a `Ieeest`
40- enum class IeeestInternalVariables : size_t
41+ /* *
42+ * @brief Combined denominator coefficients of the IEEEST notch filter.
43+ *
44+ * The two second-order denominator factors expand into a single quartic
45+ * with coefficients a1..a4.
46+ */
47+ template <typename real_type>
48+ inline std::array<real_type, 4 > notchCoefficients (real_type A1 ,
49+ real_type A2 ,
50+ real_type A3 ,
51+ real_type A4 )
4152 {
42- X1 , // /< Notch filter state 1
43- X2 , // /< Notch filter state 2
44- X3 , // /< Notch filter state 3
45- X4 , // /< Notch filter state 4
46- X5 , // /< Lead-lag 1 state
47- X6 , // /< Lead-lag 2 state
48- X7 , // /< Washout state
49- V4 , // /< Notch filter output
50- V5 , // /< Lead-lag 1 output
51- V6 , // /< Lead-lag 2 output
52- V7 , // /< Unlimited stabilizer signal
53- VSS , // /< Limited stabilizer signal (model output)
54- MAXIMUM ,
53+ return {A1 + A3 ,
54+ A2 + A4 + A1 * A3 ,
55+ A1 * A4 + A2 * A3 ,
56+ A2 * A4 };
57+ }
58+
59+ /* *
60+ * @brief Notch-filter order implied by the combined denominator
61+ * coefficients.
62+ *
63+ * Structural coefficients are exact data-file literals, so the
64+ * comparisons against zero are intentionally exact.
65+ */
66+ template <typename real_type>
67+ inline size_t notchOrder (real_type a1, real_type a2, real_type a3, real_type a4)
68+ {
69+ size_t order = 0 ;
70+
71+ if (a1 != ZERO <real_type>)
72+ {
73+ order = 1 ;
74+ }
75+ if (a2 != ZERO <real_type>)
76+ {
77+ order = 2 ;
78+ }
79+ if (a3 != ZERO <real_type>)
80+ {
81+ order = 3 ;
82+ }
83+ if (a4 != ZERO <real_type>)
84+ {
85+ order = 4 ;
86+ }
87+
88+ return order;
89+ }
90+
91+ // / Internal variable layout of a `Ieeest` by notch-filter order
92+ template <size_t order>
93+ struct IeeestVariables ;
94+
95+ template <>
96+ struct IeeestVariables <0 >
97+ {
98+ // / Internal variables of a zeroth-order `Ieeest`
99+ enum class InternalVariables : size_t
100+ {
101+ X5 , // /< Lead-lag 1 state
102+ X6 , // /< Lead-lag 2 state
103+ X7 , // /< Washout state
104+ V4 , // /< Notch filter output
105+ V5 , // /< Lead-lag 1 output
106+ V6 , // /< Lead-lag 2 output
107+ V7 , // /< Unlimited stabilizer signal
108+ VSS , // /< Limited stabilizer signal (model output)
109+ MAXIMUM ,
110+ };
111+ };
112+
113+ template <>
114+ struct IeeestVariables <1 >
115+ {
116+ // / Internal variables of a first-order `Ieeest`
117+ enum class InternalVariables : size_t
118+ {
119+ X1 , // /< Notch filter state 1
120+ X5 , // /< Lead-lag 1 state
121+ X6 , // /< Lead-lag 2 state
122+ X7 , // /< Washout state
123+ V4 , // /< Notch filter output
124+ V5 , // /< Lead-lag 1 output
125+ V6 , // /< Lead-lag 2 output
126+ V7 , // /< Unlimited stabilizer signal
127+ VSS , // /< Limited stabilizer signal (model output)
128+ MAXIMUM ,
129+ };
130+ };
131+
132+ template <>
133+ struct IeeestVariables <2 >
134+ {
135+ // / Internal variables of a second-order `Ieeest`
136+ enum class InternalVariables : size_t
137+ {
138+ X1 , // /< Notch filter state 1
139+ X2 , // /< Notch filter state 2
140+ X5 , // /< Lead-lag 1 state
141+ X6 , // /< Lead-lag 2 state
142+ X7 , // /< Washout state
143+ V4 , // /< Notch filter output
144+ V5 , // /< Lead-lag 1 output
145+ V6 , // /< Lead-lag 2 output
146+ V7 , // /< Unlimited stabilizer signal
147+ VSS , // /< Limited stabilizer signal (model output)
148+ MAXIMUM ,
149+ };
150+ };
151+
152+ template <>
153+ struct IeeestVariables <3 >
154+ {
155+ // / Internal variables of a third-order `Ieeest`
156+ enum class InternalVariables : size_t
157+ {
158+ X1 , // /< Notch filter state 1
159+ X2 , // /< Notch filter state 2
160+ X3 , // /< Notch filter state 3
161+ X5 , // /< Lead-lag 1 state
162+ X6 , // /< Lead-lag 2 state
163+ X7 , // /< Washout state
164+ V4 , // /< Notch filter output
165+ V5 , // /< Lead-lag 1 output
166+ V6 , // /< Lead-lag 2 output
167+ V7 , // /< Unlimited stabilizer signal
168+ VSS , // /< Limited stabilizer signal (model output)
169+ MAXIMUM ,
170+ };
55171 };
56172
173+ template <>
174+ struct IeeestVariables <4 >
175+ {
176+ // / Internal variables of a fourth-order `Ieeest`
177+ enum class InternalVariables : size_t
178+ {
179+ X1 , // /< Notch filter state 1
180+ X2 , // /< Notch filter state 2
181+ X3 , // /< Notch filter state 3
182+ X4 , // /< Notch filter state 4
183+ X5 , // /< Lead-lag 1 state
184+ X6 , // /< Lead-lag 2 state
185+ X7 , // /< Washout state
186+ V4 , // /< Notch filter output
187+ V5 , // /< Lead-lag 1 output
188+ V6 , // /< Lead-lag 2 output
189+ V7 , // /< Unlimited stabilizer signal
190+ VSS , // /< Limited stabilizer signal (model output)
191+ MAXIMUM ,
192+ };
193+ };
194+
195+ // / Internal variables of a `Ieeest` of the given notch-filter order
196+ template <size_t order>
197+ using IeeestInternalVariables = typename IeeestVariables<order>::InternalVariables;
198+
57199 // / External variables of a `Ieeest`
58200 enum class IeeestExternalVariables : size_t
59201 {
60202 U, // /< Stabilizer input signal
61203 MAXIMUM ,
62204 };
63205
64- template <typename scalar_type, typename index_type>
206+ template <typename scalar_type, typename index_type, size_t order >
65207 class Ieeest : public Component <scalar_type, index_type>
66208 {
209+ static_assert (order <= 4 , " Ieeest notch filter order must be in [0, 4]" );
210+
67211 using Component<scalar_type, index_type>::gridkit_component_id_;
68212 using Component<scalar_type, index_type>::alpha_;
69213 using Component<scalar_type, index_type>::f_;
@@ -75,7 +219,6 @@ namespace GridKit
75219 using Component<scalar_type, index_type>::y_;
76220 using Component<scalar_type, index_type>::yp_;
77221 using Component<scalar_type, index_type>::wb_;
78- using Component<scalar_type, index_type>::h_;
79222 using Component<scalar_type, index_type>::J_rows_buffer_;
80223 using Component<scalar_type, index_type>::J_cols_buffer_;
81224 using Component<scalar_type, index_type>::J_vals_buffer_;
@@ -107,7 +250,7 @@ namespace GridKit
107250 auto getSignals ()
108251 -> ComponentSignals<ScalarT,
109252 IdxT,
110- IeeestInternalVariables,
253+ IeeestInternalVariables<order> ,
111254 IeeestExternalVariables>&
112255 {
113256 return signals_;
@@ -149,20 +292,9 @@ namespace GridKit
149292 RealT a3_{0 };
150293 RealT a4_{0 };
151294
152- IdxT order_{0 };
153- RealT s0_{1 };
154- RealT s1_{0 };
155- RealT s2_{0 };
156- RealT s3_{0 };
157- RealT s4_{0 };
158- RealT a1_inv_{0 };
159- RealT a2_inv_{0 };
160- RealT a3_inv_{0 };
161- RealT a4_inv_{0 };
162-
163295 IdxT parameter_error_count_{0 };
164296
165- ComponentSignals<ScalarT, IdxT, IeeestInternalVariables, IeeestExternalVariables> signals_;
297+ ComponentSignals<ScalarT, IdxT, IeeestInternalVariables<order> , IeeestExternalVariables> signals_;
166298
167299 std::unique_ptr<MonitorT> monitor_;
168300
0 commit comments