diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/iterative_linear_se_solver.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/iterative_linear_se_solver.hpp index b053ac4c5..7ab95e281 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/iterative_linear_se_solver.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/iterative_linear_se_solver.hpp @@ -348,7 +348,8 @@ template class IterativeLinearSESolver { // of the measured bus side. NOTE: not the bus that is currently being processed! auto measured_current = static_cast>(m.measurement); if (m.angle_measurement_type == AngleMeasurementType::local_angle) { - measured_current.value *= phase_shift(u[measured_bus]); // offset with the phase shift + measured_current.value = conj(measured_current.value) * + phase_shift(u[measured_bus]); // offset with the phase shift } add_branch_measurement(measured_side, measured_current); } diff --git a/tests/cpp_unit_tests/test_math_solver_se.hpp b/tests/cpp_unit_tests/test_math_solver_se.hpp index b891c798b..9e232fbe9 100644 --- a/tests/cpp_unit_tests/test_math_solver_se.hpp +++ b/tests/cpp_unit_tests/test_math_solver_se.hpp @@ -367,28 +367,55 @@ TEST_CASE_TEMPLATE_DEFINE("Test math solver - SE, measurements", SolverType, tes SolverType solver{y_bus_sym, topo_ptr}; SUBCASE("Local angle current sensor") { - se_input.measured_source_power = {{.real_component = {.value = 1.93, .variance = 0.05}, - .imag_component = {.value = 0.0, .variance = 0.05}}}; - se_input.measured_branch_from_current = { - {.angle_measurement_type = AngleMeasurementType::local_angle, - .measurement = {.real_component = {.value = 1.97, .variance = 0.05}, - .imag_component = {.value = 0.0, .variance = 0.05}}}}; - - output = run_state_estimation(solver, y_bus_sym, se_input, error_tolerance, num_iter, info); - - if (SolverType::has_current_sensor_implemented) { // TODO(mgovers): for testing purposes; remove if - // statement after NRSE has current sensor implemented - CHECK(real(output.bus_injection[0]) == doctest::Approx(1.95)); - CHECK(real(output.source[0].s) == doctest::Approx(1.95)); - CHECK(real(output.branch[0].s_f) == doctest::Approx(1.95)); - CHECK(real(output.branch[0].i_f) == doctest::Approx(real(1.95 * global_shift))); - CHECK(imag(output.branch[0].i_f) == doctest::Approx(imag(1.95 * global_shift))); - } else { - CHECK_FALSE(real(output.bus_injection[0]) == doctest::Approx(1.95)); - CHECK_FALSE(real(output.source[0].s) == doctest::Approx(1.95)); - CHECK_FALSE(real(output.branch[0].s_f) == doctest::Approx(1.95)); - CHECK_FALSE(real(output.branch[0].i_f) == doctest::Approx(real(1.95 * global_shift))); - CHECK_FALSE(imag(output.branch[0].i_f) == doctest::Approx(imag(1.95 * global_shift))); + SUBCASE("No phase shift") { + se_input.measured_source_power = {{.real_component = {.value = 1.93, .variance = 0.05}, + .imag_component = {.value = 0.0, .variance = 0.05}}}; + se_input.measured_branch_from_current = { + {.angle_measurement_type = AngleMeasurementType::local_angle, + .measurement = {.real_component = {.value = 1.97, .variance = 0.05}, + .imag_component = {.value = 0.0, .variance = 0.05}}}}; + + output = run_state_estimation(solver, y_bus_sym, se_input, error_tolerance, num_iter, info); + + if (SolverType::has_current_sensor_implemented) { // TODO(mgovers): for testing purposes; remove if + // statement after NRSE has current sensor implemented + CHECK(real(output.bus_injection[0]) == doctest::Approx(1.95)); + CHECK(real(output.source[0].s) == doctest::Approx(1.95)); + CHECK(real(output.branch[0].s_f) == doctest::Approx(1.95)); + CHECK(real(output.branch[0].i_f) == doctest::Approx(real(1.95 * global_shift))); + CHECK(imag(output.branch[0].i_f) == doctest::Approx(imag(1.95 * global_shift))); + } else { + CHECK_FALSE(real(output.bus_injection[0]) == doctest::Approx(1.95)); + CHECK_FALSE(real(output.source[0].s) == doctest::Approx(1.95)); + CHECK_FALSE(real(output.branch[0].s_f) == doctest::Approx(1.95)); + CHECK_FALSE(real(output.branch[0].i_f) == doctest::Approx(real(1.95 * global_shift))); + CHECK_FALSE(imag(output.branch[0].i_f) == doctest::Approx(imag(1.95 * global_shift))); + } + } + SUBCASE("With phase shift") { + se_input.measured_source_power = {{.real_component = {.value = 0.0, .variance = 0.05}, + .imag_component = {.value = 1.93, .variance = 0.05}}}; + se_input.measured_branch_from_current = { + {.angle_measurement_type = AngleMeasurementType::local_angle, + .measurement = {.real_component = {.value = 0.0, .variance = 0.05}, + .imag_component = {.value = 1.97, .variance = 0.05}}}}; + + output = run_state_estimation(solver, y_bus_sym, se_input, error_tolerance, num_iter, info); + + if (SolverType::has_current_sensor_implemented) { // TODO(mgovers): for testing purposes; remove if + // statement after NRSE has current sensor implemented + CHECK(imag(output.bus_injection[0]) == doctest::Approx(1.95)); + CHECK(imag(output.source[0].s) == doctest::Approx(1.95)); + CHECK(imag(output.branch[0].s_f) == doctest::Approx(1.95)); + CHECK(real(output.branch[0].i_f) == doctest::Approx(real(1.95 * global_shift))); + CHECK(imag(output.branch[0].i_f) == doctest::Approx(-imag(1.95 * global_shift))); + } else { + CHECK_FALSE(imag(output.bus_injection[0]) == doctest::Approx(1.95)); + CHECK_FALSE(imag(output.source[0].s) == doctest::Approx(1.95)); + CHECK_FALSE(imag(output.branch[0].s_f) == doctest::Approx(1.95)); + CHECK_FALSE(real(output.branch[0].i_f) == doctest::Approx(real(1.95 * global_shift))); + CHECK_FALSE(imag(output.branch[0].i_f) == doctest::Approx(-imag(1.95 * global_shift))); + } } } SUBCASE("Global angle current sensor") {