Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix NRSE line measurement implementation #478

Merged
merged 45 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
8d5e631
fix multiplication
nitbharambe Jan 24, 2024
6a2802f
rearrange branch injection
nitbharambe Jan 25, 2024
44d3f15
Merge branch 'feature/NRSE-general-structure' into fix/nrse-line-meas…
nitbharambe Jan 25, 2024
c018a17
refactor big blocks
nitbharambe Jan 25, 2024
1fbec29
fix adding to both
nitbharambe Jan 26, 2024
03d5101
remove commentted code
nitbharambe Jan 26, 2024
4562c35
change condition
nitbharambe Jan 26, 2024
3c62f60
rename to workout
nitbharambe Jan 26, 2024
6ad0718
rename del to delta
nitbharambe Jan 26, 2024
2f49229
pre-merge to comments
nitbharambe Jan 26, 2024
38c1b0f
add docstring
nitbharambe Jan 26, 2024
0d6e780
merge fixes to angle
nitbharambe Jan 29, 2024
cb21b9f
add newton raphson state estimation unit tests to math solver
mgovers Jan 29, 2024
632412a
add shunt tests
nitbharambe Jan 29, 2024
098c961
Merge branch 'feature/NRSE-general-structure' into fix/nrse-line-meas…
nitbharambe Jan 29, 2024
cbcba36
fix injection variance
nitbharambe Jan 29, 2024
6aea7f5
Merge branch 'feature/NRSE-general-structure' into fix/nrse-line-meas…
mgovers Jan 30, 2024
de343e4
minor
mgovers Jan 30, 2024
00d4325
format
mgovers Jan 30, 2024
c6cec66
Merge branch 'feature/NRSE-general-structure' into fix/nrse-line-meas…
mgovers Jan 30, 2024
b54487c
fix branch logic
nitbharambe Jan 30, 2024
5ddaa96
remove rough branch logic
nitbharambe Jan 30, 2024
12cfb32
improve readability
nitbharambe Jan 31, 2024
6d397e1
Merge branch 'fix/nrse-line-measurements' of https://github.com/Power…
nitbharambe Jan 31, 2024
e54b85a
refactor zero voltage angle
nitbharambe Jan 31, 2024
307bf50
fix spell
nitbharambe Jan 31, 2024
fab7277
change injection uj to ui
nitbharambe Jan 31, 2024
a706503
fix zero injection fx addition
nitbharambe Feb 1, 2024
4c471ca
revert line order change
nitbharambe Feb 2, 2024
0027661
correct lagrange multiplier
nitbharambe Feb 4, 2024
061d592
fix tau
nitbharambe Feb 5, 2024
1cac73b
remove unused variable
nitbharambe Feb 5, 2024
5e273ac
fix shunt
nitbharambe Feb 5, 2024
ec04c22
xfail distribution and sensor update
nitbharambe Feb 5, 2024
7b37e15
refactor, fix any zero to all zero
nitbharambe Feb 5, 2024
5247ea4
fix NRSE validation jsons
mgovers Feb 6, 2024
b46998b
fix compiler warning
mgovers Feb 6, 2024
1dcccea
Merge branch 'feature/NRSE-general-structure' into fix/nrse-line-meas…
mgovers Feb 6, 2024
84b3e65
Merge branch 'fix/nrse-line-measurements' of https://github.com/Power…
mgovers Feb 6, 2024
9940af1
minor resolve comments
mgovers Feb 6, 2024
bada724
refactor iteration logic
mgovers Feb 6, 2024
451a420
refactor
mgovers Feb 6, 2024
be53049
replace inline comments by multiline docstrings
mgovers Feb 6, 2024
f7e2cf0
fix bug in measured values
mgovers Feb 6, 2024
cdcd535
fix clang tidy
mgovers Feb 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ template <bool sym> class MeasuredValues {

// assign a meaningful mean angle shift, if at least one voltage has angle measurement
if (has_angle()) {
mean_angle_shift_ = angle_cum / n_voltage_angle_measurements_;
mean_angle_shift_ = angle_cum / static_cast<RealValue<sym>>(n_voltage_angle_measurements_);
}

static constexpr auto const is_measured = [](auto const& value) { return value >= 0; };
Expand Down
mgovers marked this conversation as resolved.
Show resolved Hide resolved
mgovers marked this conversation as resolved.
Show resolved Hide resolved
mgovers marked this conversation as resolved.
Show resolved Hide resolved

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ template <scalar_value T> class Tensor : public Eigen3Tensor<T> {

template <scalar_value T> class DiagonalTensor : public Eigen3DiagonalTensor<T> {
public:
DiagonalTensor() { (*this) = Eigen3DiagonalTensor<T>::Zero(); }
DiagonalTensor() { (*this).setZero(); }
// additional constructors
explicit DiagonalTensor(T const& x) : Eigen3DiagonalTensor<T>{x, x, x} {}
explicit DiagonalTensor(Vector<T> const& v) : Eigen3DiagonalTensor<T>{v(0), v(1), v(2)} {}
Expand Down
42 changes: 42 additions & 0 deletions tests/cpp_unit_tests/test_main_model_se.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,48 @@ TEST_CASE_TEMPLATE("Test main model - state estimation", CalculationMethod, Iter
}
}
}
SUBCASE("Line power sensor") {
main_model.add_component<Node>({{1, 10e3}, {2, 10e3}});
main_model.add_component<Line>({{3, 1, 2, 1, 1, 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1e3}});
main_model.add_component<Source>({{4, 1, 1, 1.0, nan, nan, nan, nan}});
main_model.add_component<Shunt>({{6, 2, 1, 1800 / 10e3 / 10e3, -180 / 10e3 / 10e3, 0.0, 0.0}});
main_model.add_component<SymVoltageSensor>({{11, 1, 1e2, 10.0e3, 0.0}});
SUBCASE("Symmetric Power Sensor - Symmetric Calculation") {
main_model.add_component<SymPowerSensor>(
{{17, 3, MeasuredTerminalType::branch_from, 1e2, 1800.0, 180.0, nan, nan},
{18, 3, MeasuredTerminalType::branch_to, 1e2, -1800.0, -180.0, nan, nan},
{16, 6, MeasuredTerminalType::shunt, 1e2, 1800.0, 180.0, nan, nan}});
SUBCASE("Line flow") {
main_model.set_construction_complete();
std::vector<MathOutput<true>> const math_output =
main_model.calculate_state_estimation<true>(1e-8, 20, calculation_method);

std::vector<SymApplianceOutput> shunt_output(1);
std::vector<SymNodeOutput> node_output(2);
std::vector<SymPowerSensorOutput> power_sensor_output(3);
std::vector<BranchOutput<true>> line_output(1);
main_model.output_result<Shunt>(math_output, shunt_output.begin());
main_model.output_result<Node>(math_output, node_output.begin());
main_model.output_result<Line>(math_output, line_output.begin());
main_model.output_result<SymPowerSensor>(math_output, power_sensor_output.begin());

CHECK(shunt_output[0].p == doctest::Approx(1800.0).scale(1e3));
CHECK(shunt_output[0].q == doctest::Approx(180.0).scale(1e3));

CHECK(line_output[0].p_from == doctest::Approx(1800.0).scale(1e3));
CHECK(line_output[0].q_from == doctest::Approx(180.0).scale(1e3));
CHECK(line_output[0].p_to == doctest::Approx(-1800.0).scale(1e3));
CHECK(line_output[0].q_to == doctest::Approx(-180.0).scale(1e3));

CHECK(power_sensor_output[0].p_residual == doctest::Approx(0.0).scale(1e3)); // shunt
CHECK(power_sensor_output[0].q_residual == doctest::Approx(0.0).scale(1e3)); // shunt
CHECK(power_sensor_output[1].p_residual == doctest::Approx(0.0).scale(1e3)); // branch_from
CHECK(power_sensor_output[1].q_residual == doctest::Approx(0.0).scale(1e3)); // branch_from
CHECK(power_sensor_output[2].p_residual == doctest::Approx(0.0).scale(1e3)); // branch_to
CHECK(power_sensor_output[2].q_residual == doctest::Approx(0.0).scale(1e3)); // branch_to
}
}
}
SUBCASE("Forbid Link Power Measurements") {
main_model.add_component<Node>({{1, 10e3}, {2, 10e3}});
main_model.add_component<Link>({{3, 1, 2, 1, 1}});
Expand Down
165 changes: 140 additions & 25 deletions tests/cpp_unit_tests/test_math_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,24 +521,45 @@ TEST_CASE("Test math solver") {
SUBCASE("Test sym se with angle") {
MathSolver<true> solver{topo_ptr};
CalculationInfo info;
MathOutput<true> const output =
solver.run_state_estimation(se_input_angle, 1e-10, 20, info, iterative_linear, y_bus_sym);
MathOutput<true> output;

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input_angle, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input_angle, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

assert_output(output, output_ref);
}

SUBCASE("Test sym se without angle") {
MathSolver<true> solver{topo_ptr};
CalculationInfo info;
MathOutput<true> const output =
solver.run_state_estimation(se_input_no_angle, 1e-10, 20, info, iterative_linear, y_bus_sym);
MathOutput<true> output;

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input_no_angle, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input_no_angle, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

assert_output(output, output_ref, true);
}

SUBCASE("Test sym se with angle, const z") {
MathSolver<true> solver{topo_ptr};
CalculationInfo info;
MathOutput<true> const output =
solver.run_state_estimation(se_input_angle_const_z, 1e-10, 20, info, iterative_linear, y_bus_sym);
MathOutput<true> output;

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input_angle_const_z, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input_angle_const_z, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

assert_output(output, output_ref_z);
}

Expand All @@ -548,32 +569,62 @@ TEST_CASE("Test math solver") {
auto& branch_from_power = se_input_angle.measured_branch_from_power.front();
branch_from_power.p_variance = 0.25;
branch_from_power.q_variance = 0.75;
MathOutput<true> const output =
solver.run_state_estimation(se_input_angle, 1e-10, 20, info, iterative_linear, y_bus_sym);
MathOutput<true> output;

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input_angle, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input_angle, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

assert_output(output, output_ref);
}

SUBCASE("Test asym se with angle") {
MathSolver<false> solver{topo_ptr};
CalculationInfo info;
MathOutput<false> const output =
solver.run_state_estimation(se_input_asym_angle, 1e-10, 20, info, iterative_linear, y_bus_asym);
MathOutput<false> output;

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input_asym_angle, 1e-10, 20, info, iterative_linear, y_bus_asym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input_asym_angle, 1e-10, 20, info, newton_raphson, y_bus_asym);
}

assert_output(output, output_ref_asym);
}

SUBCASE("Test asym se without angle") {
MathSolver<false> solver{topo_ptr};
CalculationInfo info;
MathOutput<false> const output =
solver.run_state_estimation(se_input_asym_no_angle, 1e-10, 20, info, iterative_linear, y_bus_asym);
MathOutput<false> output;

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input_asym_no_angle, 1e-10, 20, info, iterative_linear, y_bus_asym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input_asym_no_angle, 1e-10, 20, info, newton_raphson, y_bus_asym);
}

assert_output(output, output_ref_asym, true);
}

SUBCASE("Test asym se with angle, const z") {
MathSolver<false> solver{topo_ptr};
CalculationInfo info;
MathOutput<false> const output =
solver.run_state_estimation(se_input_asym_angle_const_z, 1e-10, 20, info, iterative_linear, y_bus_asym);
MathOutput<false> output;

SUBCASE("iterative linear") {
output =
solver.run_state_estimation(se_input_asym_angle_const_z, 1e-10, 20, info, iterative_linear, y_bus_asym);
}
SUBCASE("Newton-Raphson") {
output =
solver.run_state_estimation(se_input_asym_angle_const_z, 1e-10, 20, info, newton_raphson, y_bus_asym);
}

assert_output(output, output_ref_asym_z);
}

Expand All @@ -583,8 +634,15 @@ TEST_CASE("Test math solver") {
auto& branch_from_power = se_input_asym_angle.measured_branch_from_power.front();
branch_from_power.p_variance = RealValue<false>{0.25};
branch_from_power.q_variance = RealValue<false>{0.75};
MathOutput<false> const output =
solver.run_state_estimation(se_input_asym_angle, 1e-10, 20, info, iterative_linear, y_bus_asym);
MathOutput<false> output;

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input_asym_angle, 1e-10, 20, info, iterative_linear, y_bus_asym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input_asym_angle, 1e-10, 20, info, newton_raphson, y_bus_asym);
}

assert_output(output, output_ref_asym);
}
}
Expand Down Expand Up @@ -1065,7 +1123,15 @@ TEST_CASE("Math solver, zero variance test") {

MathSolver<true> solver{topo_ptr};
CalculationInfo info;
MathOutput<true> output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
MathOutput<true> output;

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
// TODO(mgovers): to be added in #478
output = solver.run_state_estimation(se_input, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

// check both voltage
check_close(output.u[0], 1.0);
Expand Down Expand Up @@ -1126,8 +1192,15 @@ TEST_CASE("Math solver, measurements") {
auto param_ptr = std::make_shared<MathModelParam<true> const>(param);
auto topo_ptr = std::make_shared<MathModelTopology const>(topo);
YBus<true> const y_bus_sym{topo_ptr, param_ptr};

MathSolver<true> solver{topo_ptr};
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

CHECK(real(output.bus_injection[0]) == doctest::Approx(1.95));
CHECK(real(output.source[0].s) == doctest::Approx(1.95));
Expand All @@ -1153,7 +1226,13 @@ TEST_CASE("Math solver, measurements") {
auto topo_ptr = std::make_shared<MathModelTopology const>(topo);
YBus<true> const y_bus_sym{topo_ptr, param_ptr};
MathSolver<true> solver{topo_ptr};
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

CHECK(real(output.bus_injection[1]) == doctest::Approx(-1.95));
CHECK(real(output.load_gen[0].s) == doctest::Approx(-1.95));
Expand Down Expand Up @@ -1181,7 +1260,13 @@ TEST_CASE("Math solver, measurements") {
auto topo_ptr = std::make_shared<MathModelTopology const>(topo);
YBus<true> const y_bus_sym{topo_ptr, param_ptr};
MathSolver<true> solver{topo_ptr};
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

CHECK(real(output.bus_injection[0]) == doctest::Approx(2.0));
CHECK(real(output.source[0].s) == doctest::Approx(2.0));
Expand Down Expand Up @@ -1209,7 +1294,13 @@ TEST_CASE("Math solver, measurements") {
auto topo_ptr = std::make_shared<MathModelTopology const>(topo);
YBus<true> const y_bus_sym{topo_ptr, param_ptr};
MathSolver<true> solver{topo_ptr};
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

CHECK(real(output.bus_injection[0]) == doctest::Approx(2.0));
CHECK(real(output.source[0].s) == doctest::Approx(2.0));
Expand Down Expand Up @@ -1237,7 +1328,13 @@ TEST_CASE("Math solver, measurements") {
auto topo_ptr = std::make_shared<MathModelTopology const>(topo);
YBus<true> const y_bus_sym{topo_ptr, param_ptr};
MathSolver<true> solver{topo_ptr};
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

CHECK(real(output.bus_injection[1]) == doctest::Approx(-2.0));
CHECK(real(output.load_gen[0].s) == doctest::Approx(-2.0));
Expand All @@ -1264,7 +1361,13 @@ TEST_CASE("Math solver, measurements") {
auto topo_ptr = std::make_shared<MathModelTopology const>(topo);
YBus<true> const y_bus_sym{topo_ptr, param_ptr};
MathSolver<true> solver{topo_ptr};
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

CHECK(real(output.bus_injection[1]) == doctest::Approx(-2.0));
CHECK(real(output.branch[0].s_t) == doctest::Approx(-2.0));
Expand Down Expand Up @@ -1294,7 +1397,13 @@ TEST_CASE("Math solver, measurements") {
auto topo_ptr = std::make_shared<MathModelTopology const>(topo);
YBus<true> const y_bus_sym{topo_ptr, param_ptr};
MathSolver<true> solver{topo_ptr};
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

CHECK(real(output.bus_injection[1]) == doctest::Approx(-1.0));
CHECK(real(output.load_gen[0].s) == doctest::Approx(-1.85));
Expand Down Expand Up @@ -1323,7 +1432,13 @@ TEST_CASE("Math solver, measurements") {
auto topo_ptr = std::make_shared<MathModelTopology const>(topo);
YBus<true> const y_bus_sym{topo_ptr, param_ptr};
MathSolver<true> solver{topo_ptr};
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);

SUBCASE("iterative linear") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, iterative_linear, y_bus_sym);
}
SUBCASE("Newton-Raphson") {
output = solver.run_state_estimation(se_input, 1e-10, 20, info, newton_raphson, y_bus_sym);
}

// the different aggregation of the load gen's P and Q measurements cause differences compared to the case with
// identical variances
Expand Down
1 change: 0 additions & 1 deletion tests/cpp_unit_tests/test_serializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ constexpr std::string_view batch_dataset_dict_indent =
} // namespace

TEST_CASE("Serializer") {

std::vector<SymLoadGenUpdate> sym_load_gen(4);
meta_data.get_dataset("update").get_component("sym_load").set_nan(sym_load_gen.data(), 0, 4);
sym_load_gen[0].id = 9;
Expand Down