diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 53764bab0..f6289e0a1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -219,7 +219,7 @@ jobs: xcode-version: latest-stable - name: Build wheels - uses: pypa/cibuildwheel@v2.21.3 + uses: pypa/cibuildwheel@v2.22.0 # GitHub Actions specific build parameters env: # pass GitHub runner info into Linux container diff --git a/tests/cpp_integration_tests/test_main_model.cpp b/tests/cpp_integration_tests/test_main_model.cpp index f723532a8..199991c46 100644 --- a/tests/cpp_integration_tests/test_main_model.cpp +++ b/tests/cpp_integration_tests/test_main_model.cpp @@ -40,6 +40,7 @@ constexpr double i_load = 0.005 / 0.025 * i; } // namespace test struct State { + // TODO(mgovers): values identical to power_flow/dummy-test/input.json validation case std::vector node_input{{1, 10e3}, {2, 10e3}, {3, 10e3}}; std::vector line_input{{4, 1, 2, 1, 1, 10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 1e3}}; std::vector link_input{{5, 2, 3, 1, 1}}; @@ -49,6 +50,7 @@ struct State { {8, 3, 1, LoadGenType::const_y, RealValue{0.5e6 / 3.0}, RealValue{0.0}}}; std::vector shunt_input{{9, 3, 1, 0.015, 0.0, 0.015, 0.0}}; + // TODO(mgovers): only power_flow/pandapower pf validation cases have sensor input and they differ from here // {{{id}, measured_object}, measured_terminal_type, power_sigma, p_measured, q_measured} std::vector sym_power_sensor_input{ {11, 4, MeasuredTerminalType::branch_from, 0.02, 1.1e6, 1.1e3, nan, nan}, @@ -59,6 +61,7 @@ struct State { {17, 8, MeasuredTerminalType::load, 0.02, 1.7e6, 1.7e3, nan, nan}, {28, 3, MeasuredTerminalType::node, 0.02, 3.0e6, 3.0e3, nan, nan}}; + // TODO(mgovers): only power_flow/pandapower pf validation cases have sensor input and they differ from here // {{{id}, measured_object}, measured_terminal_type, power_sigma, p_measured, q_measured} std::vector asym_power_sensor_input{{18, 4, @@ -117,14 +120,18 @@ struct State { {nan, nan, nan}, {nan, nan, nan}}}; + // TODO(mgovers): only power_flow/pandapower pf validation cases have sensor input and they differ from here // {{{id}, measured_object}, u_sigma, u_measured, u_angle_measured} std::vector sym_voltage_sensor_input{{25, 1, 105.0, 10.1e3, 0.1}, {26, 2, 105.0, 10.2e3, 0.2}}; + // TODO(mgovers): only power_flow/pandapower pf validation cases have sensor input and they differ from here // {{{id}, measured_object}, u_sigma, u_measured, u_angle_measured} std::vector asym_voltage_sensor_input{ {27, 3, 105.0, {10.31e3 / sqrt3, 10.32e3 / sqrt3, 10.33e3 / sqrt3}, {0.0, -deg_120, -deg_240}}}; + // TODO(mgovers): only used for updating (and proving no different output). nowhere else used in powerflow + // TODO(mgovers): no powerflow validation cases have fault input std::vector fault_input{{30, 1, FaultType::single_phase_to_ground, FaultPhase::a, 3, 0.1, 0.1}}; // output vector @@ -207,7 +214,7 @@ TEST_CASE("Test main model - power flow") { State state; auto main_model = default_model(state); - SUBCASE("Test get indexer") { + SUBCASE("Test get indexer") { // TODO(mgovers): needed std::vector const node_id{2, 1, 3, 2}; IdxVector const expected_indexer{1, 0, 2, 1}; IdxVector indexer(4); @@ -215,20 +222,23 @@ TEST_CASE("Test main model - power flow") { CHECK(indexer == expected_indexer); } - SUBCASE("Test duplicated id") { + SUBCASE("Test duplicated id") { // TODO(mgovers): needed; captured in Python test; maybe move to + // test_main_core_input.cpp MainModel main_model2{50.0, meta_data::meta_data_gen::meta_data}; state.node_input[1].id = 1; CHECK_THROWS_AS(main_model2.add_component(state.node_input), ConflictID); } - SUBCASE("Test no existing id") { + SUBCASE("Test no existing id") { // TODO(mgovers): needed; captured in Python test; maybe move to + // test_main_core_input.cpp MainModel main_model2{50.0, meta_data::meta_data_gen::meta_data}; state.line_input[0].from_node = 100; main_model2.add_component(state.node_input); CHECK_THROWS_AS(main_model2.add_component(state.line_input), IDNotFound); } - SUBCASE("Test id for wrong type") { + SUBCASE("Test id for wrong type") { // TODO(mgovers): needed; captured in Python test but not all flavors; maybe + // move to test_main_core_input.cpp MainModel main_model2{50.0, meta_data::meta_data_gen::meta_data}; state.link_input[0].from_node = 4; @@ -260,157 +270,6 @@ TEST_CASE("Test main model - power flow") { CHECK_THROWS_AS(main_model2.add_component(state.sym_power_sensor_input), IDWrongType); } } - - SUBCASE("Test calculate power flow") { - auto const solver_output = - main_model.calculate(get_default_options(symmetric, CalculationMethod::linear)); - main_model.output_result(solver_output, state.sym_node); - main_model.output_result(solver_output, state.sym_branch); - main_model.output_result(solver_output, state.sym_appliance); - } -} - -TEST_CASE("Test copy main model") { - State state; - auto main_model = default_model(state); - MainModel model_2{main_model}; - - SUBCASE("Copied - Symmetrical") { - auto const solver_output = - model_2.calculate(get_default_options(symmetric, CalculationMethod::linear)); - model_2.output_result(solver_output, state.sym_node); - model_2.output_result(solver_output, state.sym_branch); - model_2.output_result(solver_output, state.sym_appliance); - CHECK(state.sym_node[0].u_pu == doctest::Approx(1.05)); - CHECK(state.sym_node[1].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_node[2].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_branch[0].i_from == doctest::Approx(test::i)); - CHECK(state.sym_appliance[0].i == doctest::Approx(test::i)); - CHECK(state.sym_appliance[1].i == doctest::Approx(0.0)); - CHECK(state.sym_appliance[2].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[3].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[4].i == doctest::Approx(test::i_shunt)); - } - SUBCASE("Copied - Asymmetrical") { - auto const solver_output = - model_2.calculate(get_default_options(asymmetric, CalculationMethod::linear)); - model_2.output_result(solver_output, state.asym_node); - model_2.output_result(solver_output, state.asym_branch); - model_2.output_result(solver_output, state.asym_appliance); - CHECK(state.asym_node[0].u_pu(0) == doctest::Approx(1.05)); - CHECK(state.asym_node[1].u_pu(1) == doctest::Approx(test::u1)); - CHECK(state.asym_node[2].u_pu(2) == doctest::Approx(test::u1)); - CHECK(state.asym_branch[0].i_from(0) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[0].i(1) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[1].i(2) == doctest::Approx(0.0)); - CHECK(state.asym_appliance[2].i(0) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[3].i(1) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[4].i(2) == doctest::Approx(test::i_shunt)); - } - model_2 = main_model; - SUBCASE("Assigned - Symmetrical") { - auto const solver_output = - model_2.calculate(get_default_options(symmetric, CalculationMethod::linear)); - model_2.output_result(solver_output, state.sym_node); - model_2.output_result(solver_output, state.sym_branch); - model_2.output_result(solver_output, state.sym_appliance); - // TODO: check voltage angle - CHECK(state.sym_node[0].u_pu == doctest::Approx(1.05)); - CHECK(state.sym_node[1].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_node[2].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_branch[0].i_from == doctest::Approx(test::i)); - CHECK(state.sym_appliance[0].i == doctest::Approx(test::i)); - CHECK(state.sym_appliance[1].i == doctest::Approx(0.0)); - CHECK(state.sym_appliance[2].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[3].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[4].i == doctest::Approx(test::i_shunt)); - } - SUBCASE("Assigned - Asymmetrical") { - auto const solver_output = - model_2.calculate(get_default_options(asymmetric, CalculationMethod::linear)); - model_2.output_result(solver_output, state.asym_node); - model_2.output_result(solver_output, state.asym_branch); - model_2.output_result(solver_output, state.asym_appliance); - CHECK(state.asym_node[0].u_pu(0) == doctest::Approx(1.05)); - CHECK(state.asym_node[1].u_pu(1) == doctest::Approx(test::u1)); - CHECK(state.asym_node[2].u_pu(2) == doctest::Approx(test::u1)); - CHECK(state.asym_branch[0].i_from(0) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[0].i(1) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[1].i(2) == doctest::Approx(0.0)); - CHECK(state.asym_appliance[2].i(0) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[3].i(1) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[4].i(2) == doctest::Approx(test::i_shunt)); - } - SUBCASE("Original - Symmetrical") { - auto const solver_output = - main_model.calculate(get_default_options(symmetric, CalculationMethod::linear)); - main_model.output_result(solver_output, state.sym_node); - main_model.output_result(solver_output, state.sym_branch); - main_model.output_result(solver_output, state.sym_appliance); - CHECK(state.sym_node[0].u_pu == doctest::Approx(1.05)); - CHECK(state.sym_node[1].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_node[2].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_branch[0].i_from == doctest::Approx(test::i)); - CHECK(state.sym_appliance[0].i == doctest::Approx(test::i)); - CHECK(state.sym_appliance[1].i == doctest::Approx(0.0)); - CHECK(state.sym_appliance[2].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[3].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[4].i == doctest::Approx(test::i_shunt)); - } - SUBCASE("Original - Asymmetrical") { - auto const solver_output = main_model.calculate( - get_default_options(asymmetric, CalculationMethod::linear)); - main_model.output_result(solver_output, state.asym_node); - main_model.output_result(solver_output, state.asym_branch); - main_model.output_result(solver_output, state.asym_appliance); - CHECK(state.asym_node[0].u_pu(0) == doctest::Approx(1.05)); - CHECK(state.asym_node[1].u_pu(1) == doctest::Approx(test::u1)); - CHECK(state.asym_node[2].u_pu(2) == doctest::Approx(test::u1)); - CHECK(state.asym_branch[0].i_from(0) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[0].i(1) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[1].i(2) == doctest::Approx(0.0)); - CHECK(state.asym_appliance[2].i(0) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[3].i(1) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[4].i(2) == doctest::Approx(test::i_shunt)); - } -} - -TEST_CASE("Test main model - iterative calculation") { - State state; - auto main_model = default_model(state); - - SUBCASE("Symmetrical") { - auto const solver_output = main_model.calculate( - get_default_options(symmetric, CalculationMethod::newton_raphson)); - main_model.output_result(solver_output, state.sym_node); - main_model.output_result(solver_output, state.sym_branch); - main_model.output_result(solver_output, state.sym_appliance); - CHECK(state.sym_node[0].u_pu == doctest::Approx(1.05)); - CHECK(state.sym_node[1].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_node[2].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_branch[0].i_from == doctest::Approx(test::i)); - CHECK(state.sym_appliance[0].i == doctest::Approx(test::i)); - CHECK(state.sym_appliance[1].i == doctest::Approx(0.0)); - CHECK(state.sym_appliance[2].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[3].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[4].i == doctest::Approx(test::i_shunt)); - } - SUBCASE("Asymmetrical") { - auto const solver_output = main_model.calculate( - get_default_options(asymmetric, CalculationMethod::newton_raphson)); - main_model.output_result(solver_output, state.asym_node); - main_model.output_result(solver_output, state.asym_branch); - main_model.output_result(solver_output, state.asym_appliance); - CHECK(state.asym_node[0].u_pu(0) == doctest::Approx(1.05)); - CHECK(state.asym_node[1].u_pu(1) == doctest::Approx(test::u1)); - CHECK(state.asym_node[2].u_pu(2) == doctest::Approx(test::u1)); - CHECK(state.asym_branch[0].i_from(0) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[0].i(1) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[1].i(2) == doctest::Approx(0.0)); - CHECK(state.asym_appliance[2].i(0) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[3].i(1) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[4].i(2) == doctest::Approx(test::i_shunt)); - } } TEST_CASE("Test main model - individual output (symmetric)") { @@ -420,111 +279,8 @@ TEST_CASE("Test main model - individual output (symmetric)") { auto const res = main_model.calculate( get_default_options(symmetric, CalculationMethod::newton_raphson)); - SUBCASE("Node, sym output") { - main_model.output_result(res, state.sym_node); - main_model.output_result(res, state.sym_appliance); - - CHECK(state.sym_node[0].u_pu == doctest::Approx(1.05)); - CHECK(state.sym_node[1].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_node[2].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_node[0].p == doctest::Approx(state.sym_appliance[0].p).scale(1e3)); - CHECK(state.sym_node[1].p == doctest::Approx(0.0).scale(1e3)); - CHECK( - state.sym_node[2].p == - doctest::Approx(state.sym_appliance[1].p - state.sym_appliance[2].p - state.sym_appliance[3].p).scale(1e3)); - CHECK(state.sym_node[0].q == doctest::Approx(state.sym_appliance[0].q).scale(1e3)); - CHECK(state.sym_node[1].q == doctest::Approx(0.0).scale(1e3)); - CHECK( - state.sym_node[2].q == - doctest::Approx(state.sym_appliance[1].q - state.sym_appliance[2].q - state.sym_appliance[3].q).scale(2e3)); - - /* - TODO - - u - - angle - */ - } - - SUBCASE("Line, sym output") { - main_model.output_result(res, state.sym_line); - - CHECK(state.sym_line[0].i_from == doctest::Approx(test::i)); - /* - TODO - - i_to - - p_from - - p_to - - q_from - - q_to - */ - } - - SUBCASE("Link, sym output") { - main_model.output_result(res, state.sym_link); - - CHECK(state.sym_link[0].i_from == doctest::Approx(test::i)); - /* - TODO - - i_to - - p_from - - p_to - - q_from - - q_to - - s_from - - s_to - */ - } - - SUBCASE("Source, sym output") { - main_model.output_result(res, state.sym_source); - main_model.output_result(res, state.sym_node); - - CHECK(state.sym_source[0].i == doctest::Approx(test::i)); - CHECK(state.sym_source[1].i == doctest::Approx(0.0)); - /* - TODO - - p - - q - - s - */ - } - - SUBCASE("SymLoad, sym output") { - main_model.output_result(res, state.sym_load_sym); - - CHECK(state.sym_load_sym[0].i == doctest::Approx(test::i_load)); - /* - TODO - - p - - q - - s - */ - } - - SUBCASE("AsymLoad, sym output") { - main_model.output_result(res, state.sym_load_asym); - - CHECK(state.sym_load_asym[0].i == doctest::Approx(test::i_load)); - /* - TODO - - p - - q - - s - */ - } - - SUBCASE("Shunt, sym output") { - main_model.output_result(res, state.sym_node); - main_model.output_result(res, state.sym_shunt); - auto const& output = state.sym_shunt[0]; - CHECK(output.i == doctest::Approx(test::i_shunt)); - CHECK(output.p == doctest::Approx(sqrt3 * test::i_shunt * state.sym_node[2].u)); - CHECK(output.q == doctest::Approx(0.0)); - CHECK(output.s == doctest::Approx(output.p)); - CHECK(output.pf == doctest::Approx(1.0)); - } - - SUBCASE("SymVoltageSensor, sym output") { + SUBCASE("SymVoltageSensor, sym output") { // TODO(mgovers): sensor output for powerflow calculations are not tested + // elsewhere => validation case main_model.output_result(res, state.sym_node); main_model.output_result(res, state.sym_voltage_sensor); @@ -534,7 +290,8 @@ TEST_CASE("Test main model - individual output (symmetric)") { CHECK(state.sym_voltage_sensor[1].u_angle_residual == doctest::Approx(0.2 - state.sym_node[1].u_angle)); } - SUBCASE("SymPowerSensor, sym output") { + SUBCASE("SymPowerSensor, sym output") { // TODO(mgovers): sensor output for powerflow calculations are not tested + // elsewhere => validation case main_model.output_result(res, state.sym_line); main_model.output_result(res, state.sym_link); main_model.output_result(res, state.sym_source); @@ -561,7 +318,8 @@ TEST_CASE("Test main model - individual output (symmetric)") { doctest::Approx(3.0e3 - (state.sym_source[1].q - state.sym_load_sym[0].q - state.sym_load_asym[0].q))); } - SUBCASE("AsymVoltageSensor, sym output") { + SUBCASE("AsymVoltageSensor, sym output") { // TODO(mgovers): sensor output for powerflow calculations are not tested + // elsewhere => validation case main_model.output_result(res, state.sym_node); main_model.output_result(res, state.asym_voltage_sensor_sym_output); @@ -570,7 +328,8 @@ TEST_CASE("Test main model - individual output (symmetric)") { doctest::Approx(0.0 - state.sym_node[2].u_angle)); } - SUBCASE("AsymPowerSensor, sym output") { + SUBCASE("AsymPowerSensor, sym output") { // TODO(mgovers): sensor output for powerflow calculations are not tested + // elsewhere => validation case main_model.output_result(res, state.sym_line); main_model.output_result(res, state.sym_link); main_model.output_result(res, state.sym_source); @@ -613,38 +372,8 @@ TEST_CASE("Test main model - individual output (asymmetric)") { auto const res = main_model.calculate( get_default_options(asymmetric, CalculationMethod::newton_raphson)); - /* - TODO: - - test node - - test line - - test link - - test source - - test sym load - - test asym load - - test shunt - */ - - SUBCASE("Node, asym output") { - main_model.output_result(res, state.asym_node); - main_model.output_result(res, state.asym_appliance); - - CHECK(state.asym_node[0].u_pu(0) == doctest::Approx(1.05)); - CHECK(state.asym_node[1].u_pu(1) == doctest::Approx(test::u1)); - CHECK(state.asym_node[2].u_pu(2) == doctest::Approx(test::u1)); - - CHECK(state.asym_node[0].p(0) == doctest::Approx(state.asym_appliance[0].p(0)).scale(1e3)); - CHECK(state.asym_node[1].p(1) == doctest::Approx(0.0).scale(1e3)); - CHECK(state.asym_node[2].p(2) == doctest::Approx(state.asym_appliance[1].p(2) - state.asym_appliance[2].p(2) - - state.asym_appliance[3].p(2)) - .scale(1e3)); - CHECK(state.asym_node[0].q(2) == doctest::Approx(state.asym_appliance[0].q(2)).scale(1e3)); - CHECK(state.asym_node[1].q(1) == doctest::Approx(0.0).scale(1e3)); - CHECK(state.asym_node[2].q(0) == doctest::Approx(state.asym_appliance[1].q(0) - state.asym_appliance[2].q(0) - - state.asym_appliance[3].q(0)) - .scale(1e3)); - } - - SUBCASE("AsymVoltageSensor, asym output") { + SUBCASE("AsymVoltageSensor, asym output") { // TODO(mgovers): sensor output for powerflow calculations are not + // tested elsewhere => validation case main_model.output_result(res, state.asym_node); main_model.output_result(res, state.asym_voltage_sensor); @@ -661,7 +390,8 @@ TEST_CASE("Test main model - individual output (asymmetric)") { doctest::Approx(-deg_240 - state.asym_node[2].u_angle[2])); } - SUBCASE("SymVoltageSensor, asym output") { + SUBCASE("SymVoltageSensor, asym output") { // TODO(mgovers): sensor output for powerflow calculations are not tested + // elsewhere => validation case main_model.output_result(res, state.asym_node); main_model.output_result(res, state.sym_voltage_sensor_asym_output); @@ -692,7 +422,8 @@ TEST_CASE("Test main model - individual output (asymmetric)") { } // Note that only 1/3 of the values is being checked - SUBCASE("AsymPowerSensor, asym output") { + SUBCASE("AsymPowerSensor, asym output") { // TODO(mgovers): sensor output for powerflow calculations are not tested + // elsewhere main_model.output_result(res, state.asym_line); main_model.output_result(res, state.asym_link); main_model.output_result(res, state.asym_source); @@ -721,7 +452,8 @@ TEST_CASE("Test main model - individual output (asymmetric)") { 5.02e3 - (state.asym_source[1].q[1] - state.asym_load_sym[0].q[1] - state.asym_load_asym[0].q[1]))); } - SUBCASE("SymPowerSensor, asym output") { + SUBCASE("SymPowerSensor, asym output") { // TODO(mgovers): sensor output for powerflow calculations are not tested + // elsewhere main_model.output_result(res, state.asym_line); main_model.output_result(res, state.asym_link); main_model.output_result(res, state.asym_source); @@ -763,45 +495,8 @@ TEST_CASE("Test main model - individual output (asymmetric)") { } } -TEST_CASE("Test main model - linear calculation") { - State state; - auto main_model = default_model(state); - - SUBCASE("Symmetrical") { - auto const solver_output = - main_model.calculate(get_default_options(symmetric, CalculationMethod::linear)); - main_model.output_result(solver_output, state.sym_node); - main_model.output_result(solver_output, state.sym_branch); - main_model.output_result(solver_output, state.sym_appliance); - CHECK(state.sym_node[0].u_pu == doctest::Approx(1.05)); - CHECK(state.sym_node[1].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_node[2].u_pu == doctest::Approx(test::u1)); - CHECK(state.sym_branch[0].i_from == doctest::Approx(test::i)); - CHECK(state.sym_appliance[0].i == doctest::Approx(test::i)); - CHECK(state.sym_appliance[1].i == doctest::Approx(0.0)); - CHECK(state.sym_appliance[2].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[3].i == doctest::Approx(test::i_load)); - CHECK(state.sym_appliance[4].i == doctest::Approx(test::i_shunt)); - } - SUBCASE("Asymmetrical") { - auto const solver_output = main_model.calculate( - get_default_options(asymmetric, CalculationMethod::linear)); - main_model.output_result(solver_output, state.asym_node); - main_model.output_result(solver_output, state.asym_branch); - main_model.output_result(solver_output, state.asym_appliance); - CHECK(state.asym_node[0].u_pu(0) == doctest::Approx(1.05)); - CHECK(state.asym_node[1].u_pu(1) == doctest::Approx(test::u1)); - CHECK(state.asym_node[2].u_pu(2) == doctest::Approx(test::u1)); - CHECK(state.asym_branch[0].i_from(0) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[0].i(1) == doctest::Approx(test::i)); - CHECK(state.asym_appliance[1].i(2) == doctest::Approx(0.0)); - CHECK(state.asym_appliance[2].i(0) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[3].i(1) == doctest::Approx(test::i_load)); - CHECK(state.asym_appliance[4].i(2) == doctest::Approx(test::i_shunt)); - } -} - -TEST_CASE_TEMPLATE("Test main model - unknown id", settings, regular_update, cached_update) { +TEST_CASE_TEMPLATE("Test main model - unknown id", settings, regular_update, + cached_update) { // TODO(mgovers): we need this test State const state; auto main_model = default_model(state); @@ -811,7 +506,9 @@ TEST_CASE_TEMPLATE("Test main model - unknown id", settings, regular_update, cac CHECK_THROWS_AS((main_model.update_components(update_data)), IDNotFound); } -TEST_CASE_TEMPLATE("Test main model - update only load", settings, regular_update, cached_update) { +TEST_CASE_TEMPLATE( + "Test main model - update only load", settings, regular_update, + cached_update) { // TODO(mgovers): we should whitebox-test this instead; values not reproduced by validation tests State state; auto main_model = default_model(state); @@ -856,7 +553,9 @@ TEST_CASE_TEMPLATE("Test main model - update only load", settings, regular_updat } } -TEST_CASE_TEMPLATE("Test main model - update load and shunt param", settings, regular_update, cached_update) { +TEST_CASE_TEMPLATE( + "Test main model - update load and shunt param", settings, regular_update, + cached_update) { // TODO(mgovers): we should whitebox-test this instead; values not reproduced by validation tests State state; auto main_model = default_model(state); @@ -904,7 +603,9 @@ TEST_CASE_TEMPLATE("Test main model - update load and shunt param", settings, re } } -TEST_CASE_TEMPLATE("Test main model - all updates", settings, regular_update, cached_update) { +TEST_CASE_TEMPLATE( + "Test main model - all updates", settings, regular_update, + cached_update) { // TODO(mgovers): we should whitebox-test this instead; values not reproduced by validation tests State state; auto main_model = default_model(state); @@ -959,7 +660,8 @@ TEST_CASE_TEMPLATE("Test main model - all updates", settings, regular_update, ca } } -TEST_CASE_TEMPLATE("Test main model - single permanent update from batch", settings, regular_update, cached_update) { +TEST_CASE_TEMPLATE("Test main model - single permanent update from batch", settings, regular_update, + cached_update) { // TODO(mgovers): we should whitebox-test this instead State state; auto main_model = default_model(state); @@ -1010,7 +712,9 @@ TEST_CASE_TEMPLATE("Test main model - single permanent update from batch", setti } } -TEST_CASE_TEMPLATE("Test main model - restore components", settings, regular_update, cached_update) { +TEST_CASE_TEMPLATE("Test main model - restore components", settings, regular_update, + cached_update) { // TODO(mgovers): either whitebox (as a sub-part of batch impl) or otherwise drop + // entirely (tested by batch update) State state; auto main_model = default_model(state); @@ -1072,7 +776,8 @@ TEST_CASE_TEMPLATE("Test main model - restore components", settings, regular_upd } } -TEST_CASE_TEMPLATE("Test main model - updates w/ alternating compute mode", settings, regular_update, cached_update) { +TEST_CASE_TEMPLATE("Test main model - updates w/ alternating compute mode", settings, regular_update, + cached_update) { // TODO(mgovers): we need to keep this one way or another constexpr auto check_sym = [](MainModel const& model_, auto const& math_output_) { State state_; model_.output_result(math_output_, state_.sym_node); @@ -1174,7 +879,8 @@ TEST_CASE("Test main model - runtime dispatch") { input_data.add_buffer("shunt", state.shunt_input.size(), state.shunt_input.size(), nullptr, state.shunt_input.data()); - SUBCASE("Single-size batches") { + SUBCASE("Single-size batches") { // TODO(mgovers): can be removed: validation cases already do single + + // multi-threaded; whitebox test should be isolated ConstDataset update_data{true, 1, "update", meta_data::meta_data_gen::meta_data}; update_data.add_buffer("sym_load", state.sym_load_update.size(), state.sym_load_update.size(), nullptr, state.sym_load_update.data()); @@ -1261,7 +967,8 @@ TEST_CASE("Test main model - runtime dispatch") { CHECK(state.asym_node[2].u_pu(2) == doctest::Approx(test::u1)); } - SUBCASE("no dependent updates within batches") { + SUBCASE("no dependent updates within batches") { // TODO(mgovers): validation cases capture this; whitebox test + // should be isolated MainModel model{50.0, input_data}; std::vector sym_load_update_2{{7, 1, nan, 1.0e7}, {7, 1, 1.0e3, nan}, {7, 1, 1.0e3, 1.0e7}}; @@ -1287,7 +994,8 @@ TEST_CASE("Test main model - runtime dispatch") { CHECK(sym_node_2[8].u_pu == doctest::Approx(0.67).epsilon(0.005)); } - SUBCASE("Columnar buffers in dataset") { + SUBCASE("Columnar buffers in dataset") { // TODO(mgovers): API tests now capture this; validation cases do not test + // columnar buffers auto const options = get_default_options(symmetric, CalculationMethod::newton_raphson); SUBCASE("Columnar buffers in input data") { @@ -1437,7 +1145,7 @@ TEST_CASE("Test main model - runtime dispatch") { } } - SUBCASE("Without IDs") { + SUBCASE("Without IDs") { // TODO(mgovers): API tests already captured this; validation cases added ConstDataset update_data_with_ids{false, 1, "update", meta_data::meta_data_gen::meta_data}; update_data_with_ids.add_buffer("sym_load", update_size, update_size, nullptr, nullptr); update_data_with_ids.add_attribute_buffer("sym_load", "id", sym_load_ids.data()); @@ -1480,7 +1188,8 @@ TEST_CASE("Test main model - runtime dispatch") { } } - SUBCASE("Empty columnar update data") { + SUBCASE( + "Empty columnar update data") { // TODO(mgovers): power_flow/dummy-test-batch-shunt already captures this std::vector sym_load_ids; std::vector sym_load_p_specified; REQUIRE(sym_load_ids.size() == sym_load_p_specified.size()); @@ -1579,7 +1288,8 @@ TEST_CASE("Test main model - incomplete input") { MainModel const ref_model{main_model}; - SUBCASE("Symmetrical - Complete") { + SUBCASE("Symmetrical - Complete") { // TODO(mgovers): validation case with different values in + // power_flow/dummy-test-batch-incomplete-input MutableDataset test_result_data{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; MutableDataset ref_result_data{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; @@ -1613,7 +1323,7 @@ TEST_CASE("Test main model - incomplete input") { CHECK(test_sym_node[2].u_pu == doctest::Approx(ref_sym_node[2].u_pu)); } - SUBCASE("Asymmetrical - Complete") { + SUBCASE("Asymmetrical - Complete") { // TODO(mgovers): no validation case for asym exists MutableDataset test_result_data{true, 1, "asym_output", meta_data::meta_data_gen::meta_data}; MutableDataset ref_result_data{true, 1, "asym_output", meta_data::meta_data_gen::meta_data}; @@ -1655,7 +1365,7 @@ TEST_CASE("Test main model - incomplete input") { } } - SUBCASE("Symmetrical - Incomplete") { + SUBCASE("Symmetrical - Incomplete") { // TODO(mgovers): not tested elsewhere; maybe test in API model? MutableDataset test_result_data{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; MutableDataset const ref_result_data{true, 1, "sym_output", meta_data::meta_data_gen::meta_data}; @@ -1693,7 +1403,7 @@ TEST_CASE("Test main model - incomplete input") { } } - SUBCASE("Asymmetrical - Incomplete") { + SUBCASE("Asymmetrical - Incomplete") { // TODO(mgovers): not tested elsewhere; maybe test in API model? MutableDataset test_result_data{true, 1, "asym_output", meta_data::meta_data_gen::meta_data}; MutableDataset const ref_result_data{true, 1, "asym_output", meta_data::meta_data_gen::meta_data}; @@ -1732,7 +1442,8 @@ TEST_CASE("Test main model - incomplete input") { } } -TEST_CASE("Test main model - Incomplete followed by complete") { +TEST_CASE("Test main model - Incomplete followed by complete") { // TODO(mgovers): This tests the reset of 2 consecutive + // batch scenarios and definitely needs to be tested using CalculationMethod::linear; State const state; diff --git a/tests/cpp_integration_tests/test_main_model_sc.cpp b/tests/cpp_integration_tests/test_main_model_sc.cpp index 9250c3768..59498c76d 100644 --- a/tests/cpp_integration_tests/test_main_model_sc.cpp +++ b/tests/cpp_integration_tests/test_main_model_sc.cpp @@ -17,7 +17,8 @@ using enum CalculationSymmetry; TEST_CASE("Test main model - short circuit") { MainModel main_model{50.0, meta_data::meta_data_gen::meta_data}; - SUBCASE("Single node + source") { + SUBCASE("Single node + source") { // TODO(mgovers): existing validation case for this is too difficult. we may want + // to keep this. Also should not live here but in SC solver double const u_rated = 10e3; double const u_ref = 1.0; double const sk = 100e6; @@ -127,7 +128,8 @@ TEST_CASE("Test main model - short circuit") { } } - SUBCASE("Two nodes + branch + source") { + SUBCASE("Two nodes + branch + source") { // TODO(mgovers): existing validation case for this is too difficult. we + // may want to keep this ShortCircuitVoltageScaling const voltage_scaling = ShortCircuitVoltageScaling::maximum; constexpr double voltage_scaling_c = 1.1; @@ -163,7 +165,9 @@ TEST_CASE("Test main model - short circuit") { } } -TEST_CASE("Test main model - short circuit - Dataset input") { +TEST_CASE("Test main model - short circuit - Dataset input") { // TODO(mgovers): same logic as above but different input + // type. maybe make a validation case for this; otherwise + // may be removed SUBCASE("Two nodes + branch + source") { std::vector node_input{{1, 10e4}, {2, 10e4}}; std::vector line_input{{3, 1, 2, 1, 1, 10.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 1e3}}; diff --git a/tests/cpp_integration_tests/test_main_model_se.cpp b/tests/cpp_integration_tests/test_main_model_se.cpp index 1ad636d4f..714d53dee 100644 --- a/tests/cpp_integration_tests/test_main_model_se.cpp +++ b/tests/cpp_integration_tests/test_main_model_se.cpp @@ -35,7 +35,8 @@ TEST_CASE_TEMPLATE("Test main model - state estimation", CalcMethod, IterativeLi .max_iter = 20}; SUBCASE("State Estimation") { - SUBCASE("Single Node + Source") { + SUBCASE("Single Node + Source") { // TODO(mgovers): these are so simple, they may be API tests, but that would + // just be moving the problem around. main_model.add_component({{1, 10e3}}); main_model.add_component({{2, 1, 1, 1.0, nan, nan, nan, nan}}); SUBCASE("Symmetric Voltage Sensor") { @@ -141,7 +142,8 @@ TEST_CASE_TEMPLATE("Test main model - state estimation", CalcMethod, IterativeLi } } - SUBCASE("Node Injection") { + SUBCASE("Node Injection") { // TODO(mgovers): these are so simple, they may be API tests, but that would just be + // moving the problem around. main_model.add_component({{1, 10e3}, {2, 10e3}}); main_model.add_component({{3, 1, 2, 1, 1}}); main_model.add_component({{4, 1, 1, 1.0, nan, nan, nan, nan}}); @@ -220,7 +222,8 @@ TEST_CASE_TEMPLATE("Test main model - state estimation", CalcMethod, IterativeLi } } } - SUBCASE("Line power sensor") { + SUBCASE("Line power sensor") { // TODO(mgovers): these are so simple, they may be API tests, but that would just + // be moving the problem around. main_model.add_component({{1, 10e3}, {2, 10e3}}); main_model.add_component({{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({{4, 1, 1, 1.0, nan, nan, nan, nan}}); @@ -265,7 +268,8 @@ TEST_CASE_TEMPLATE("Test main model - state estimation", CalcMethod, IterativeLi } } } - SUBCASE("Forbid Link Power Measurements") { + SUBCASE("Forbid Link Power Measurements") { // TODO(mgovers): This should be tested. maybe API test or in an + // isolated environment main_model.add_component({{1, 10e3}, {2, 10e3}}); main_model.add_component({{3, 1, 2, 1, 1}}); CHECK_THROWS_AS(main_model.add_component( @@ -298,7 +302,8 @@ TEST_CASE_TEMPLATE("Test main model - state estimation", CalcMethod, IterativeLi } } - SUBCASE("Test incomplete input but complete update dataset") { + SUBCASE( + "Test incomplete input but complete update dataset") { // TODO(mgovers): this tests the same as the PF version std::vector node_input{{1, 10e3}}; std::vector incomplete_source_input{{2, 1, 1, nan, nan, nan, nan, nan}}; diff --git a/tests/cpp_integration_tests/test_math_solver.cpp b/tests/cpp_integration_tests/test_math_solver.cpp index eb3529d37..822513aae 100644 --- a/tests/cpp_integration_tests/test_math_solver.cpp +++ b/tests/cpp_integration_tests/test_math_solver.cpp @@ -122,7 +122,8 @@ void assert_sc_output(ShortCircuitSolverOutput const& output, ShortCircuitS } // namespace -TEST_CASE("Test math solver") { +TEST_CASE( + "Test math solver") { // most of these should be template test cases with instantiations for the individual solvers /* network, v means voltage measured, p means power measured, pp means double measured variance always 1.0 diff --git a/tests/data/power_flow/dummy-test-batch-incomplete-input/params.json b/tests/data/power_flow/dummy-test-batch-incomplete-input/params.json index 30cc0dc99..56afdd500 100644 --- a/tests/data/power_flow/dummy-test-batch-incomplete-input/params.json +++ b/tests/data/power_flow/dummy-test-batch-incomplete-input/params.json @@ -1,5 +1,10 @@ { - "calculation_method": "linear", + "calculation_method": [ + "linear", + "newton_raphson", + "iterative_current", + "linear_current" + ], "rtol": 1e-5, "atol": 1e-5 } \ No newline at end of file diff --git a/tests/data/power_flow/dummy-test-batch-independent-cacheable/update_batch.json b/tests/data/power_flow/dummy-test-batch-independent-cacheable/update_batch.json index 6e417bc52..210ea3c86 100644 --- a/tests/data/power_flow/dummy-test-batch-independent-cacheable/update_batch.json +++ b/tests/data/power_flow/dummy-test-batch-independent-cacheable/update_batch.json @@ -7,11 +7,9 @@ { "sym_load": [ { - "id": 7, "q_specified": 2.5 }, { - "id": 8, "q_specified": 7.5 } ] @@ -19,11 +17,9 @@ { "sym_load": [ { - "id": 7, "q_specified": 15.0 }, { - "id": 8, "q_specified": 5.0 } ] @@ -31,11 +27,9 @@ { "sym_load": [ { - "id": 7, "q_specified": 21.0 }, { - "id": 8, "q_specified": 9.0 } ] diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/input.json b/tests/data/power_flow/dummy-test-batch-optional-id/input.json new file mode 100644 index 000000000..5351d0a4e --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/input.json @@ -0,0 +1,60 @@ +{ + "version": "1.0", + "type": "input", + "is_batch": false, + "attributes": {}, + "data": { + "node": [ + { + "id": 1, + "u_rated": 10.0 + }, + { + "id": 2, + "u_rated": 10.0 + } + ], + "line": [ + { + "id": 4, + "from_node": 1, + "to_node": 2, + "from_status": 1, + "to_status": 1, + "r1": 0.0, + "x1": 1.0, + "c1": 0.0, + "tan1": 0.0, + "i_n": 1e3 + } + ], + "source": [ + { + "id": 6, + "node": 1, + "status": 1, + "u_ref": 1.0, + "sk": 100.0, + "rx_ratio": 0.0 + } + ], + "sym_load": [ + { + "id": 7, + "node": 2, + "status": 1, + "type": 2, + "p_specified": 0.0, + "q_specified": 0.0 + }, + { + "id": 8, + "node": 2, + "status": 1, + "type": 2, + "p_specified": 0.0, + "q_specified": 0.0 + } + ] + } +} \ No newline at end of file diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/input.json.license b/tests/data/power_flow/dummy-test-batch-optional-id/input.json.license new file mode 100644 index 000000000..760105916 --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/input.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/params.json b/tests/data/power_flow/dummy-test-batch-optional-id/params.json new file mode 100644 index 000000000..d32ef9505 --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/params.json @@ -0,0 +1,5 @@ +{ + "calculation_method": ["newton_raphson", "iterative_current"], + "rtol": 1e-5, + "atol": 1e-5 +} \ No newline at end of file diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/params.json.license b/tests/data/power_flow/dummy-test-batch-optional-id/params.json.license new file mode 100644 index 000000000..760105916 --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/params.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/sym_output.json b/tests/data/power_flow/dummy-test-batch-optional-id/sym_output.json new file mode 100644 index 000000000..f03e4ea72 --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/sym_output.json @@ -0,0 +1,16 @@ +{ + "version": "1.0", + "type": "sym_output", + "is_batch": false, + "attributes": {}, + "data": { + "node": [ + { + "u": 10.0 + }, + { + "u": 10.0 + } + ] + } +} \ No newline at end of file diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/sym_output.json.license b/tests/data/power_flow/dummy-test-batch-optional-id/sym_output.json.license new file mode 100644 index 000000000..760105916 --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/sym_output.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/sym_output_batch.json b/tests/data/power_flow/dummy-test-batch-optional-id/sym_output_batch.json new file mode 100644 index 000000000..2002269a9 --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/sym_output_batch.json @@ -0,0 +1,38 @@ +{ + "version": "1.0", + "type": "sym_output", + "is_batch": true, + "attributes": {}, + "data": [ + { + "node": [ + { + "u": 9.0 + }, + { + "u": 8.0 + } + ] + }, + { + "node": [ + { + "u": 8.0 + }, + { + "u": 6.0 + } + ] + }, + { + "node": [ + { + "u": 7.0 + }, + { + "u": 4.0 + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/sym_output_batch.json.license b/tests/data/power_flow/dummy-test-batch-optional-id/sym_output_batch.json.license new file mode 100644 index 000000000..760105916 --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/sym_output_batch.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/update_batch.json b/tests/data/power_flow/dummy-test-batch-optional-id/update_batch.json new file mode 100644 index 000000000..210ea3c86 --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/update_batch.json @@ -0,0 +1,38 @@ +{ + "version": "1.0", + "type": "update", + "is_batch": true, + "attributes": {}, + "data": [ + { + "sym_load": [ + { + "q_specified": 2.5 + }, + { + "q_specified": 7.5 + } + ] + }, + { + "sym_load": [ + { + "q_specified": 15.0 + }, + { + "q_specified": 5.0 + } + ] + }, + { + "sym_load": [ + { + "q_specified": 21.0 + }, + { + "q_specified": 9.0 + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/data/power_flow/dummy-test-batch-optional-id/update_batch.json.license b/tests/data/power_flow/dummy-test-batch-optional-id/update_batch.json.license new file mode 100644 index 000000000..760105916 --- /dev/null +++ b/tests/data/power_flow/dummy-test-batch-optional-id/update_batch.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/tests/data/power_flow/dummy-test-batch/params.json b/tests/data/power_flow/dummy-test-batch/params.json index 30cc0dc99..56afdd500 100644 --- a/tests/data/power_flow/dummy-test-batch/params.json +++ b/tests/data/power_flow/dummy-test-batch/params.json @@ -1,5 +1,10 @@ { - "calculation_method": "linear", + "calculation_method": [ + "linear", + "newton_raphson", + "iterative_current", + "linear_current" + ], "rtol": 1e-5, "atol": 1e-5 } \ No newline at end of file diff --git a/tests/data/power_flow/dummy-test/asym_output.json b/tests/data/power_flow/dummy-test/asym_output.json new file mode 100644 index 000000000..4ec910f67 --- /dev/null +++ b/tests/data/power_flow/dummy-test/asym_output.json @@ -0,0 +1,197 @@ +{ + "version": "1.0", + "type": "asym_output", + "is_batch": false, + "attributes": {}, + "data": { + "node": [ + { + "id": 1, + "u_pu": [ + 1.05, + 1.05, + 1.05 + ], + "u_angle": [ + 0.0, + 0.0, + 0.0 + ], + "p": [ + 735000.0, + 735000.0, + 735000.0 + ], + "q": [ + 0.0, + 0.0, + 0.0 + ] + }, + { + "id": 2, + "u_pu": [ + 0.84, + 0.84, + 0.84 + ], + "p": [ + 0.0, + 0.0, + 0.0 + ], + "q": [ + 0.0, + 0.0, + 0.0 + ] + }, + { + "id": 3, + "u_pu": [ + 0.84, + 0.84, + 0.84 + ], + "p": [ + -235200.0, + -235200.0, + -235200.0 + ], + "q": [ + 0.0, + 0.0, + 0.0 + ] + } + ], + "line": [ + { + "id": 4, + "i_from": [ + 121.24355652982142, + 121.24355652982142, + 121.24355652982142 + ] + } + ], + "link": [ + { + "id": 5, + "i_from": [ + 121.24355652982142, + 121.24355652982142, + 121.24355652982142 + ] + } + ], + "source": [ + { + "id": 6, + "i": [ + 121.24355652982142, + 121.24355652982142, + 121.24355652982142 + ], + "p": [ + 735000.0, + 735000.0, + 735000.0 + ], + "q": [ + 0.0, + 0.0, + 0.0 + ] + }, + { + "id": 10, + "i": [ + 0.0, + 0.0, + 0.0 + ], + "p": [ + 0.0, + 0.0, + 0.0 + ], + "q": [ + 0.0, + 0.0, + 0.0 + ] + } + ], + "sym_load": [ + { + "id": 7, + "i": [ + 24.24871130596428, + 24.24871130596428, + 24.24871130596428 + ], + "p": [ + 117600.0, + 117600.0, + 117600.0 + ], + "q": [ + 0.0, + 0.0, + 0.0 + ] + } + ], + "asym_load": [ + { + "id": 8, + "i": [ + 24.24871130596428, + 24.24871130596428, + 24.24871130596428 + ], + "p": [ + 117600.0, + 117600.0, + 117600.0 + ], + "q": [ + 0.0, + 0.0, + 0.0 + ] + } + ], + "shunt": [ + { + "id": 9, + "i": [ + 72.74613391789285, + 72.74613391789285, + 72.74613391789285 + ], + "p": [ + 3.528e5, + 3.528e5, + 3.528e5 + ], + "q": [ + 0.0, + 0.0, + 0.0 + ], + "s": [ + 3.528e5, + 3.528e5, + 3.528e5 + ], + "pf": [ + 1.0, + 1.0, + 1.0 + ] + } + ] + } +} \ No newline at end of file diff --git a/tests/data/power_flow/dummy-test/asym_output.json.license b/tests/data/power_flow/dummy-test/asym_output.json.license new file mode 100644 index 000000000..760105916 --- /dev/null +++ b/tests/data/power_flow/dummy-test/asym_output.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: Contributors to the Power Grid Model project + +SPDX-License-Identifier: MPL-2.0 diff --git a/tests/data/power_flow/dummy-test/params.json b/tests/data/power_flow/dummy-test/params.json index d32ef9505..13c1e17f6 100644 --- a/tests/data/power_flow/dummy-test/params.json +++ b/tests/data/power_flow/dummy-test/params.json @@ -1,5 +1,14 @@ { - "calculation_method": ["newton_raphson", "iterative_current"], + "calculation_method": [ + "linear", + "newton_raphson", + "iterative_current", + "linear_current" + ], "rtol": 1e-5, - "atol": 1e-5 + "atol": { + "default": 1e-5, + "p": 0.005, + "q": 0.05 + } } \ No newline at end of file diff --git a/tests/data/power_flow/dummy-test/sym_output.json b/tests/data/power_flow/dummy-test/sym_output.json index 773e42661..4a679e321 100644 --- a/tests/data/power_flow/dummy-test/sym_output.json +++ b/tests/data/power_flow/dummy-test/sym_output.json @@ -7,15 +7,27 @@ "node": [ { "id": 1, - "u_pu": 1.05 + "u_pu": 1.05, + "u": 10500.0, + "u_angle": 0.0, + "p": 2205000.0, + "q": 0.0 }, { "id": 2, - "u_pu": 0.84 + "u_pu": 0.84, + "u": 8400.0, + "u_angle": 0.0, + "p": -0.00961, + "q": 0.0 }, { "id": 3, - "u_pu": 0.84 + "u_pu": 0.84, + "u": 8400.0, + "u_angle": 0.0, + "p": -705600.0, + "q": 0.0 } ], "line": [ @@ -33,29 +45,41 @@ "source": [ { "id": 6, - "i": 121.24355652982142 + "i": 121.24355652982142, + "p": 2205000.0, + "q": 0.0 }, { "id": 10, - "i": 0.0 + "i": 0.0, + "p": 0.0, + "q": 0.0 } ], "sym_load": [ { "id": 7, - "i": 24.24871130596428 + "i": 24.24871130596428, + "p": 3.528e5, + "q": 0.0 } ], "asym_load": [ { "id": 8, - "i": 24.24871130596428 + "i": 24.24871130596428, + "p": 3.528e5, + "q": 0.0 } ], "shunt": [ { "id": 9, - "i": 72.74613391789285 + "i": 72.74613391789285, + "p": 1058400.0, + "q": 0.0, + "s": 1058400.0, + "pf": 1.0 } ] } diff --git a/tests/unit/test_error_handling.py b/tests/unit/test_error_handling.py index 38e7a522d..15902c6fc 100644 --- a/tests/unit/test_error_handling.py +++ b/tests/unit/test_error_handling.py @@ -13,6 +13,7 @@ AutomaticTapCalculationError, ConflictID, ConflictVoltage, + IDNotFound, IDWrongType, InvalidArguments, InvalidBranch, @@ -205,6 +206,21 @@ def test_handle_conflict_id_error(): PowerGridModel(input_data={"node": node_input}) +def test_handle_id_not_found_error(): + node_input = initialize_array("input", "node", 1) + node_input["id"] = [0] + node_input["u_rated"] = [0.0] + + source_input = initialize_array("input", "source", 1) + source_input["id"] = [1] + source_input["node"] = [99] + source_input["status"] = [1] + source_input["u_ref"] = [0.0] + + with pytest.raises(IDNotFound): + PowerGridModel(input_data={"node": node_input, "source": source_input}) + + def test_handle_invalid_measured_object_error(): node_input = initialize_array("input", "node", 2) node_input["id"] = [0, 1]