Skip to content

Commit ab9cff1

Browse files
committed
move logic to common phase_mod_2pi functionality
Signed-off-by: Martijn Govers <Martijn.Govers@Alliander.com>
1 parent 6ae6f6d commit ab9cff1

File tree

4 files changed

+43
-5
lines changed

4 files changed

+43
-5
lines changed

power_grid_model_c/power_grid_model/include/power_grid_model/common/three_phase_tensor.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,14 @@ inline ComplexValue<asymmetric_t> phase_shift(ComplexValue<asymmetric_t> const&
176176
return {phase_shift(m(0)), phase_shift(m(1)), phase_shift(m(2))};
177177
}
178178

179+
// arg(e^(i * phase)) = phase (mod 2pi). By convention restrict to [-pi, pi].
180+
inline auto phase_mod_2pi(double phase) {
181+
return RealValue<symmetric_t>{arg(ComplexValue<symmetric_t>{exp(1.0i * phase)})};
182+
}
183+
inline auto phase_mod_2pi(RealValue<asymmetric_t> const& phase) {
184+
return RealValue<asymmetric_t>{arg(ComplexValue<asymmetric_t>{exp(1.0i * phase)})};
185+
}
186+
179187
// calculate kron product of two vector
180188
inline double vector_outer_product(double x, double y) { return x * y; }
181189
inline DoubleComplex vector_outer_product(DoubleComplex x, DoubleComplex y) { return x * y; }

power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,7 @@ template <symmetry_tag current_sensor_symmetry_> class CurrentSensor : public Ge
174174
}
175175
}();
176176
output.i_residual = (cabs(i_measured_complex) - cabs(i_output)) * base_current_;
177-
// arg(e^i * u_angle) = u_angle in (-pi, pi]
178-
auto const unbounded_i_angle_residual = arg(i_measured_complex) - arg(i_output);
179-
output.i_angle_residual = arg(ComplexValue<sym_calc>{exp(1.0i * unbounded_i_angle_residual)});
177+
output.i_angle_residual = phase_mod_2pi(arg(i_measured_complex) - arg(i_output));
180178
return output;
181179
}
182180
};

power_grid_model_c/power_grid_model/include/power_grid_model/component/voltage_sensor.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ template <symmetry_tag sym> class VoltageSensor : public GenericVoltageSensor {
151151
} else {
152152
value.u_residual = (real(u1_measured) - cabs(u)) * u_rated_;
153153
}
154-
value.u_angle_residual = arg(ComplexValue<symmetric_t>{exp(1.0i * (arg(u1_measured) - arg(u)))});
154+
value.u_angle_residual = phase_mod_2pi(arg(u1_measured) - arg(u));
155155
return value;
156156
}
157157

@@ -160,7 +160,7 @@ template <symmetry_tag sym> class VoltageSensor : public GenericVoltageSensor {
160160
value.id = id();
161161
value.energized = 1;
162162
value.u_residual = (u_measured_ - cabs(u)) * u_rated_ / sqrt3;
163-
value.u_angle_residual = arg(ComplexValue<asymmetric_t>{exp(1.0i * (u_angle_measured_ - arg(u)))});
163+
value.u_angle_residual = phase_mod_2pi(u_angle_measured_ - arg(u));
164164
return value;
165165
}
166166
};

tests/cpp_unit_tests/test_three_phase_tensor.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,38 @@ TEST_CASE("Three phase tensor") {
206206
CHECK(is_nan(vec(1)));
207207
CHECK(vec(2) == 6.0);
208208
}
209+
SUBCASE("phase_mod_2pi") {
210+
auto const check = [](double value) {
211+
CAPTURE(value);
212+
CHECK_GE(value, -pi);
213+
CHECK_LE(value, pi);
214+
if (value != pi && value != -pi) {
215+
CHECK(phase_mod_2pi(value) == doctest::Approx(value));
216+
}
217+
};
218+
auto const check_asym = [&check](RealValue<asymmetric_t> const& value) {
219+
for (Idx i : {0, 1, 2}) {
220+
CAPTURE(i);
221+
check(value(i));
222+
}
223+
};
224+
check(phase_mod_2pi(0.0));
225+
check(phase_mod_2pi(2.0 * pi));
226+
check(phase_mod_2pi(2.0 * pi + 1.0));
227+
check(phase_mod_2pi(-1.0));
228+
check(phase_mod_2pi(-pi));
229+
check(phase_mod_2pi(pi));
230+
check(phase_mod_2pi(-3.0 * pi));
231+
check(phase_mod_2pi(3.0 * pi));
232+
check(phase_mod_2pi(pi * (1.0 + std::numeric_limits<double>::epsilon())));
233+
check(phase_mod_2pi(pi * (1.0 - std::numeric_limits<double>::epsilon())));
234+
check(phase_mod_2pi(-pi * (1.0 + std::numeric_limits<double>::epsilon())));
235+
check(phase_mod_2pi(-pi * (1.0 - std::numeric_limits<double>::epsilon())));
236+
237+
check_asym(phase_mod_2pi(RealValue<asymmetric_t>{0.0, 2.0 * pi, 2.0 * pi + 1.0}));
238+
check_asym(phase_mod_2pi(RealValue<asymmetric_t>{0.0, 2.0 * pi, 2.0 * pi + 1.0}));
239+
check_asym(phase_mod_2pi(RealValue<asymmetric_t>{0.0, 2.0 * pi, 2.0 * pi + 1.0}));
240+
}
209241
}
210242

211243
} // namespace power_grid_model

0 commit comments

Comments
 (0)