Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Implementation of feature 720 asym_line #762

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions code_generation/data/attribute_classes/input.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
TonyXiang8787 marked this conversation as resolved.
Show resolved Hide resolved
"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",
Expand Down
12 changes: 10 additions & 2 deletions code_generation/data/dataset_class_maps/dataset_definitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"names": ["line"],
"class_name": "LineInput"
},
{
"names": ["asym_line"],
"class_name": "AsymLineInput"
},
{
"names": ["link"],
"class_name": "LinkInput"
Expand Down Expand Up @@ -67,7 +71,7 @@
"class_name": "NodeOutput"
},
{
"names": ["line", "link", "transformer", "generic_branch"],
"names": ["line", "link", "transformer", "generic_branch", "asym_line"],
"class_name": "BranchOutput"
},
{
Expand Down Expand Up @@ -108,6 +112,10 @@
"names": ["line"],
"class_name": "BranchUpdate"
},
{
"names": ["asym_line"],
"class_name": "BranchUpdate"
},
{
"names": ["link"],
"class_name": "BranchUpdate"
Expand Down Expand Up @@ -159,7 +167,7 @@
"class_name": "NodeShortCircuitOutput"
},
{
"names": ["line", "link", "transformer"],
"names": ["line", "link", "transformer", "asym_line"],
"class_name": "BranchShortCircuitOutput"
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "component/fault.hpp"
#include "component/generic_branch.hpp"
#include "component/line.hpp"
#include "component/asym_line.hpp"
#include "component/link.hpp"
#include "component/load_gen.hpp"
#include "component/node.hpp"
Expand All @@ -27,7 +28,7 @@
namespace power_grid_model {

using AllComponents =
ComponentList<Node, Line, Link, GenericBranch, Transformer, ThreeWindingTransformer, Shunt, Source, SymGenerator,
ComponentList<Node, Line, AsymLine, Link, GenericBranch, Transformer, ThreeWindingTransformer, Shunt, Source, SymGenerator,
AsymGenerator, SymLoad, AsymLoad, SymPowerSensor, AsymPowerSensor, SymVoltageSensor,
AsymVoltageSensor, Fault, TransformerTapRegulator>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,55 @@ struct LineInput {
operator BranchInput const&() const { return reinterpret_cast<BranchInput const&>(*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<BaseInput&>(*this); }
operator BaseInput const&() const { return reinterpret_cast<BaseInput const&>(*this); }

// implicit conversions to BranchInput
operator BranchInput&() { return reinterpret_cast<BranchInput&>(*this); }
operator BranchInput const&() const { return reinterpret_cast<BranchInput const&>(*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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,52 @@ struct get_attributes_list<LineInput> {
};
};

template<>
struct get_attributes_list<AsymLineInput> {
static constexpr std::array<MetaAttribute, 38> 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<GenericBranchInput> {
static constexpr std::array<MetaAttribute, 12> value{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<AsymLineInput>);
// static asserts for conversion of AsymLineInput to BaseInput
static_assert(std::alignment_of_v<AsymLineInput> >= std::alignment_of_v<BranchInput>);
static_assert(std::same_as<decltype(AsymLineInput::id), decltype(BaseInput::id)>);
static_assert(offsetof(AsymLineInput, id) == offsetof(BaseInput, id));
// static asserts for conversion of AsymLineInput to BranchInput
static_assert(std::alignment_of_v<AsymLineInput> >= std::alignment_of_v<BranchInput>);
static_assert(std::same_as<decltype(AsymLineInput::id), decltype(BranchInput::id)>);
static_assert(std::same_as<decltype(AsymLineInput::from_node), decltype(BranchInput::from_node)>);
static_assert(std::same_as<decltype(AsymLineInput::to_node), decltype(BranchInput::to_node)>);
static_assert(std::same_as<decltype(AsymLineInput::from_status), decltype(BranchInput::from_status)>);
static_assert(std::same_as<decltype(AsymLineInput::to_status), decltype(BranchInput::to_status)>);
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<GenericBranchInput>);
// static asserts for conversion of GenericBranchInput to BaseInput
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ using DoubleComplex = std::complex<double>;
using std::numbers::inv_sqrt3;
using std::numbers::pi;
using std::numbers::sqrt3;
using std::numbers::e;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with this being in the full namespace of this project, i'm a little bit hesitant to add single-letter names here. let's think about whether this is the way to go or whether it's preferable to just use std::numbers::e where it's used (since it's not that common in the code base anyways). alternatively, we can put them all in a power_grid_model::numbers namespace and expose only the longer ones outside.

namespace numbers {
using std::numbers::inv_sqrt3;
using std::numbers::pi;
using std::numbers::sqrt3;
using std::numbers::e;
} // namespace numbers

using numbers::inv_sqrt3;
using numbers::pi;
using numbers::sqrt3;


constexpr DoubleComplex a2{-0.5, -sqrt3 / 2.0};
constexpr DoubleComplex a{-0.5, sqrt3 / 2.0};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
};
Comment on lines +62 to +71
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think we explicitly check input parameters in any of the other components. only things like ID references to other components are checked. I would just consider this UB (undefined behavior; in this case in particular unspecified behavior). The data validator in Python can check that it is supported, but the core should not.


class ConflictVoltage : public PowerGridError {
public:
ConflictVoltage(ID id, ID id1, ID id2, double u1, double u2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace three_phase_tensor {

template <class T> using Eigen3Vector = Eigen::Array<T, 3, 1>;
template <class T> using Eigen3Tensor = Eigen::Array<T, 3, 3, Eigen::ColMajor>;
template <class T> using Eigen4Tensor = Eigen::Array<T, 4, 4, Eigen::ColMajor>;
template <class T> using Eigen3DiagonalTensor = Eigen::DiagonalMatrix<T, 3>;

template <scalar_value T> class Vector : public Eigen3Vector<T> {
Expand Down Expand Up @@ -61,6 +62,8 @@ template <scalar_value T> class Tensor : public Eigen3Tensor<T> {
// 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; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd go for something more explicit. It's very easy to make a mistake in the order.

A proposal is the one below (BEWARE: this changes the order, so usage needs to be adjusted)

Suggested change
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& s1, T const& s2, T const& s3, T const& m12, T const& m13, T const& m23) { (*this) << s1, m12, m13, m12, s2, m23, m13, m23, s3; }

alternatively, you can provide 2 Vector<T> as input for readability

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<T> const& v) { (*this) << v(0), 0.0, 0.0, 0.0, v(1), 0.0, 0.0, 0.0, v(2); }
// eigen expression
template <typename OtherDerived> Tensor(Eigen::ArrayBase<OtherDerived> const& other) : Eigen3Tensor<T>{other} {}
Expand All @@ -70,6 +73,22 @@ template <scalar_value T> class Tensor : public Eigen3Tensor<T> {
}
};

template <scalar_value T> class Tensor4 : public Eigen4Tensor<T> {
public:
Tensor4() { (*this) = Eigen4Tensor<T>::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; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idem to my comment on Tensor3

explicit Tensor4(Vector<T> 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 <typename OtherDerived> Tensor4(Eigen::ArrayBase<OtherDerived> const& other) : Eigen4Tensor<T>{other} {}
template <typename OtherDerived> Tensor4& operator=(Eigen::ArrayBase<OtherDerived> const& other) {
this->Eigen4Tensor<T>::operator=(other);
return *this;
}
};

template <scalar_value T> class DiagonalTensor : public Eigen3DiagonalTensor<T> {
public:
DiagonalTensor() { (*this).setZero(); }
Expand All @@ -92,6 +111,7 @@ template <symmetry_tag sym>
using RealTensor = std::conditional_t<is_symmetric_v<sym>, double, three_phase_tensor::Tensor<double>>;
template <symmetry_tag sym>
using ComplexTensor = std::conditional_t<is_symmetric_v<sym>, DoubleComplex, three_phase_tensor::Tensor<DoubleComplex>>;
using ComplexTensor4 = three_phase_tensor::Tensor4<DoubleComplex>;

template <symmetry_tag sym>
using RealDiagonalTensor = std::conditional_t<is_symmetric_v<sym>, double, three_phase_tensor::DiagonalTensor<double>>;
Expand Down
Loading
Loading