From 655e49480ba8918e827afa774362f126011b3c43 Mon Sep 17 00:00:00 2001 From: leovsch Date: Thu, 3 Oct 2024 17:18:37 +0200 Subject: [PATCH] Added implementation for asym_line input --- .../data/attribute_classes/input.json | 49 ++++++ .../dataset_definitions.json | 12 +- .../power_grid_model/auxiliary/input.hpp | 49 ++++++ .../auxiliary/meta_gen/input.hpp | 46 +++++ .../auxiliary/static_asserts/input.hpp | 19 +++ .../power_grid_model/common/common.hpp | 1 + .../power_grid_model/common/exception.hpp | 11 ++ .../common/three_phase_tensor.hpp | 20 +++ .../power_grid_model/component/asym_line.hpp | 139 ++++++++++++++++ .../power_grid_model_c/dataset_definitions.h | 84 ++++++++++ .../src/dataset_definitions.cpp | 84 ++++++++++ .../core/dataset_definitions.py | 1 + tests/cpp_unit_tests/CMakeLists.txt | 1 + tests/cpp_unit_tests/test_asym_line.cpp | 157 ++++++++++++++++++ 14 files changed, 671 insertions(+), 2 deletions(-) create mode 100644 power_grid_model_c/power_grid_model/include/power_grid_model/component/asym_line.hpp create mode 100644 tests/cpp_unit_tests/test_asym_line.cpp diff --git a/code_generation/data/attribute_classes/input.json b/code_generation/data/attribute_classes/input.json index dea1c0fdd1..93f917d4d9 100644 --- a/code_generation/data/attribute_classes/input.json +++ b/code_generation/data/attribute_classes/input.json @@ -127,6 +127,55 @@ } ] }, + { + "name": "AsymLineInput", + "base": "BranchInput", + "attributes": [ + { + "data_type": "double", + "names": [ + "r_aa", + "r_ba", + "r_bb", + "r_ca", + "r_cb", + "r_cc", + "r_na", + "r_nb", + "r_nc", + "r_nn", + "x_aa", + "x_ba", + "x_bb", + "x_ca", + "x_cb", + "x_cc", + "x_na", + "x_nb", + "x_nc", + "x_nn", + "c_aa", + "c_ba", + "c_bb", + "c_ca", + "c_cb", + "c_cc", + "c_na", + "c_nb", + "c_nc", + "c_nn", + "c0", + "c1" + ], + "description": "Lower triangle matrix values for R, X and C matrices" + }, + { + "data_type": "double", + "names": "i_n", + "description": "rated current" + } + ] + }, { "name": "GenericBranchInput", "base": "BranchInput", diff --git a/code_generation/data/dataset_class_maps/dataset_definitions.json b/code_generation/data/dataset_class_maps/dataset_definitions.json index e4cb9073d2..78834d419b 100644 --- a/code_generation/data/dataset_class_maps/dataset_definitions.json +++ b/code_generation/data/dataset_class_maps/dataset_definitions.json @@ -12,6 +12,10 @@ "names": ["line"], "class_name": "LineInput" }, + { + "names": ["asym_line"], + "class_name": "AsymLineInput" + }, { "names": ["link"], "class_name": "LinkInput" @@ -67,7 +71,7 @@ "class_name": "NodeOutput" }, { - "names": ["line", "link", "transformer", "generic_branch"], + "names": ["line", "link", "transformer", "generic_branch", "asym_line"], "class_name": "BranchOutput" }, { @@ -108,6 +112,10 @@ "names": ["line"], "class_name": "BranchUpdate" }, + { + "names": ["asym_line"], + "class_name": "BranchUpdate" + }, { "names": ["link"], "class_name": "BranchUpdate" @@ -159,7 +167,7 @@ "class_name": "NodeShortCircuitOutput" }, { - "names": ["line", "link", "transformer"], + "names": ["line", "link", "transformer", "asym_line"], "class_name": "BranchShortCircuitOutput" }, { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/input.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/input.hpp index ec9eaed243..71d44ae0ad 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/input.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/input.hpp @@ -98,6 +98,55 @@ struct LineInput { operator BranchInput const&() const { return reinterpret_cast(*this); } }; +struct AsymLineInput { + ID id{na_IntID}; // ID of the object + ID from_node{na_IntID}; // node IDs to which this branch is connected at both sides + ID to_node{na_IntID}; // node IDs to which this branch is connected at both sides + IntS from_status{na_IntS}; // whether the branch is connected at each side + IntS to_status{na_IntS}; // whether the branch is connected at each side + double r_aa{nan}; // Lower triangle matrix values for R, X and C matrices + double r_ba{nan}; // Lower triangle matrix values for R, X and C matrices + double r_bb{nan}; // Lower triangle matrix values for R, X and C matrices + double r_ca{nan}; // Lower triangle matrix values for R, X and C matrices + double r_cb{nan}; // Lower triangle matrix values for R, X and C matrices + double r_cc{nan}; // Lower triangle matrix values for R, X and C matrices + double r_na{nan}; // Lower triangle matrix values for R, X and C matrices + double r_nb{nan}; // Lower triangle matrix values for R, X and C matrices + double r_nc{nan}; // Lower triangle matrix values for R, X and C matrices + double r_nn{nan}; // Lower triangle matrix values for R, X and C matrices + double x_aa{nan}; // Lower triangle matrix values for R, X and C matrices + double x_ba{nan}; // Lower triangle matrix values for R, X and C matrices + double x_bb{nan}; // Lower triangle matrix values for R, X and C matrices + double x_ca{nan}; // Lower triangle matrix values for R, X and C matrices + double x_cb{nan}; // Lower triangle matrix values for R, X and C matrices + double x_cc{nan}; // Lower triangle matrix values for R, X and C matrices + double x_na{nan}; // Lower triangle matrix values for R, X and C matrices + double x_nb{nan}; // Lower triangle matrix values for R, X and C matrices + double x_nc{nan}; // Lower triangle matrix values for R, X and C matrices + double x_nn{nan}; // Lower triangle matrix values for R, X and C matrices + double c_aa{nan}; // Lower triangle matrix values for R, X and C matrices + double c_ba{nan}; // Lower triangle matrix values for R, X and C matrices + double c_bb{nan}; // Lower triangle matrix values for R, X and C matrices + double c_ca{nan}; // Lower triangle matrix values for R, X and C matrices + double c_cb{nan}; // Lower triangle matrix values for R, X and C matrices + double c_cc{nan}; // Lower triangle matrix values for R, X and C matrices + double c_na{nan}; // Lower triangle matrix values for R, X and C matrices + double c_nb{nan}; // Lower triangle matrix values for R, X and C matrices + double c_nc{nan}; // Lower triangle matrix values for R, X and C matrices + double c_nn{nan}; // Lower triangle matrix values for R, X and C matrices + double c0{nan}; // Lower triangle matrix values for R, X and C matrices + double c1{nan}; // Lower triangle matrix values for R, X and C matrices + double i_n{nan}; // rated current + + // implicit conversions to BaseInput + operator BaseInput&() { return reinterpret_cast(*this); } + operator BaseInput const&() const { return reinterpret_cast(*this); } + + // implicit conversions to BranchInput + operator BranchInput&() { return reinterpret_cast(*this); } + operator BranchInput const&() const { return reinterpret_cast(*this); } +}; + struct GenericBranchInput { ID id{na_IntID}; // ID of the object ID from_node{na_IntID}; // node IDs to which this branch is connected at both sides diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/input.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/input.hpp index 7cca2754f8..ce86cc2a42 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/input.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/input.hpp @@ -111,6 +111,52 @@ struct get_attributes_list { }; }; +template<> +struct get_attributes_list { + static constexpr std::array value{ + // all attributes including base class + + meta_data_gen::get_meta_attribute<&AsymLineInput::id>(offsetof(AsymLineInput, id), "id"), + meta_data_gen::get_meta_attribute<&AsymLineInput::from_node>(offsetof(AsymLineInput, from_node), "from_node"), + meta_data_gen::get_meta_attribute<&AsymLineInput::to_node>(offsetof(AsymLineInput, to_node), "to_node"), + meta_data_gen::get_meta_attribute<&AsymLineInput::from_status>(offsetof(AsymLineInput, from_status), "from_status"), + meta_data_gen::get_meta_attribute<&AsymLineInput::to_status>(offsetof(AsymLineInput, to_status), "to_status"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_aa>(offsetof(AsymLineInput, r_aa), "r_aa"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_ba>(offsetof(AsymLineInput, r_ba), "r_ba"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_bb>(offsetof(AsymLineInput, r_bb), "r_bb"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_ca>(offsetof(AsymLineInput, r_ca), "r_ca"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_cb>(offsetof(AsymLineInput, r_cb), "r_cb"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_cc>(offsetof(AsymLineInput, r_cc), "r_cc"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_na>(offsetof(AsymLineInput, r_na), "r_na"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_nb>(offsetof(AsymLineInput, r_nb), "r_nb"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_nc>(offsetof(AsymLineInput, r_nc), "r_nc"), + meta_data_gen::get_meta_attribute<&AsymLineInput::r_nn>(offsetof(AsymLineInput, r_nn), "r_nn"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_aa>(offsetof(AsymLineInput, x_aa), "x_aa"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_ba>(offsetof(AsymLineInput, x_ba), "x_ba"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_bb>(offsetof(AsymLineInput, x_bb), "x_bb"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_ca>(offsetof(AsymLineInput, x_ca), "x_ca"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_cb>(offsetof(AsymLineInput, x_cb), "x_cb"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_cc>(offsetof(AsymLineInput, x_cc), "x_cc"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_na>(offsetof(AsymLineInput, x_na), "x_na"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_nb>(offsetof(AsymLineInput, x_nb), "x_nb"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_nc>(offsetof(AsymLineInput, x_nc), "x_nc"), + meta_data_gen::get_meta_attribute<&AsymLineInput::x_nn>(offsetof(AsymLineInput, x_nn), "x_nn"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_aa>(offsetof(AsymLineInput, c_aa), "c_aa"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_ba>(offsetof(AsymLineInput, c_ba), "c_ba"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_bb>(offsetof(AsymLineInput, c_bb), "c_bb"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_ca>(offsetof(AsymLineInput, c_ca), "c_ca"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_cb>(offsetof(AsymLineInput, c_cb), "c_cb"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_cc>(offsetof(AsymLineInput, c_cc), "c_cc"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_na>(offsetof(AsymLineInput, c_na), "c_na"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_nb>(offsetof(AsymLineInput, c_nb), "c_nb"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_nc>(offsetof(AsymLineInput, c_nc), "c_nc"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c_nn>(offsetof(AsymLineInput, c_nn), "c_nn"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c0>(offsetof(AsymLineInput, c0), "c0"), + meta_data_gen::get_meta_attribute<&AsymLineInput::c1>(offsetof(AsymLineInput, c1), "c1"), + meta_data_gen::get_meta_attribute<&AsymLineInput::i_n>(offsetof(AsymLineInput, i_n), "i_n"), + }; +}; + template<> struct get_attributes_list { static constexpr std::array value{ diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/input.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/input.hpp index ee2288a362..7e8e005854 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/input.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/input.hpp @@ -70,6 +70,25 @@ static_assert(offsetof(LineInput, to_node) == offsetof(BranchInput, to_node)); static_assert(offsetof(LineInput, from_status) == offsetof(BranchInput, from_status)); static_assert(offsetof(LineInput, to_status) == offsetof(BranchInput, to_status)); +// static asserts for AsymLineInput +static_assert(std::is_standard_layout_v); +// static asserts for conversion of AsymLineInput to BaseInput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(offsetof(AsymLineInput, id) == offsetof(BaseInput, id)); +// static asserts for conversion of AsymLineInput to BranchInput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(std::same_as); +static_assert(std::same_as); +static_assert(std::same_as); +static_assert(std::same_as); +static_assert(offsetof(AsymLineInput, id) == offsetof(BranchInput, id)); +static_assert(offsetof(AsymLineInput, from_node) == offsetof(BranchInput, from_node)); +static_assert(offsetof(AsymLineInput, to_node) == offsetof(BranchInput, to_node)); +static_assert(offsetof(AsymLineInput, from_status) == offsetof(BranchInput, from_status)); +static_assert(offsetof(AsymLineInput, to_status) == offsetof(BranchInput, to_status)); + // static asserts for GenericBranchInput static_assert(std::is_standard_layout_v); // static asserts for conversion of GenericBranchInput to BaseInput diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/common/common.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/common/common.hpp index 43c6d78ce3..b2ea72f0ca 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/common/common.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/common/common.hpp @@ -56,6 +56,7 @@ using DoubleComplex = std::complex; using std::numbers::inv_sqrt3; using std::numbers::pi; using std::numbers::sqrt3; +using std::numbers::e; constexpr DoubleComplex a2{-0.5, -sqrt3 / 2.0}; constexpr DoubleComplex a{-0.5, sqrt3 / 2.0}; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/common/exception.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/common/exception.hpp index 34c55f53c4..78b9ddf446 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/common/exception.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/common/exception.hpp @@ -59,6 +59,17 @@ class MissingCaseForEnumError : public InvalidArguments { } }; +class UnsupportedInputDescriptionAsymLine : public PowerGridError { + public: + UnsupportedInputDescriptionAsymLine() { + append_msg("Invalid or missing parameters supplied for component asym_line. The following input specifications are allowed"); + append_msg("3 phase x_matrix, 3 phase r_matrix and 3 phase c_matrix"); + append_msg("3 phase + neutral x_matrix, 3 phase + neutral r_matrix and 3 phase + neutral c_matrix"); + append_msg("3 phase x_matrix, 3 phase r_matrix and c1, c0"); + append_msg("3 phase + neutral x_matrix, 3 phase + neutral r_matrix and c1, c0"); + } +}; + class ConflictVoltage : public PowerGridError { public: ConflictVoltage(ID id, ID id1, ID id2, double u1, double u2) { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/common/three_phase_tensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/common/three_phase_tensor.hpp index 6523933eaa..5e87da3806 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/common/three_phase_tensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/common/three_phase_tensor.hpp @@ -22,6 +22,7 @@ namespace three_phase_tensor { template using Eigen3Vector = Eigen::Array; template using Eigen3Tensor = Eigen::Array; +template using Eigen4Tensor = Eigen::Array; template using Eigen3DiagonalTensor = Eigen::DiagonalMatrix; template class Vector : public Eigen3Vector { @@ -61,6 +62,8 @@ template class Tensor : public Eigen3Tensor { // additional constructors explicit Tensor(T const& x) { (*this) << x, 0.0, 0.0, 0.0, x, 0.0, 0.0, 0.0, x; } explicit Tensor(T const& s, T const& m) { (*this) << s, m, m, m, s, m, m, m, s; } + explicit Tensor(T const& x1, T const& x2, T const& x3, T const& x4, T const& x5, T const& x6) { (*this) << x1, x2, x4, x2, x3, x5, x4, x5, x6; } + explicit Tensor(T const& x1, T const& x2, T const& x3, T const& x4, T const& x5, T const& x6, T const& x7, T const& x8, T const& x9) { (*this) << x1, x2, x3, x4, x5, x6, x7, x8, x9; } explicit Tensor(Vector const& v) { (*this) << v(0), 0.0, 0.0, 0.0, v(1), 0.0, 0.0, 0.0, v(2); } // eigen expression template Tensor(Eigen::ArrayBase const& other) : Eigen3Tensor{other} {} @@ -70,6 +73,22 @@ template class Tensor : public Eigen3Tensor { } }; +template class Tensor4 : public Eigen4Tensor { + public: + Tensor4() { (*this) = Eigen4Tensor::Zero(); } + // additional constructors + explicit Tensor4(T const& x) { (*this) << x, 0.0, 0.0, 0.0, 0.0, x, 0.0, 0.0, 0.0, 0.0, x, 0.0, 0.0, 0.0, 0.0, x; } + explicit Tensor4(T const& s, T const& m) { (*this) << s, m, m, m, m, s, m, m, m, m, s, m, m, m, m, s; } + explicit Tensor4(T const& x1, T const& x2, T const& x3, T const& x4, T const& x5, T const& x6, T const& x7, T const& x8, T const& x9, T const& x10) { (*this) << x1, x2, x4, x7, x2, x3, x5, x8, x4, x5, x6, x9, x7, x8, x9, x10; } + explicit Tensor4(Vector const& v) { (*this) << v(0), 0.0, 0.0, 0.0, 0.0, v(1), 0.0, 0.0, 0.0, 0.0, v(2), 0.0, 0.0, 0.0, 0.0, v(3); } + // eigen expression + template Tensor4(Eigen::ArrayBase const& other) : Eigen4Tensor{other} {} + template Tensor4& operator=(Eigen::ArrayBase const& other) { + this->Eigen4Tensor::operator=(other); + return *this; + } +}; + template class DiagonalTensor : public Eigen3DiagonalTensor { public: DiagonalTensor() { (*this).setZero(); } @@ -92,6 +111,7 @@ template using RealTensor = std::conditional_t, double, three_phase_tensor::Tensor>; template using ComplexTensor = std::conditional_t, DoubleComplex, three_phase_tensor::Tensor>; +using ComplexTensor4 = three_phase_tensor::Tensor4; template using RealDiagonalTensor = std::conditional_t, double, three_phase_tensor::DiagonalTensor>; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/asym_line.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/asym_line.hpp new file mode 100644 index 0000000000..267ce577e8 --- /dev/null +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/asym_line.hpp @@ -0,0 +1,139 @@ +#pragma once + +#include + +#include +#include "branch.hpp" + +#include "../auxiliary/input.hpp" +#include "../auxiliary/output.hpp" +#include "../auxiliary/update.hpp" +#include "../calculation_parameters.hpp" +#include "../common/common.hpp" +#include "../common/three_phase_tensor.hpp" + +namespace power_grid_model { + +class AsymLine : public Branch { + public: + using InputType = AsymLineInput; + using UpdateType = BranchUpdate; + static constexpr char const* name = "asym_line"; + + explicit AsymLine(AsymLineInput const& asym_line_input, double system_frequency, double u1, double u2) + : Branch{asym_line_input}, i_n_{asym_line_input.i_n}, base_i_{base_power_3p / u1 / sqrt3} { + if (cabs(u1 - u2) > numerical_tolerance) { + throw ConflictVoltage{id(), from_node(), to_node(), u1, u2}; + } + + ComplexTensor c_matrix = compute_c_matrix_from_input(asym_line_input); + ComplexTensor z_series = compute_z_series_from_input(asym_line_input); + + ComplexTensor empty_tensor; + + if (c_matrix.isZero() || z_series.isZero()) { + throw UnsupportedInputDescriptionAsymLine(); + } + + y_series = inv(z_series); + y_shunt = 2 * pi * system_frequency * c_matrix * 1.0i; + } + + // override getter + double base_i_from() const override { return base_i_; } + double base_i_to() const override { return base_i_; } + double loading(double /* max_s */, double max_i) const override { return max_i / i_n_; }; + double phase_shift() const override { return 0.0; } + bool is_param_mutable() const override { return false; } + + private: + double i_n_; + double base_i_; + ComplexTensor y_series; + ComplexTensor y_shunt; + + ComplexTensor kron_reduction(const ComplexTensor4& matrix_to_reduce) const { + ComplexTensor4 Y = matrix_to_reduce; + ComplexTensor Y_aa = ComplexTensor(Y(0,0), Y(1,0), Y(1, 1), Y(2,0), Y(2,1), Y(2,2)); + ComplexValue Y_ab(Y(0,3), Y(1,3), Y(2,3)); + Eigen::Array Y_ba; + Y_ba << Y(3,0), Y(3,1), Y(3,2); + DoubleComplex Y_bb_inv = 1.0 / Y(3,3); + + return Y_aa - ((Y_ab * Y_bb_inv).matrix() * Y_ba.matrix()).array(); + } + + ComplexTensor compute_z_series_from_input(const power_grid_model::AsymLineInput& asym_line_input) { + ComplexTensor z_series_abc; + if (is_nan(asym_line_input.r_na) && is_nan(asym_line_input.x_na)) { + ComplexTensor r_matrix = ComplexTensor(asym_line_input.r_aa, asym_line_input.r_ba, asym_line_input.r_bb, asym_line_input.r_ca, asym_line_input.r_cb, asym_line_input.r_cc); + ComplexTensor x_matrix = ComplexTensor(asym_line_input.x_aa, asym_line_input.x_ba, asym_line_input.x_bb, asym_line_input.x_ca, asym_line_input.x_cb, asym_line_input.x_cc); + z_series_abc = r_matrix + x_matrix * 1.0i; + } + else { + ComplexTensor4 r_matrix = ComplexTensor4(asym_line_input.r_aa, asym_line_input.r_ba, asym_line_input.r_bb, asym_line_input.r_ca, asym_line_input.r_cb, asym_line_input.r_cc, asym_line_input.r_na, asym_line_input.r_nb, asym_line_input.r_nc, asym_line_input.r_nn); + ComplexTensor4 x_matrix = ComplexTensor4(asym_line_input.x_aa, asym_line_input.x_ba, asym_line_input.x_bb, asym_line_input.x_ca, asym_line_input.x_cb, asym_line_input.x_cc, asym_line_input.x_na, asym_line_input.x_nb, asym_line_input.x_nc, asym_line_input.x_nn); + + ComplexTensor4 y = r_matrix + 1.0i * x_matrix; + z_series_abc = kron_reduction(y); + } + DoubleComplex a = std::pow(e, 1.0i * (2.0 / 3.0) * pi); + ComplexTensor a_matrix = ComplexTensor(1, 1, pow(a, 2), 1, a, pow(a, 2)); + ComplexTensor a_matrix_inv = (1.0/3.0) * ComplexTensor(1, 1, a, 1, pow(a, 2), a); + ComplexTensor z_series = (a_matrix_inv.matrix() * z_series_abc.matrix() * a_matrix.matrix()).array(); + return z_series; + } + + ComplexTensor compute_c_matrix_from_input(const power_grid_model::AsymLineInput& asym_line_input) { + ComplexTensor c_matrix; + if (!is_nan(asym_line_input.c0) && !is_nan(asym_line_input.c1)) { + c_matrix = ComplexTensor(asym_line_input.c0 + asym_line_input.c1, -asym_line_input.c1); + } + else if (is_nan(asym_line_input.c_nn)) { + c_matrix = ComplexTensor(asym_line_input.c_aa, asym_line_input.c_ba, asym_line_input.c_bb, asym_line_input.c_ca, asym_line_input.c_cb, asym_line_input.c_cc); + } + else { + ComplexTensor4 c_matrix_neutral = ComplexTensor4(asym_line_input.c_aa, asym_line_input.c_ba, asym_line_input.c_bb, asym_line_input.c_ca, asym_line_input.c_cb, asym_line_input.c_cc, asym_line_input.c_na, asym_line_input.c_nb, asym_line_input.c_nc, asym_line_input.c_nn); + c_matrix = this->kron_reduction(c_matrix_neutral); + } + return c_matrix; + } + + DoubleComplex average_of_diagonal_of_matrix(const ComplexTensor &matrix) const { + return (matrix(0,0) + matrix(1,1) + matrix(2,2)) / 3.0; + } + + DoubleComplex average_of_off_diagonal_of_matrix(const ComplexTensor &matrix) const { + return (matrix(0,2) + matrix(1,1) + matrix(2,0)) / 3.0; + } + + BranchCalcParam sym_calc_param() const override { + DoubleComplex y1_series_ = average_of_diagonal_of_matrix(y_series) - average_of_off_diagonal_of_matrix(y_series); + DoubleComplex y1_shunt_ = average_of_diagonal_of_matrix(y_shunt) - average_of_off_diagonal_of_matrix(y_shunt); + return calc_param_y_sym(y1_series_, y1_shunt_, 1.0); + } + + BranchCalcParam asym_calc_param() const override { + BranchCalcParam param{}; + // not both connected + if (!branch_status()) { + // single connected + if (from_status() || to_status()) { + // branch_shunt = 0.5 * y_shunt + 1.0 / (1.0 / y_series + 2.0 / y_shunt); + ComplexTensor branch_shunt = 0.5 * inv(y_shunt) + inv(inv(y_series) + 2.0 * inv(y_shunt)); + // from or to connected + param.yff() = from_status() ? branch_shunt : ComplexTensor(); + param.ytt() = to_status() ? branch_shunt : ComplexTensor(); + } + } + // both connected + else { + param.ytt() = y_series + 0.5 * y_shunt; + param.yff() = param.ytt(); + param.yft() = y_series; + param.ytf() = y_series; + } + return param; + } +}; +} \ No newline at end of file diff --git a/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset_definitions.h b/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset_definitions.h index 3be340891e..2c47dc4fa1 100644 --- a/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset_definitions.h +++ b/power_grid_model_c/power_grid_model_c/include/power_grid_model_c/dataset_definitions.h @@ -47,6 +47,47 @@ PGM_API extern PGM_MetaAttribute const* const PGM_def_input_line_x0; PGM_API extern PGM_MetaAttribute const* const PGM_def_input_line_c0; PGM_API extern PGM_MetaAttribute const* const PGM_def_input_line_tan0; PGM_API extern PGM_MetaAttribute const* const PGM_def_input_line_i_n; +// component asym_line +PGM_API extern PGM_MetaComponent const* const PGM_def_input_asym_line; +// attributes of input asym_line +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_id; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_from_node; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_to_node; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_from_status; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_to_status; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_aa; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_ba; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_bb; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_ca; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_cb; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_cc; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_na; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_nb; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_nc; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_r_nn; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_aa; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_ba; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_bb; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_ca; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_cb; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_cc; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_na; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_nb; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_nc; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_x_nn; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_aa; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_ba; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_bb; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_ca; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_cb; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_cc; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_na; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_nb; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_nc; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c_nn; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c0; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_c1; +PGM_API extern PGM_MetaAttribute const* const PGM_def_input_asym_line_i_n; // component link PGM_API extern PGM_MetaComponent const* const PGM_def_input_link; // attributes of input link @@ -340,6 +381,20 @@ PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_generic_branch_ PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_generic_branch_q_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_generic_branch_i_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_generic_branch_s_to; +// component asym_line +PGM_API extern PGM_MetaComponent const* const PGM_def_sym_output_asym_line; +// attributes of sym_output asym_line +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_id; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_energized; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_loading; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_p_from; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_q_from; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_i_from; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_s_from; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_p_to; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_q_to; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_i_to; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_s_to; // component transformer_tap_regulator PGM_API extern PGM_MetaComponent const* const PGM_def_sym_output_transformer_tap_regulator; // attributes of sym_output transformer_tap_regulator @@ -526,6 +581,20 @@ PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_generic_branch PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_generic_branch_q_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_generic_branch_i_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_generic_branch_s_to; +// component asym_line +PGM_API extern PGM_MetaComponent const* const PGM_def_asym_output_asym_line; +// attributes of asym_output asym_line +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_id; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_energized; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_loading; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_p_from; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_q_from; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_i_from; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_s_from; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_p_to; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_q_to; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_i_to; +PGM_API extern PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_s_to; // component transformer_tap_regulator PGM_API extern PGM_MetaComponent const* const PGM_def_asym_output_transformer_tap_regulator; // attributes of asym_output transformer_tap_regulator @@ -656,6 +725,12 @@ PGM_API extern PGM_MetaComponent const* const PGM_def_update_line; PGM_API extern PGM_MetaAttribute const* const PGM_def_update_line_id; PGM_API extern PGM_MetaAttribute const* const PGM_def_update_line_from_status; PGM_API extern PGM_MetaAttribute const* const PGM_def_update_line_to_status; +// component asym_line +PGM_API extern PGM_MetaComponent const* const PGM_def_update_asym_line; +// attributes of update asym_line +PGM_API extern PGM_MetaAttribute const* const PGM_def_update_asym_line_id; +PGM_API extern PGM_MetaAttribute const* const PGM_def_update_asym_line_from_status; +PGM_API extern PGM_MetaAttribute const* const PGM_def_update_asym_line_to_status; // component link PGM_API extern PGM_MetaComponent const* const PGM_def_update_link; // attributes of update link @@ -806,6 +881,15 @@ PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_transformer_i_fr PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_transformer_i_from_angle; PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_transformer_i_to; PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_transformer_i_to_angle; +// component asym_line +PGM_API extern PGM_MetaComponent const* const PGM_def_sc_output_asym_line; +// attributes of sc_output asym_line +PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_id; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_energized; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_i_from; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_i_from_angle; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_i_to; +PGM_API extern PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_i_to_angle; // component three_winding_transformer PGM_API extern PGM_MetaComponent const* const PGM_def_sc_output_three_winding_transformer; // attributes of sc_output three_winding_transformer diff --git a/power_grid_model_c/power_grid_model_c/src/dataset_definitions.cpp b/power_grid_model_c/power_grid_model_c/src/dataset_definitions.cpp index 9639a97550..c7d309962e 100644 --- a/power_grid_model_c/power_grid_model_c/src/dataset_definitions.cpp +++ b/power_grid_model_c/power_grid_model_c/src/dataset_definitions.cpp @@ -36,6 +36,47 @@ PGM_MetaAttribute const* const PGM_def_input_line_x0 = PGM_meta_get_attribute_by PGM_MetaAttribute const* const PGM_def_input_line_c0 = PGM_meta_get_attribute_by_name(nullptr, "input", "line", "c0"); PGM_MetaAttribute const* const PGM_def_input_line_tan0 = PGM_meta_get_attribute_by_name(nullptr, "input", "line", "tan0"); PGM_MetaAttribute const* const PGM_def_input_line_i_n = PGM_meta_get_attribute_by_name(nullptr, "input", "line", "i_n"); +// component asym_line +PGM_MetaComponent const* const PGM_def_input_asym_line = PGM_meta_get_component_by_name(nullptr, "input", "asym_line"); +// attributes of input asym_line +PGM_MetaAttribute const* const PGM_def_input_asym_line_id = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "id"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_from_node = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "from_node"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_to_node = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "to_node"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_from_status = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "from_status"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_to_status = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "to_status"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_aa = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_aa"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_ba = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_ba"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_bb = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_bb"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_ca = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_ca"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_cb = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_cb"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_cc = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_cc"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_na = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_na"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_nb = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_nb"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_nc = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_nc"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_r_nn = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "r_nn"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_aa = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_aa"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_ba = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_ba"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_bb = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_bb"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_ca = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_ca"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_cb = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_cb"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_cc = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_cc"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_na = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_na"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_nb = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_nb"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_nc = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_nc"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_x_nn = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "x_nn"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_aa = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_aa"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_ba = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_ba"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_bb = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_bb"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_ca = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_ca"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_cb = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_cb"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_cc = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_cc"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_na = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_na"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_nb = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_nb"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_nc = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_nc"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c_nn = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c_nn"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c0 = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c0"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_c1 = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "c1"); +PGM_MetaAttribute const* const PGM_def_input_asym_line_i_n = PGM_meta_get_attribute_by_name(nullptr, "input", "asym_line", "i_n"); // component link PGM_MetaComponent const* const PGM_def_input_link = PGM_meta_get_component_by_name(nullptr, "input", "link"); // attributes of input link @@ -329,6 +370,20 @@ PGM_MetaAttribute const* const PGM_def_sym_output_generic_branch_p_to = PGM_meta PGM_MetaAttribute const* const PGM_def_sym_output_generic_branch_q_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "generic_branch", "q_to"); PGM_MetaAttribute const* const PGM_def_sym_output_generic_branch_i_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "generic_branch", "i_to"); PGM_MetaAttribute const* const PGM_def_sym_output_generic_branch_s_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "generic_branch", "s_to"); +// component asym_line +PGM_MetaComponent const* const PGM_def_sym_output_asym_line = PGM_meta_get_component_by_name(nullptr, "sym_output", "asym_line"); +// attributes of sym_output asym_line +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_id = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "id"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_energized = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "energized"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_loading = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "loading"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_p_from = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "p_from"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_q_from = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "q_from"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_i_from = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "i_from"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_s_from = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "s_from"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_p_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "p_to"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_q_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "q_to"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_i_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "i_to"); +PGM_MetaAttribute const* const PGM_def_sym_output_asym_line_s_to = PGM_meta_get_attribute_by_name(nullptr, "sym_output", "asym_line", "s_to"); // component transformer_tap_regulator PGM_MetaComponent const* const PGM_def_sym_output_transformer_tap_regulator = PGM_meta_get_component_by_name(nullptr, "sym_output", "transformer_tap_regulator"); // attributes of sym_output transformer_tap_regulator @@ -515,6 +570,20 @@ PGM_MetaAttribute const* const PGM_def_asym_output_generic_branch_p_to = PGM_met PGM_MetaAttribute const* const PGM_def_asym_output_generic_branch_q_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "generic_branch", "q_to"); PGM_MetaAttribute const* const PGM_def_asym_output_generic_branch_i_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "generic_branch", "i_to"); PGM_MetaAttribute const* const PGM_def_asym_output_generic_branch_s_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "generic_branch", "s_to"); +// component asym_line +PGM_MetaComponent const* const PGM_def_asym_output_asym_line = PGM_meta_get_component_by_name(nullptr, "asym_output", "asym_line"); +// attributes of asym_output asym_line +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_id = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "id"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_energized = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "energized"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_loading = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "loading"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_p_from = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "p_from"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_q_from = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "q_from"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_i_from = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "i_from"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_s_from = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "s_from"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_p_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "p_to"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_q_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "q_to"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_i_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "i_to"); +PGM_MetaAttribute const* const PGM_def_asym_output_asym_line_s_to = PGM_meta_get_attribute_by_name(nullptr, "asym_output", "asym_line", "s_to"); // component transformer_tap_regulator PGM_MetaComponent const* const PGM_def_asym_output_transformer_tap_regulator = PGM_meta_get_component_by_name(nullptr, "asym_output", "transformer_tap_regulator"); // attributes of asym_output transformer_tap_regulator @@ -645,6 +714,12 @@ PGM_MetaComponent const* const PGM_def_update_line = PGM_meta_get_component_by_n PGM_MetaAttribute const* const PGM_def_update_line_id = PGM_meta_get_attribute_by_name(nullptr, "update", "line", "id"); PGM_MetaAttribute const* const PGM_def_update_line_from_status = PGM_meta_get_attribute_by_name(nullptr, "update", "line", "from_status"); PGM_MetaAttribute const* const PGM_def_update_line_to_status = PGM_meta_get_attribute_by_name(nullptr, "update", "line", "to_status"); +// component asym_line +PGM_MetaComponent const* const PGM_def_update_asym_line = PGM_meta_get_component_by_name(nullptr, "update", "asym_line"); +// attributes of update asym_line +PGM_MetaAttribute const* const PGM_def_update_asym_line_id = PGM_meta_get_attribute_by_name(nullptr, "update", "asym_line", "id"); +PGM_MetaAttribute const* const PGM_def_update_asym_line_from_status = PGM_meta_get_attribute_by_name(nullptr, "update", "asym_line", "from_status"); +PGM_MetaAttribute const* const PGM_def_update_asym_line_to_status = PGM_meta_get_attribute_by_name(nullptr, "update", "asym_line", "to_status"); // component link PGM_MetaComponent const* const PGM_def_update_link = PGM_meta_get_component_by_name(nullptr, "update", "link"); // attributes of update link @@ -795,6 +870,15 @@ PGM_MetaAttribute const* const PGM_def_sc_output_transformer_i_from = PGM_meta_g PGM_MetaAttribute const* const PGM_def_sc_output_transformer_i_from_angle = PGM_meta_get_attribute_by_name(nullptr, "sc_output", "transformer", "i_from_angle"); PGM_MetaAttribute const* const PGM_def_sc_output_transformer_i_to = PGM_meta_get_attribute_by_name(nullptr, "sc_output", "transformer", "i_to"); PGM_MetaAttribute const* const PGM_def_sc_output_transformer_i_to_angle = PGM_meta_get_attribute_by_name(nullptr, "sc_output", "transformer", "i_to_angle"); +// component asym_line +PGM_MetaComponent const* const PGM_def_sc_output_asym_line = PGM_meta_get_component_by_name(nullptr, "sc_output", "asym_line"); +// attributes of sc_output asym_line +PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_id = PGM_meta_get_attribute_by_name(nullptr, "sc_output", "asym_line", "id"); +PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_energized = PGM_meta_get_attribute_by_name(nullptr, "sc_output", "asym_line", "energized"); +PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_i_from = PGM_meta_get_attribute_by_name(nullptr, "sc_output", "asym_line", "i_from"); +PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_i_from_angle = PGM_meta_get_attribute_by_name(nullptr, "sc_output", "asym_line", "i_from_angle"); +PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_i_to = PGM_meta_get_attribute_by_name(nullptr, "sc_output", "asym_line", "i_to"); +PGM_MetaAttribute const* const PGM_def_sc_output_asym_line_i_to_angle = PGM_meta_get_attribute_by_name(nullptr, "sc_output", "asym_line", "i_to_angle"); // component three_winding_transformer PGM_MetaComponent const* const PGM_def_sc_output_three_winding_transformer = PGM_meta_get_component_by_name(nullptr, "sc_output", "three_winding_transformer"); // attributes of sc_output three_winding_transformer diff --git a/src/power_grid_model/core/dataset_definitions.py b/src/power_grid_model/core/dataset_definitions.py index d8f8031b85..623aa46a80 100644 --- a/src/power_grid_model/core/dataset_definitions.py +++ b/src/power_grid_model/core/dataset_definitions.py @@ -56,6 +56,7 @@ class ComponentType(str, Enum, metaclass=_MetaEnum): node = "node" line = "line" + asym_line = "asym_line" link = "link" generic_branch = "generic_branch" transformer = "transformer" diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt index bcadaa2223..46e573cfed 100644 --- a/tests/cpp_unit_tests/CMakeLists.txt +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -13,6 +13,7 @@ set(PROJECT_SOURCES "test_component_update.cpp" "test_three_phase_tensor.cpp" "test_node.cpp" + "test_asym_line.cpp" "test_line.cpp" "test_generic_branch.cpp" "test_link.cpp" diff --git a/tests/cpp_unit_tests/test_asym_line.cpp b/tests/cpp_unit_tests/test_asym_line.cpp new file mode 100644 index 0000000000..6cfa8f63f7 --- /dev/null +++ b/tests/cpp_unit_tests/test_asym_line.cpp @@ -0,0 +1,157 @@ +// SPDX-FileCopyrightText: Contributors to the Power Grid Model project +// +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include + +namespace power_grid_model { + +using namespace std::complex_literals; + +TEST_CASE("Test asym line") { + double system_frequency = 50.0; + AsymLineInput const input{.id = 1, + .from_node = 2, + .to_node = 3, + .from_status = 1, + .to_status = 1, + .r_aa = 0.4369, + .r_ba = 0.0496, + .r_bb = 0.4369, + .r_ca = 0.0485, + .r_cb = 0.0496, + .r_cc = 0.4369, + .r_na = 0.0496, + .r_nb = 0.0485, + .r_nc = 0.0496, + .r_nn = 0.4369, + .x_aa = 0.8538, + .x_ba = 0.7886, + .x_bb = 0.8538, + .x_ca = 0.7663, + .x_cb = 0.7886, + .x_cc = 0.8538, + .x_na = 0.7886, + .x_nb = 0.7663, + .x_nc = 0.7886, + .x_nn = 0.8538, + .c0 = 0.18, + .c1 = 0.308, + .i_n = 216.0}; + AsymLine asym_line{input, system_frequency, 10.0e3, 10.0e3}; + double const base_i = base_power_1p / (10.0e3 / sqrt3); + double const base_y = base_i * base_i / base_power_1p; + Branch& branch = asym_line; + ComplexTensor const y_series = ComplexTensor(0.66303418-0.34266364i, -0.02971114+0.03783535i, 0.04762194+0.00681293i, 0.04762194+0.00681293i, 2.48612768-0.46271628i, 0.05942228-0.07567069i, -0.02971114+0.03783535i, -0.09524388-0.01362585i, 2.48612768-0.46271628i); + + ComplexTensor const y_shunt = 2 * pi * system_frequency * ComplexTensor(input.c0 + input.c1, -input.c1) * 1.0i; + + DoubleComplex const y1_series = (y_series(0,0) + y_series(1,1) + y_series(2,2)) / 3.0 - (y_series(0,2) + y_series(1,1) + y_series(2,0)) / 3.0; + DoubleComplex const y1_shunt = (y_shunt(0,0) + y_shunt(1,1) + y_shunt(2,2)) / 3.0 - (y_shunt(0,2) + y_shunt(1,1) + y_shunt(2,0)) / 3.0; + + // symmetric + DoubleComplex const yff1 = y1_series + 0.5 * y1_shunt; + DoubleComplex const yft1 = -y1_series; + DoubleComplex const ys1 = 0.5 * y1_shunt + 1.0 / (1.0 / y1_series + 2.0 / y1_shunt); + + // asymmetric + ComplexTensor ytt = y_series + 0.5 * y_shunt; + DoubleComplex const yff0 = ytt(0,0); + DoubleComplex const yft0 = -y_series(0,0); + DoubleComplex const ys0 = 0.5 * y_shunt(0,0) + 1.0 / (1.0 / y_series(0,0) + 2.0 / y_shunt(0,0)); + ComplexTensor const yffa{(2.0 * yff1 + yff0) / 3.0, (yff0 - yff1) / 3.0}; + ComplexTensor const yfta{(2.0 * yft1 + yft0) / 3.0, (yft0 - yft1) / 3.0}; + ComplexTensor const ysa{(2.0 * ys1 + ys0) / 3.0, (ys0 - ys1) / 3.0}; + + DoubleComplex const u1f = 1.0; + DoubleComplex const u1t = 0.9; + ComplexValue const uaf{1.0}; + ComplexValue const uat{0.9}; + DoubleComplex const i1f = (yff1 * u1f + yft1 * u1t) * base_i; + DoubleComplex const i1t = (yft1 * u1f + yff1 * u1t) * base_i; + DoubleComplex const s_f = conj(i1f) * u1f * 10e3 * sqrt3; + DoubleComplex const s_t = conj(i1t) * u1t * 10e3 * sqrt3; + double const loading = std::max(cabs(i1f), cabs(i1t)) / 200.0; + + // Short circuit results + DoubleComplex const if_sc{1.0, 1.0}; + DoubleComplex const it_sc{2.0, 2.0 * sqrt(3)}; + ComplexValue const if_sc_asym{1.0 + 1.0i}; + ComplexValue const it_sc_asym{2.0 + (2.0i * sqrt(3))}; + + CHECK(asym_line.math_model_type() == ComponentType::branch); + + SUBCASE("Voltge error") { CHECK_THROWS_AS(AsymLine(input, 50.0, 10.0e3, 50.0e3), ConflictVoltage); } + + SUBCASE("General") { + CHECK(branch.from_node() == 2); + CHECK(branch.to_node() == 3); + CHECK(branch.from_status() == true); + CHECK(branch.to_status() == true); + CHECK(branch.branch_status() == true); + CHECK(branch.status(BranchSide::from) == branch.from_status()); + CHECK(branch.status(BranchSide::to) == branch.to_status()); + CHECK(branch.base_i_from() == doctest::Approx(base_i)); + CHECK(branch.base_i_to() == doctest::Approx(base_i)); + CHECK(branch.phase_shift() == 0.0); + CHECK(!branch.is_param_mutable()); + } + + SUBCASE("Symmetric parameters") { + // double connected + BranchCalcParam param = branch.calc_param(); + CHECK(cabs(param.yff() - yff1) < numerical_tolerance); + CHECK(cabs(param.ytt() - yff1) < numerical_tolerance); + CHECK(cabs(param.ytf() - yft1) < numerical_tolerance); + CHECK(cabs(param.yft() - yft1) < numerical_tolerance); + // to connected + CHECK(branch.update(BranchUpdate{1, false, na_IntS}).topo); + param = branch.calc_param(); + CHECK(cabs(param.yff() - 0.0) < numerical_tolerance); + CHECK(cabs(param.ytt() - ys1) < numerical_tolerance); + CHECK(cabs(param.ytf() - 0.0) < numerical_tolerance); + CHECK(cabs(param.yft() - 0.0) < numerical_tolerance); + // not connected + CHECK(branch.set_status(na_IntS, false)); + param = branch.calc_param(); + CHECK(cabs(param.yff() - 0.0) < numerical_tolerance); + CHECK(cabs(param.ytt() - 0.0) < numerical_tolerance); + CHECK(cabs(param.ytf() - 0.0) < numerical_tolerance); + CHECK(cabs(param.yft() - 0.0) < numerical_tolerance); + // not changing + CHECK(!branch.set_status(false, false)); + // from connected + CHECK(branch.set_status(true, na_IntS)); + param = branch.calc_param(); + CHECK(cabs(param.yff() - ys1) < numerical_tolerance); + CHECK(cabs(param.ytt() - 0.0) < numerical_tolerance); + CHECK(cabs(param.ytf() - 0.0) < numerical_tolerance); + CHECK(cabs(param.yft() - 0.0) < numerical_tolerance); + } + + SUBCASE("Asymmetric parameters") { + // double connected + BranchCalcParam param = asym_line.calc_param(); + CHECK((cabs(param.yff() - yffa) < numerical_tolerance).all()); + CHECK((cabs(param.ytt() - yffa) < numerical_tolerance).all()); + CHECK((cabs(param.ytf() - yfta) < numerical_tolerance).all()); + CHECK((cabs(param.yft() - yfta) < numerical_tolerance).all()); + // no source + param = branch.calc_param(false); + CHECK((cabs(param.yff() - 0.0) < numerical_tolerance).all()); + CHECK((cabs(param.ytt() - 0.0) < numerical_tolerance).all()); + CHECK((cabs(param.ytf() - 0.0) < numerical_tolerance).all()); + CHECK((cabs(param.yft() - 0.0) < numerical_tolerance).all()); + // from connected + CHECK(branch.set_status(na_IntS, false)); + param = asym_line.calc_param(); + CHECK((cabs(param.yff() - ysa) < numerical_tolerance).all()); + CHECK((cabs(param.ytt() - 0.0) < numerical_tolerance).all()); + CHECK((cabs(param.ytf() - 0.0) < numerical_tolerance).all()); + CHECK((cabs(param.yft() - 0.0) < numerical_tolerance).all()); + } +} + +} // namespace power_grid_model \ No newline at end of file