From 66ce29b0c65216f3c454d29c3022e3015604a458 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 24 Dec 2024 14:34:02 +0100 Subject: [PATCH 01/38] angle measurement type enum Signed-off-by: petersalemink95 --- .../include/power_grid_model/common/enum.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/common/enum.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/common/enum.hpp index a75961c74..f8a7bd5d0 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/common/enum.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/common/enum.hpp @@ -126,4 +126,9 @@ enum class SearchMethod : IntS { // Which type of tap search method for finite e binary_search = 1, // use binary search: half a tap range at a time }; +enum class AngleMeasurementType : IntS { // The type of the angle measurement for current sensors + local = 0, // local = 0, the angle is relative to the local voltage angle + global = 1, // global = 1, the angle is relative to the global voltage angle +}; + } // namespace power_grid_model From 411f160a9b30ec7e506b9fed0113f72bf99dff33 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 24 Dec 2024 14:54:04 +0100 Subject: [PATCH 02/38] current sensor input Signed-off-by: petersalemink95 --- .../data/attribute_classes/input.json | 34 ++++++ .../power_grid_model/auxiliary/input.hpp | 44 +++++++ .../auxiliary/meta_gen/input.hpp | 30 +++++ .../auxiliary/static_asserts/input.hpp | 110 ++++++++++++++++++ 4 files changed, 218 insertions(+) diff --git a/code_generation/data/attribute_classes/input.json b/code_generation/data/attribute_classes/input.json index dea1c0fdd..141115ddb 100644 --- a/code_generation/data/attribute_classes/input.json +++ b/code_generation/data/attribute_classes/input.json @@ -494,6 +494,40 @@ "description": "line drop compensation reactance" } ] + }, + { + "name": "GenericCurrentSensorInput", + "base": "SensorInput", + "attributes": [ + { + "data_type": "AngleMeasurementType", + "names": "angle_measurement_type", + "description": "type of angle measurement" + }, + { + "data_type": "double", + "names": [ + "i_sigma", + "i_angle_sigma" + ], + "description": "sigma of error margin of apparent power measurement" + } + ] + }, + { + "name": "CurrentSensorInput", + "base": "GenericCurrentSensorInput", + "is_template": true, + "attributes": [ + { + "data_type": "RealValue", + "names": [ + "i_measured", + "i_angle_measured" + ], + "description": "measured current and current angle" + } + ] } ] } \ No newline at end of file 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 ec9eaed24..87c7a7d4e 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 @@ -444,6 +444,50 @@ struct TransformerTapRegulatorInput { operator RegulatorInput const&() const { return reinterpret_cast(*this); } }; +struct GenericCurrentSensorInput { + ID id{na_IntID}; // ID of the object + ID measured_object{na_IntID}; // ID of the measured object + AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement + double i_sigma{nan}; // sigma of error margin of apparent power measurement + double i_angle_sigma{nan}; // sigma of error margin of apparent power measurement + + // implicit conversions to BaseInput + operator BaseInput&() { return reinterpret_cast(*this); } + operator BaseInput const&() const { return reinterpret_cast(*this); } + + // implicit conversions to SensorInput + operator SensorInput&() { return reinterpret_cast(*this); } + operator SensorInput const&() const { return reinterpret_cast(*this); } +}; + +template +struct CurrentSensorInput { + using sym = sym_type; + + ID id{na_IntID}; // ID of the object + ID measured_object{na_IntID}; // ID of the measured object + AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement + double i_sigma{nan}; // sigma of error margin of apparent power measurement + double i_angle_sigma{nan}; // sigma of error margin of apparent power measurement + RealValue i_measured{nan}; // measured current and current angle + RealValue i_angle_measured{nan}; // measured current and current angle + + // implicit conversions to BaseInput + operator BaseInput&() { return reinterpret_cast(*this); } + operator BaseInput const&() const { return reinterpret_cast(*this); } + + // implicit conversions to SensorInput + operator SensorInput&() { return reinterpret_cast(*this); } + operator SensorInput const&() const { return reinterpret_cast(*this); } + + // implicit conversions to GenericCurrentSensorInput + operator GenericCurrentSensorInput&() { return reinterpret_cast(*this); } + operator GenericCurrentSensorInput const&() const { return reinterpret_cast(*this); } +}; + +using SymCurrentSensorInput = CurrentSensorInput; +using AsymCurrentSensorInput = CurrentSensorInput; + } // namespace power_grid_model 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 7cca2754f..f20333f27 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 @@ -396,6 +396,36 @@ 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<&GenericCurrentSensorInput::id>(offsetof(GenericCurrentSensorInput, id), "id"), + meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::measured_object>(offsetof(GenericCurrentSensorInput, measured_object), "measured_object"), + meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::angle_measurement_type>(offsetof(GenericCurrentSensorInput, angle_measurement_type), "angle_measurement_type"), + meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::i_sigma>(offsetof(GenericCurrentSensorInput, i_sigma), "i_sigma"), + meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::i_angle_sigma>(offsetof(GenericCurrentSensorInput, i_angle_sigma), "i_angle_sigma"), + }; +}; + +template +struct get_attributes_list> { + using sym = sym_type; + + static constexpr std::array value{ + // all attributes including base class + + meta_data_gen::get_meta_attribute<&CurrentSensorInput::id>(offsetof(CurrentSensorInput, id), "id"), + meta_data_gen::get_meta_attribute<&CurrentSensorInput::measured_object>(offsetof(CurrentSensorInput, measured_object), "measured_object"), + meta_data_gen::get_meta_attribute<&CurrentSensorInput::angle_measurement_type>(offsetof(CurrentSensorInput, angle_measurement_type), "angle_measurement_type"), + meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_sigma>(offsetof(CurrentSensorInput, i_sigma), "i_sigma"), + meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_angle_sigma>(offsetof(CurrentSensorInput, i_angle_sigma), "i_angle_sigma"), + meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_measured>(offsetof(CurrentSensorInput, i_measured), "i_measured"), + meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_angle_measured>(offsetof(CurrentSensorInput, i_angle_measured), "i_angle_measured"), + }; +}; + 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 ee2288a36..5c2334794 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 @@ -517,6 +517,116 @@ static_assert(offsetof(TransformerTapRegulatorInput, id) == offsetof(RegulatorIn static_assert(offsetof(TransformerTapRegulatorInput, regulated_object) == offsetof(RegulatorInput, regulated_object)); static_assert(offsetof(TransformerTapRegulatorInput, status) == offsetof(RegulatorInput, status)); +// static asserts for GenericCurrentSensorInput +static_assert(std::is_standard_layout_v); +// static asserts for conversion of GenericCurrentSensorInput to BaseInput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(offsetof(GenericCurrentSensorInput, id) == offsetof(BaseInput, id)); +// static asserts for conversion of GenericCurrentSensorInput to SensorInput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(std::same_as); +static_assert(offsetof(GenericCurrentSensorInput, id) == offsetof(SensorInput, id)); +static_assert(offsetof(GenericCurrentSensorInput, measured_object) == offsetof(SensorInput, measured_object)); + +// static asserts for CurrentSensorInput +static_assert(std::is_standard_layout_v>); +// static asserts for conversion of CurrentSensorInput to BaseInput +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(BaseInput::id)>); +static_assert(offsetof(CurrentSensorInput, id) == offsetof(BaseInput, id)); +// static asserts for conversion of CurrentSensorInput to SensorInput +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(SensorInput::id)>); +static_assert(std::same_as::measured_object), decltype(SensorInput::measured_object)>); +static_assert(offsetof(CurrentSensorInput, id) == offsetof(SensorInput, id)); +static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(SensorInput, measured_object)); +// static asserts for conversion of CurrentSensorInput to GenericCurrentSensorInput +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(GenericCurrentSensorInput::id)>); +static_assert(std::same_as::measured_object), decltype(GenericCurrentSensorInput::measured_object)>); +static_assert(std::same_as::angle_measurement_type), decltype(GenericCurrentSensorInput::angle_measurement_type)>); +static_assert(std::same_as::i_sigma), decltype(GenericCurrentSensorInput::i_sigma)>); +static_assert(std::same_as::i_angle_sigma), decltype(GenericCurrentSensorInput::i_angle_sigma)>); +static_assert(offsetof(CurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); +static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); +static_assert(offsetof(CurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); +static_assert(offsetof(CurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); +static_assert(offsetof(CurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); +// static asserts for CurrentSensorInput +static_assert(std::is_standard_layout_v>); +// static asserts for conversion of CurrentSensorInput to BaseInput +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(BaseInput::id)>); +static_assert(offsetof(CurrentSensorInput, id) == offsetof(BaseInput, id)); +// static asserts for conversion of CurrentSensorInput to SensorInput +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(SensorInput::id)>); +static_assert(std::same_as::measured_object), decltype(SensorInput::measured_object)>); +static_assert(offsetof(CurrentSensorInput, id) == offsetof(SensorInput, id)); +static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(SensorInput, measured_object)); +// static asserts for conversion of CurrentSensorInput to GenericCurrentSensorInput +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(GenericCurrentSensorInput::id)>); +static_assert(std::same_as::measured_object), decltype(GenericCurrentSensorInput::measured_object)>); +static_assert(std::same_as::angle_measurement_type), decltype(GenericCurrentSensorInput::angle_measurement_type)>); +static_assert(std::same_as::i_sigma), decltype(GenericCurrentSensorInput::i_sigma)>); +static_assert(std::same_as::i_angle_sigma), decltype(GenericCurrentSensorInput::i_angle_sigma)>); +static_assert(offsetof(CurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); +static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); +static_assert(offsetof(CurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); +static_assert(offsetof(CurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); +static_assert(offsetof(CurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); +// static asserts for SymCurrentSensorInput +static_assert(std::is_standard_layout_v); +// static asserts for conversion of SymCurrentSensorInput to BaseInput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(offsetof(SymCurrentSensorInput, id) == offsetof(BaseInput, id)); +// static asserts for conversion of SymCurrentSensorInput to SensorInput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(std::same_as); +static_assert(offsetof(SymCurrentSensorInput, id) == offsetof(SensorInput, id)); +static_assert(offsetof(SymCurrentSensorInput, measured_object) == offsetof(SensorInput, measured_object)); +// static asserts for conversion of SymCurrentSensorInput to GenericCurrentSensorInput +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(SymCurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); +static_assert(offsetof(SymCurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); +static_assert(offsetof(SymCurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); +static_assert(offsetof(SymCurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); +static_assert(offsetof(SymCurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); +// static asserts for AsymCurrentSensorInput +static_assert(std::is_standard_layout_v); +// static asserts for conversion of AsymCurrentSensorInput to BaseInput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(offsetof(AsymCurrentSensorInput, id) == offsetof(BaseInput, id)); +// static asserts for conversion of AsymCurrentSensorInput to SensorInput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(std::same_as); +static_assert(offsetof(AsymCurrentSensorInput, id) == offsetof(SensorInput, id)); +static_assert(offsetof(AsymCurrentSensorInput, measured_object) == offsetof(SensorInput, measured_object)); +// static asserts for conversion of AsymCurrentSensorInput to GenericCurrentSensorInput +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(AsymCurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); +static_assert(offsetof(AsymCurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); +static_assert(offsetof(AsymCurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); +static_assert(offsetof(AsymCurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); +static_assert(offsetof(AsymCurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); + } // namespace power_grid_model::test From 51c972d248c32a6e25b279a5f47e76485abe7a83 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 24 Dec 2024 15:07:20 +0100 Subject: [PATCH 03/38] current sensor update Signed-off-by: petersalemink95 --- .../data/attribute_classes/input.json | 2 +- .../data/attribute_classes/update.json | 23 +++++++++++++++++ .../power_grid_model/auxiliary/input.hpp | 8 +++--- .../auxiliary/meta_gen/update.hpp | 15 +++++++++++ .../auxiliary/static_asserts/update.hpp | 25 +++++++++++++++++++ .../power_grid_model/auxiliary/update.hpp | 18 +++++++++++++ 6 files changed, 86 insertions(+), 5 deletions(-) diff --git a/code_generation/data/attribute_classes/input.json b/code_generation/data/attribute_classes/input.json index 141115ddb..6449a2532 100644 --- a/code_generation/data/attribute_classes/input.json +++ b/code_generation/data/attribute_classes/input.json @@ -510,7 +510,7 @@ "i_sigma", "i_angle_sigma" ], - "description": "sigma of error margin of apparent power measurement" + "description": "sigma of error margin of current (angle) measurement" } ] }, diff --git a/code_generation/data/attribute_classes/update.json b/code_generation/data/attribute_classes/update.json index a57205b17..db87d7bd1 100644 --- a/code_generation/data/attribute_classes/update.json +++ b/code_generation/data/attribute_classes/update.json @@ -243,6 +243,29 @@ "description": "line drop compensation reactance" } ] + }, + { + "name": "CurrentSensorUpdate", + "base": "BaseUpdate", + "is_template": true, + "attributes": [ + { + "data_type": "double", + "names": [ + "i_sigma", + "i_angle_sigma" + ], + "description": "sigma of error margin of current (angle) measurement" + }, + { + "data_type": "RealValue", + "names": [ + "i_measured", + "i_angle_measured" + ], + "description": "measured current and current angle" + } + ] } ] } \ No newline at end of file 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 87c7a7d4e..3a8dca0d9 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 @@ -448,8 +448,8 @@ struct GenericCurrentSensorInput { ID id{na_IntID}; // ID of the object ID measured_object{na_IntID}; // ID of the measured object AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement - double i_sigma{nan}; // sigma of error margin of apparent power measurement - double i_angle_sigma{nan}; // sigma of error margin of apparent power measurement + double i_sigma{nan}; // sigma of error margin of current (angle) measurement + double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement // implicit conversions to BaseInput operator BaseInput&() { return reinterpret_cast(*this); } @@ -467,8 +467,8 @@ struct CurrentSensorInput { ID id{na_IntID}; // ID of the object ID measured_object{na_IntID}; // ID of the measured object AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement - double i_sigma{nan}; // sigma of error margin of apparent power measurement - double i_angle_sigma{nan}; // sigma of error margin of apparent power measurement + double i_sigma{nan}; // sigma of error margin of current (angle) measurement + double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement RealValue i_measured{nan}; // measured current and current angle RealValue i_angle_measured{nan}; // measured current and current angle diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp index d4781bfe8..0e73efc8f 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp @@ -197,6 +197,21 @@ struct get_attributes_list { }; }; +template +struct get_attributes_list> { + using sym = sym_type; + + static constexpr std::array value{ + // all attributes including base class + + meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::id>(offsetof(CurrentSensorUpdate, id), "id"), + meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_sigma>(offsetof(CurrentSensorUpdate, i_sigma), "i_sigma"), + meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_angle_sigma>(offsetof(CurrentSensorUpdate, i_angle_sigma), "i_angle_sigma"), + meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_measured>(offsetof(CurrentSensorUpdate, i_measured), "i_measured"), + meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_angle_measured>(offsetof(CurrentSensorUpdate, i_angle_measured), "i_angle_measured"), + }; +}; + diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/update.hpp index dc244f783..7579606b2 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/update.hpp @@ -221,6 +221,31 @@ static_assert(std::same_as +static_assert(std::is_standard_layout_v>); +// static asserts for conversion of CurrentSensorUpdate to BaseUpdate +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(BaseUpdate::id)>); +static_assert(offsetof(CurrentSensorUpdate, id) == offsetof(BaseUpdate, id)); +// static asserts for CurrentSensorUpdate +static_assert(std::is_standard_layout_v>); +// static asserts for conversion of CurrentSensorUpdate to BaseUpdate +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(BaseUpdate::id)>); +static_assert(offsetof(CurrentSensorUpdate, id) == offsetof(BaseUpdate, id)); +// static asserts for SymCurrentSensorUpdate +static_assert(std::is_standard_layout_v); +// static asserts for conversion of SymCurrentSensorUpdate to BaseUpdate +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(offsetof(SymCurrentSensorUpdate, id) == offsetof(BaseUpdate, id)); +// static asserts for AsymCurrentSensorUpdate +static_assert(std::is_standard_layout_v); +// static asserts for conversion of AsymCurrentSensorUpdate to BaseUpdate +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(offsetof(AsymCurrentSensorUpdate, id) == offsetof(BaseUpdate, id)); + } // namespace power_grid_model::test diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp index d5dba7a67..a30b69fba 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp @@ -209,6 +209,24 @@ struct TransformerTapRegulatorUpdate { operator RegulatorUpdate const&() const { return reinterpret_cast(*this); } }; +template +struct CurrentSensorUpdate { + using sym = sym_type; + + ID id{na_IntID}; // ID of the object + double i_sigma{nan}; // sigma of error margin of current (angle) measurement + double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement + RealValue i_measured{nan}; // measured current and current angle + RealValue i_angle_measured{nan}; // measured current and current angle + + // implicit conversions to BaseUpdate + operator BaseUpdate&() { return reinterpret_cast(*this); } + operator BaseUpdate const&() const { return reinterpret_cast(*this); } +}; + +using SymCurrentSensorUpdate = CurrentSensorUpdate; +using AsymCurrentSensorUpdate = CurrentSensorUpdate; + } // namespace power_grid_model From 8480a5f87c7b4bddc614cd0ee48f336e042e1e8f Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 24 Dec 2024 15:08:52 +0100 Subject: [PATCH 04/38] current sensor output Signed-off-by: petersalemink95 --- .../data/attribute_classes/output.json | 15 +++++++++ .../auxiliary/meta_gen/output.hpp | 14 ++++++++ .../power_grid_model/auxiliary/output.hpp | 17 ++++++++++ .../auxiliary/static_asserts/output.hpp | 33 +++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/code_generation/data/attribute_classes/output.json b/code_generation/data/attribute_classes/output.json index 3fd789e6d..b8c310850 100644 --- a/code_generation/data/attribute_classes/output.json +++ b/code_generation/data/attribute_classes/output.json @@ -293,6 +293,21 @@ "base": "BaseOutput", "is_template": false, "attributes": [] + }, + { + "name": "CurrentSensorOutput", + "base": "BaseOutput", + "is_template": true, + "attributes": [ + { + "data_type": "RealValue", + "names": [ + "i_residual", + "i_angle_residual" + ], + "description": "deviation between the measured value and calculated value" + } + ] } ] } \ No newline at end of file diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/output.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/output.hpp index 3d4b62e96..186ec3b56 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/output.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/output.hpp @@ -247,6 +247,20 @@ struct get_attributes_list { }; }; +template +struct get_attributes_list> { + using sym = sym_type; + + static constexpr std::array value{ + // all attributes including base class + + meta_data_gen::get_meta_attribute<&CurrentSensorOutput::id>(offsetof(CurrentSensorOutput, id), "id"), + meta_data_gen::get_meta_attribute<&CurrentSensorOutput::energized>(offsetof(CurrentSensorOutput, energized), "energized"), + meta_data_gen::get_meta_attribute<&CurrentSensorOutput::i_residual>(offsetof(CurrentSensorOutput, i_residual), "i_residual"), + meta_data_gen::get_meta_attribute<&CurrentSensorOutput::i_angle_residual>(offsetof(CurrentSensorOutput, i_angle_residual), "i_angle_residual"), + }; +}; + diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/output.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/output.hpp index 54de1fa69..1fae40845 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/output.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/output.hpp @@ -245,6 +245,23 @@ struct RegulatorShortCircuitOutput { operator BaseOutput const&() const { return reinterpret_cast(*this); } }; +template +struct CurrentSensorOutput { + using sym = sym_type; + + ID id{na_IntID}; // ID of the object + IntS energized{na_IntS}; // whether the object is energized + RealValue i_residual{nan}; // deviation between the measured value and calculated value + RealValue i_angle_residual{nan}; // deviation between the measured value and calculated value + + // implicit conversions to BaseOutput + operator BaseOutput&() { return reinterpret_cast(*this); } + operator BaseOutput const&() const { return reinterpret_cast(*this); } +}; + +using SymCurrentSensorOutput = CurrentSensorOutput; +using AsymCurrentSensorOutput = CurrentSensorOutput; + } // namespace power_grid_model diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/output.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/output.hpp index 54a5d5f55..9de483618 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/output.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/static_asserts/output.hpp @@ -295,6 +295,39 @@ static_assert(std::same_as +static_assert(std::is_standard_layout_v>); +// static asserts for conversion of CurrentSensorOutput to BaseOutput +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(BaseOutput::id)>); +static_assert(std::same_as::energized), decltype(BaseOutput::energized)>); +static_assert(offsetof(CurrentSensorOutput, id) == offsetof(BaseOutput, id)); +static_assert(offsetof(CurrentSensorOutput, energized) == offsetof(BaseOutput, energized)); +// static asserts for CurrentSensorOutput +static_assert(std::is_standard_layout_v>); +// static asserts for conversion of CurrentSensorOutput to BaseOutput +static_assert(std::alignment_of_v> >= std::alignment_of_v); +static_assert(std::same_as::id), decltype(BaseOutput::id)>); +static_assert(std::same_as::energized), decltype(BaseOutput::energized)>); +static_assert(offsetof(CurrentSensorOutput, id) == offsetof(BaseOutput, id)); +static_assert(offsetof(CurrentSensorOutput, energized) == offsetof(BaseOutput, energized)); +// static asserts for SymCurrentSensorOutput +static_assert(std::is_standard_layout_v); +// static asserts for conversion of SymCurrentSensorOutput to BaseOutput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(std::same_as); +static_assert(offsetof(SymCurrentSensorOutput, id) == offsetof(BaseOutput, id)); +static_assert(offsetof(SymCurrentSensorOutput, energized) == offsetof(BaseOutput, energized)); +// static asserts for AsymCurrentSensorOutput +static_assert(std::is_standard_layout_v); +// static asserts for conversion of AsymCurrentSensorOutput to BaseOutput +static_assert(std::alignment_of_v >= std::alignment_of_v); +static_assert(std::same_as); +static_assert(std::same_as); +static_assert(offsetof(AsymCurrentSensorOutput, id) == offsetof(BaseOutput, id)); +static_assert(offsetof(AsymCurrentSensorOutput, energized) == offsetof(BaseOutput, energized)); + } // namespace power_grid_model::test From 8dc43749daab5023ff328edeefc934baf26a5b9b Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 24 Dec 2024 15:19:56 +0100 Subject: [PATCH 05/38] current sensor file with license Signed-off-by: petersalemink95 --- .../power_grid_model/component/current_sensor.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp new file mode 100644 index 000000000..c8c2de4bf --- /dev/null +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: Contributors to the Power Grid Model project +// +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "sensor.hpp" + +namespace power_grid_model {} // namespace power_grid_model From 5c09d74a56e18f2803a5984e0f335c41cf7de6bf Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 24 Dec 2024 15:33:23 +0100 Subject: [PATCH 06/38] add measured terminal type to input Signed-off-by: petersalemink95 --- code_generation/data/attribute_classes/input.json | 5 +++++ .../include/power_grid_model/auxiliary/input.hpp | 2 ++ .../include/power_grid_model/auxiliary/meta_gen/input.hpp | 6 ++++-- .../power_grid_model/auxiliary/static_asserts/input.hpp | 8 ++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/code_generation/data/attribute_classes/input.json b/code_generation/data/attribute_classes/input.json index 6449a2532..7cf8b5c97 100644 --- a/code_generation/data/attribute_classes/input.json +++ b/code_generation/data/attribute_classes/input.json @@ -499,6 +499,11 @@ "name": "GenericCurrentSensorInput", "base": "SensorInput", "attributes": [ + { + "data_type": "MeasuredTerminalType", + "names": "measured_terminal_type", + "description": "type of measured terminal" + }, { "data_type": "AngleMeasurementType", "names": "angle_measurement_type", 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 3a8dca0d9..661579d1c 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 @@ -447,6 +447,7 @@ struct TransformerTapRegulatorInput { struct GenericCurrentSensorInput { ID id{na_IntID}; // ID of the object ID measured_object{na_IntID}; // ID of the measured object + MeasuredTerminalType measured_terminal_type{static_cast(na_IntS)}; // type of measured terminal AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement double i_sigma{nan}; // sigma of error margin of current (angle) measurement double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement @@ -466,6 +467,7 @@ struct CurrentSensorInput { ID id{na_IntID}; // ID of the object ID measured_object{na_IntID}; // ID of the measured object + MeasuredTerminalType measured_terminal_type{static_cast(na_IntS)}; // type of measured terminal AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement double i_sigma{nan}; // sigma of error margin of current (angle) measurement double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement 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 f20333f27..27deffff7 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 @@ -398,11 +398,12 @@ struct get_attributes_list { template<> struct get_attributes_list { - static constexpr std::array value{ + static constexpr std::array value{ // all attributes including base class meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::id>(offsetof(GenericCurrentSensorInput, id), "id"), meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::measured_object>(offsetof(GenericCurrentSensorInput, measured_object), "measured_object"), + meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::measured_terminal_type>(offsetof(GenericCurrentSensorInput, measured_terminal_type), "measured_terminal_type"), meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::angle_measurement_type>(offsetof(GenericCurrentSensorInput, angle_measurement_type), "angle_measurement_type"), meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::i_sigma>(offsetof(GenericCurrentSensorInput, i_sigma), "i_sigma"), meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::i_angle_sigma>(offsetof(GenericCurrentSensorInput, i_angle_sigma), "i_angle_sigma"), @@ -413,11 +414,12 @@ template struct get_attributes_list> { using sym = sym_type; - static constexpr std::array value{ + static constexpr std::array value{ // all attributes including base class meta_data_gen::get_meta_attribute<&CurrentSensorInput::id>(offsetof(CurrentSensorInput, id), "id"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::measured_object>(offsetof(CurrentSensorInput, measured_object), "measured_object"), + meta_data_gen::get_meta_attribute<&CurrentSensorInput::measured_terminal_type>(offsetof(CurrentSensorInput, measured_terminal_type), "measured_terminal_type"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::angle_measurement_type>(offsetof(CurrentSensorInput, angle_measurement_type), "angle_measurement_type"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_sigma>(offsetof(CurrentSensorInput, i_sigma), "i_sigma"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_angle_sigma>(offsetof(CurrentSensorInput, i_angle_sigma), "i_angle_sigma"), 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 5c2334794..ee0052125 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 @@ -546,11 +546,13 @@ static_assert(offsetof(CurrentSensorInput, measured_object) == offs static_assert(std::alignment_of_v> >= std::alignment_of_v); static_assert(std::same_as::id), decltype(GenericCurrentSensorInput::id)>); static_assert(std::same_as::measured_object), decltype(GenericCurrentSensorInput::measured_object)>); +static_assert(std::same_as::measured_terminal_type), decltype(GenericCurrentSensorInput::measured_terminal_type)>); static_assert(std::same_as::angle_measurement_type), decltype(GenericCurrentSensorInput::angle_measurement_type)>); static_assert(std::same_as::i_sigma), decltype(GenericCurrentSensorInput::i_sigma)>); static_assert(std::same_as::i_angle_sigma), decltype(GenericCurrentSensorInput::i_angle_sigma)>); static_assert(offsetof(CurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); +static_assert(offsetof(CurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(CurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(CurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); static_assert(offsetof(CurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); @@ -570,11 +572,13 @@ static_assert(offsetof(CurrentSensorInput, measured_object) == off static_assert(std::alignment_of_v> >= std::alignment_of_v); static_assert(std::same_as::id), decltype(GenericCurrentSensorInput::id)>); static_assert(std::same_as::measured_object), decltype(GenericCurrentSensorInput::measured_object)>); +static_assert(std::same_as::measured_terminal_type), decltype(GenericCurrentSensorInput::measured_terminal_type)>); static_assert(std::same_as::angle_measurement_type), decltype(GenericCurrentSensorInput::angle_measurement_type)>); static_assert(std::same_as::i_sigma), decltype(GenericCurrentSensorInput::i_sigma)>); static_assert(std::same_as::i_angle_sigma), decltype(GenericCurrentSensorInput::i_angle_sigma)>); static_assert(offsetof(CurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); +static_assert(offsetof(CurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(CurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(CurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); static_assert(offsetof(CurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); @@ -594,11 +598,13 @@ static_assert(offsetof(SymCurrentSensorInput, measured_object) == offsetof(Senso 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(std::same_as); static_assert(offsetof(SymCurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(SymCurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); +static_assert(offsetof(SymCurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(SymCurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(SymCurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); static_assert(offsetof(SymCurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); @@ -618,11 +624,13 @@ static_assert(offsetof(AsymCurrentSensorInput, measured_object) == offsetof(Sens 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(std::same_as); static_assert(offsetof(AsymCurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(AsymCurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); +static_assert(offsetof(AsymCurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(AsymCurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(AsymCurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); static_assert(offsetof(AsymCurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); From 083b2bf0faf85dbaeb3d9fe89e82ba2ea2a6ad76 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 24 Dec 2024 15:55:28 +0100 Subject: [PATCH 07/38] generic current sensor + empty test file Signed-off-by: petersalemink95 --- .../component/current_sensor.hpp | 61 ++++++++++++++++++- tests/cpp_unit_tests/CMakeLists.txt | 1 + tests/cpp_unit_tests/test_current_sensor.cpp | 9 +++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/cpp_unit_tests/test_current_sensor.cpp diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index c8c2de4bf..ddab4a9aa 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -6,4 +6,63 @@ #include "sensor.hpp" -namespace power_grid_model {} // namespace power_grid_model +namespace power_grid_model { + +class GenericCurrentSensor : public Sensor { + public: + static constexpr char const* name = "generic_current_sensor"; + + explicit GenericCurrentSensor(GenericCurrentSensorInput const& generic_current_sensor_input) + : Sensor{generic_current_sensor_input}, + terminal_type_{generic_current_sensor_input.measured_terminal_type}, + angle_measurement_type_{generic_current_sensor_input.angle_measurement_type} {} + + MeasuredTerminalType get_terminal_type() const { return terminal_type_; } + AngleMeasurementType get_angle_measurement_type() const { return angle_measurement_type_; } + + template CurrentSensorOutput get_output(ComplexValue const& i) const { + if constexpr (is_symmetric_v) { + return get_sym_output(i); + } else { + return get_asym_output(i); + } + } + + template CurrentSensorOutput get_null_output() const { + return {.id = id(), .energized = false, .i_residual = {}, .i_angle_residual = {}}; + } + + SensorShortCircuitOutput get_null_sc_output() const { return {.id = id(), .energized = 0}; } + + // getter for calculation param + template PowerSensorCalcParam calc_param() const { + if constexpr (is_symmetric_v) { + return sym_calc_param(); + } else { + return asym_calc_param(); + } + } + + protected: + double convert_direction() const { + if (terminal_type_ == MeasuredTerminalType::load || terminal_type_ == MeasuredTerminalType::shunt) { + return -1.0; // For shunt and load the direction in the math model is opposite to the direction in the + // physical model + } + return 1.0; + } + + private: + MeasuredTerminalType terminal_type_; + AngleMeasurementType angle_measurement_type_; + + // virtual function getter for sym and asym param + // override them in real sensors function + virtual PowerSensorCalcParam sym_calc_param() const = 0; + virtual PowerSensorCalcParam asym_calc_param() const = 0; + + virtual PowerSensorOutput get_sym_output(ComplexValue const& i) const = 0; + virtual PowerSensorOutput get_asym_output(ComplexValue const& i) const = 0; +}; + +} // namespace power_grid_model diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt index 53bdeb029..12c4d801a 100644 --- a/tests/cpp_unit_tests/CMakeLists.txt +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -48,6 +48,7 @@ set(PROJECT_SOURCES "test_math_solver_se_newton_raphson.cpp" "test_math_solver_se_iterative_linear.cpp" "test_math_solver_sc.cpp" + "test_current_sensor.cpp" ) add_executable(power_grid_model_unit_tests ${PROJECT_SOURCES}) diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp new file mode 100644 index 000000000..367f3ab4a --- /dev/null +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: Contributors to the Power Grid Model project +// +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include + +namespace power_grid_model {} // namespace power_grid_model From 2c71a556c2c55f9f666d5297ff5e30137510194b Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 24 Dec 2024 16:14:35 +0100 Subject: [PATCH 08/38] disable mypy call-overload Signed-off-by: petersalemink95 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6c5b98edd..7343ab1ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -103,7 +103,7 @@ ignore_missing_imports = true show_column_numbers = true non_interactive = true install_types = true - +disable_error_code = ["call-overload"] # mypy 1.14.0 does not like PGM's data_types # CI build options [tool.cibuildwheel] From a0609c78f177248ae30db3c1e9d7bf45d22996c1 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 24 Dec 2024 16:19:23 +0100 Subject: [PATCH 09/38] change sigma Signed-off-by: petersalemink95 --- code_generation/data/attribute_classes/input.json | 7 ++----- code_generation/data/attribute_classes/update.json | 5 +---- .../include/power_grid_model/auxiliary/input.hpp | 6 ++---- .../include/power_grid_model/auxiliary/meta_gen/input.hpp | 6 ++---- .../power_grid_model/auxiliary/meta_gen/update.hpp | 3 +-- .../power_grid_model/auxiliary/static_asserts/input.hpp | 8 -------- .../include/power_grid_model/auxiliary/update.hpp | 1 - 7 files changed, 8 insertions(+), 28 deletions(-) diff --git a/code_generation/data/attribute_classes/input.json b/code_generation/data/attribute_classes/input.json index 7cf8b5c97..9cf7d1e3b 100644 --- a/code_generation/data/attribute_classes/input.json +++ b/code_generation/data/attribute_classes/input.json @@ -511,11 +511,8 @@ }, { "data_type": "double", - "names": [ - "i_sigma", - "i_angle_sigma" - ], - "description": "sigma of error margin of current (angle) measurement" + "names": "i_sigma", + "description": "sigma of error margin of current measurement" } ] }, diff --git a/code_generation/data/attribute_classes/update.json b/code_generation/data/attribute_classes/update.json index db87d7bd1..10e6c1202 100644 --- a/code_generation/data/attribute_classes/update.json +++ b/code_generation/data/attribute_classes/update.json @@ -251,10 +251,7 @@ "attributes": [ { "data_type": "double", - "names": [ - "i_sigma", - "i_angle_sigma" - ], + "names": "i_sigma", "description": "sigma of error margin of current (angle) measurement" }, { 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 661579d1c..f7624160a 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 @@ -449,8 +449,7 @@ struct GenericCurrentSensorInput { ID measured_object{na_IntID}; // ID of the measured object MeasuredTerminalType measured_terminal_type{static_cast(na_IntS)}; // type of measured terminal AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement - double i_sigma{nan}; // sigma of error margin of current (angle) measurement - double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement + double i_sigma{nan}; // sigma of error margin of current measurement // implicit conversions to BaseInput operator BaseInput&() { return reinterpret_cast(*this); } @@ -469,8 +468,7 @@ struct CurrentSensorInput { ID measured_object{na_IntID}; // ID of the measured object MeasuredTerminalType measured_terminal_type{static_cast(na_IntS)}; // type of measured terminal AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement - double i_sigma{nan}; // sigma of error margin of current (angle) measurement - double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement + double i_sigma{nan}; // sigma of error margin of current measurement RealValue i_measured{nan}; // measured current and current angle RealValue i_angle_measured{nan}; // measured current and current angle 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 27deffff7..b3043e2c3 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 @@ -398,7 +398,7 @@ struct get_attributes_list { template<> struct get_attributes_list { - static constexpr std::array value{ + static constexpr std::array value{ // all attributes including base class meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::id>(offsetof(GenericCurrentSensorInput, id), "id"), @@ -406,7 +406,6 @@ struct get_attributes_list { meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::measured_terminal_type>(offsetof(GenericCurrentSensorInput, measured_terminal_type), "measured_terminal_type"), meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::angle_measurement_type>(offsetof(GenericCurrentSensorInput, angle_measurement_type), "angle_measurement_type"), meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::i_sigma>(offsetof(GenericCurrentSensorInput, i_sigma), "i_sigma"), - meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::i_angle_sigma>(offsetof(GenericCurrentSensorInput, i_angle_sigma), "i_angle_sigma"), }; }; @@ -414,7 +413,7 @@ template struct get_attributes_list> { using sym = sym_type; - static constexpr std::array value{ + static constexpr std::array value{ // all attributes including base class meta_data_gen::get_meta_attribute<&CurrentSensorInput::id>(offsetof(CurrentSensorInput, id), "id"), @@ -422,7 +421,6 @@ struct get_attributes_list> { meta_data_gen::get_meta_attribute<&CurrentSensorInput::measured_terminal_type>(offsetof(CurrentSensorInput, measured_terminal_type), "measured_terminal_type"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::angle_measurement_type>(offsetof(CurrentSensorInput, angle_measurement_type), "angle_measurement_type"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_sigma>(offsetof(CurrentSensorInput, i_sigma), "i_sigma"), - meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_angle_sigma>(offsetof(CurrentSensorInput, i_angle_sigma), "i_angle_sigma"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_measured>(offsetof(CurrentSensorInput, i_measured), "i_measured"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_angle_measured>(offsetof(CurrentSensorInput, i_angle_measured), "i_angle_measured"), }; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp index 0e73efc8f..a73aaf905 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp @@ -201,12 +201,11 @@ template struct get_attributes_list> { using sym = sym_type; - static constexpr std::array value{ + static constexpr std::array value{ // all attributes including base class meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::id>(offsetof(CurrentSensorUpdate, id), "id"), meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_sigma>(offsetof(CurrentSensorUpdate, i_sigma), "i_sigma"), - meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_angle_sigma>(offsetof(CurrentSensorUpdate, i_angle_sigma), "i_angle_sigma"), meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_measured>(offsetof(CurrentSensorUpdate, i_measured), "i_measured"), meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_angle_measured>(offsetof(CurrentSensorUpdate, i_angle_measured), "i_angle_measured"), }; 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 ee0052125..48a3afc15 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 @@ -549,13 +549,11 @@ static_assert(std::same_as::measured_ob static_assert(std::same_as::measured_terminal_type), decltype(GenericCurrentSensorInput::measured_terminal_type)>); static_assert(std::same_as::angle_measurement_type), decltype(GenericCurrentSensorInput::angle_measurement_type)>); static_assert(std::same_as::i_sigma), decltype(GenericCurrentSensorInput::i_sigma)>); -static_assert(std::same_as::i_angle_sigma), decltype(GenericCurrentSensorInput::i_angle_sigma)>); static_assert(offsetof(CurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); static_assert(offsetof(CurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(CurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(CurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); -static_assert(offsetof(CurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); // static asserts for CurrentSensorInput static_assert(std::is_standard_layout_v>); // static asserts for conversion of CurrentSensorInput to BaseInput @@ -575,13 +573,11 @@ static_assert(std::same_as::measured_o static_assert(std::same_as::measured_terminal_type), decltype(GenericCurrentSensorInput::measured_terminal_type)>); static_assert(std::same_as::angle_measurement_type), decltype(GenericCurrentSensorInput::angle_measurement_type)>); static_assert(std::same_as::i_sigma), decltype(GenericCurrentSensorInput::i_sigma)>); -static_assert(std::same_as::i_angle_sigma), decltype(GenericCurrentSensorInput::i_angle_sigma)>); static_assert(offsetof(CurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); static_assert(offsetof(CurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(CurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(CurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); -static_assert(offsetof(CurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); // static asserts for SymCurrentSensorInput static_assert(std::is_standard_layout_v); // static asserts for conversion of SymCurrentSensorInput to BaseInput @@ -601,13 +597,11 @@ static_assert(std::same_as); static_assert(std::same_as); static_assert(std::same_as); -static_assert(std::same_as); static_assert(offsetof(SymCurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(SymCurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); static_assert(offsetof(SymCurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(SymCurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(SymCurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); -static_assert(offsetof(SymCurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); // static asserts for AsymCurrentSensorInput static_assert(std::is_standard_layout_v); // static asserts for conversion of AsymCurrentSensorInput to BaseInput @@ -627,13 +621,11 @@ static_assert(std::same_as); static_assert(std::same_as); static_assert(std::same_as); -static_assert(std::same_as); static_assert(offsetof(AsymCurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(AsymCurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); static_assert(offsetof(AsymCurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(AsymCurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(AsymCurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); -static_assert(offsetof(AsymCurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp index a30b69fba..71252e64f 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp @@ -215,7 +215,6 @@ struct CurrentSensorUpdate { ID id{na_IntID}; // ID of the object double i_sigma{nan}; // sigma of error margin of current (angle) measurement - double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement RealValue i_measured{nan}; // measured current and current angle RealValue i_angle_measured{nan}; // measured current and current angle From b4644092001aca576ec4b983c33d2b28b2b396b9 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Mon, 30 Dec 2024 15:18:35 +0100 Subject: [PATCH 10/38] CurrentSensorCalcParam Signed-off-by: petersalemink95 --- .../include/power_grid_model/calculation_parameters.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp index 53cf13953..39a8e7318 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp @@ -94,6 +94,11 @@ template struct UniformComplexRandomVariable { // If the imaginary part is NaN, it means the angle calculation is not correct template using VoltageSensorCalcParam = UniformComplexRandomVariable; +// current sensor calculation parameters for state estimation +// The value is the complex current +// If the imaginary part is NaN, it means the angle calculation is not correct +template using CurrentSensorCalcParam = UniformComplexRandomVariable; + // power sensor calculation parameters for state estimation // The value is the complex power // * for appliances, it is always in injection direction From ca09197a20c0987d908f8091cbb5808add1f9973 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Mon, 30 Dec 2024 15:19:23 +0100 Subject: [PATCH 11/38] CurrentSensor template Signed-off-by: petersalemink95 --- .../component/current_sensor.hpp | 76 ++++++++++++++++++- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index ddab4a9aa..f7b947734 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -6,6 +6,10 @@ #include "sensor.hpp" +#include "../calculation_parameters.hpp" +#include "../common/common.hpp" +#include "../common/enum.hpp" + namespace power_grid_model { class GenericCurrentSensor : public Sensor { @@ -58,11 +62,75 @@ class GenericCurrentSensor : public Sensor { // virtual function getter for sym and asym param // override them in real sensors function - virtual PowerSensorCalcParam sym_calc_param() const = 0; - virtual PowerSensorCalcParam asym_calc_param() const = 0; + virtual CurrentSensorCalcParam sym_calc_param() const = 0; + virtual CurrentSensorCalcParam asym_calc_param() const = 0; + + virtual CurrentSensorOutput get_sym_output(ComplexValue const& i) const = 0; + virtual CurrentSensorOutput get_asym_output(ComplexValue const& i) const = 0; +}; + +template class CurrentSensor : public GenericCurrentSensor { + public: + using current_sensor_symmetry = current_sensor_symmetry_; + + static constexpr char const* name = + is_symmetric_v ? "sym_current_sensor" : "asym_current_sensor"; + using InputType = CurrentSensorInput; + using UpdateType = CurrentSensorUpdate; + template using OutputType = CurrentSensorOutput; + + // TODO: add u_rated to calculate base_current = base_power_3p / u_rated / sqrt3 + explicit CurrentSensor(CurrentSensorInput const& current_sensor_input) + : GenericCurrentSensor{current_sensor_input}, + i_sigma_{current_sensor_input.i_sigma / base_power}, + i_angle_measured_{current_sensor_input.i_angle_measured} { + set_current(current_sensor_input.i_measured); + }; + + UpdateChange update(CurrentSensorUpdate const& update_data) { + // TODO + return {false, false}; + } + + PowerSensorUpdate inverse(PowerSensorUpdate update_data) const { + // TODO + + return update_data; + } + + private: + ComplexValue i_measured_{}; + RealValue i_angle_measured_{}; + double i_sigma_{}; - virtual PowerSensorOutput get_sym_output(ComplexValue const& i) const = 0; - virtual PowerSensorOutput get_asym_output(ComplexValue const& i) const = 0; + void set_current(RealValue const& i_measured) { + // TODO + } + + CurrentSensorCalcParam sym_calc_param() const final { + CurrentSensorCalcParam calc_param{}; + // TODO + return calc_param; + } + CurrentSensorCalcParam asym_calc_param() const final { + CurrentSensorCalcParam calc_param{}; + // TODO + return calc_param; + } + CurrentSensorOutput get_sym_output(ComplexValue const& i) const final { + return get_generic_output(i); + } + CurrentSensorOutput get_asym_output(ComplexValue const& i) const final { + return get_generic_output(i); + } + template + CurrentSensorOutput get_generic_output(ComplexValue const& i) const { + CurrentSensorOutput output{}; + return output; + } }; +using SymCurrentSensor = CurrentSensor; +using AsymCurrentSensor = CurrentSensor; + } // namespace power_grid_model From 7c32e89118f18a12462a8e5c68d098782b22460f Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Mon, 30 Dec 2024 15:27:52 +0100 Subject: [PATCH 12/38] Revert "change sigma" This reverts commit a0609c78f177248ae30db3c1e9d7bf45d22996c1. --- code_generation/data/attribute_classes/input.json | 7 +++++-- code_generation/data/attribute_classes/update.json | 5 ++++- .../include/power_grid_model/auxiliary/input.hpp | 6 ++++-- .../include/power_grid_model/auxiliary/meta_gen/input.hpp | 6 ++++-- .../power_grid_model/auxiliary/meta_gen/update.hpp | 3 ++- .../power_grid_model/auxiliary/static_asserts/input.hpp | 8 ++++++++ .../include/power_grid_model/auxiliary/update.hpp | 1 + 7 files changed, 28 insertions(+), 8 deletions(-) diff --git a/code_generation/data/attribute_classes/input.json b/code_generation/data/attribute_classes/input.json index 9cf7d1e3b..7cf8b5c97 100644 --- a/code_generation/data/attribute_classes/input.json +++ b/code_generation/data/attribute_classes/input.json @@ -511,8 +511,11 @@ }, { "data_type": "double", - "names": "i_sigma", - "description": "sigma of error margin of current measurement" + "names": [ + "i_sigma", + "i_angle_sigma" + ], + "description": "sigma of error margin of current (angle) measurement" } ] }, diff --git a/code_generation/data/attribute_classes/update.json b/code_generation/data/attribute_classes/update.json index 10e6c1202..db87d7bd1 100644 --- a/code_generation/data/attribute_classes/update.json +++ b/code_generation/data/attribute_classes/update.json @@ -251,7 +251,10 @@ "attributes": [ { "data_type": "double", - "names": "i_sigma", + "names": [ + "i_sigma", + "i_angle_sigma" + ], "description": "sigma of error margin of current (angle) measurement" }, { 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 f7624160a..661579d1c 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 @@ -449,7 +449,8 @@ struct GenericCurrentSensorInput { ID measured_object{na_IntID}; // ID of the measured object MeasuredTerminalType measured_terminal_type{static_cast(na_IntS)}; // type of measured terminal AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement - double i_sigma{nan}; // sigma of error margin of current measurement + double i_sigma{nan}; // sigma of error margin of current (angle) measurement + double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement // implicit conversions to BaseInput operator BaseInput&() { return reinterpret_cast(*this); } @@ -468,7 +469,8 @@ struct CurrentSensorInput { ID measured_object{na_IntID}; // ID of the measured object MeasuredTerminalType measured_terminal_type{static_cast(na_IntS)}; // type of measured terminal AngleMeasurementType angle_measurement_type{static_cast(na_IntS)}; // type of angle measurement - double i_sigma{nan}; // sigma of error margin of current measurement + double i_sigma{nan}; // sigma of error margin of current (angle) measurement + double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement RealValue i_measured{nan}; // measured current and current angle RealValue i_angle_measured{nan}; // measured current and current angle 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 b3043e2c3..27deffff7 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 @@ -398,7 +398,7 @@ struct get_attributes_list { template<> struct get_attributes_list { - static constexpr std::array value{ + static constexpr std::array value{ // all attributes including base class meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::id>(offsetof(GenericCurrentSensorInput, id), "id"), @@ -406,6 +406,7 @@ struct get_attributes_list { meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::measured_terminal_type>(offsetof(GenericCurrentSensorInput, measured_terminal_type), "measured_terminal_type"), meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::angle_measurement_type>(offsetof(GenericCurrentSensorInput, angle_measurement_type), "angle_measurement_type"), meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::i_sigma>(offsetof(GenericCurrentSensorInput, i_sigma), "i_sigma"), + meta_data_gen::get_meta_attribute<&GenericCurrentSensorInput::i_angle_sigma>(offsetof(GenericCurrentSensorInput, i_angle_sigma), "i_angle_sigma"), }; }; @@ -413,7 +414,7 @@ template struct get_attributes_list> { using sym = sym_type; - static constexpr std::array value{ + static constexpr std::array value{ // all attributes including base class meta_data_gen::get_meta_attribute<&CurrentSensorInput::id>(offsetof(CurrentSensorInput, id), "id"), @@ -421,6 +422,7 @@ struct get_attributes_list> { meta_data_gen::get_meta_attribute<&CurrentSensorInput::measured_terminal_type>(offsetof(CurrentSensorInput, measured_terminal_type), "measured_terminal_type"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::angle_measurement_type>(offsetof(CurrentSensorInput, angle_measurement_type), "angle_measurement_type"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_sigma>(offsetof(CurrentSensorInput, i_sigma), "i_sigma"), + meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_angle_sigma>(offsetof(CurrentSensorInput, i_angle_sigma), "i_angle_sigma"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_measured>(offsetof(CurrentSensorInput, i_measured), "i_measured"), meta_data_gen::get_meta_attribute<&CurrentSensorInput::i_angle_measured>(offsetof(CurrentSensorInput, i_angle_measured), "i_angle_measured"), }; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp index a73aaf905..0e73efc8f 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_gen/update.hpp @@ -201,11 +201,12 @@ template struct get_attributes_list> { using sym = sym_type; - static constexpr std::array value{ + static constexpr std::array value{ // all attributes including base class meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::id>(offsetof(CurrentSensorUpdate, id), "id"), meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_sigma>(offsetof(CurrentSensorUpdate, i_sigma), "i_sigma"), + meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_angle_sigma>(offsetof(CurrentSensorUpdate, i_angle_sigma), "i_angle_sigma"), meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_measured>(offsetof(CurrentSensorUpdate, i_measured), "i_measured"), meta_data_gen::get_meta_attribute<&CurrentSensorUpdate::i_angle_measured>(offsetof(CurrentSensorUpdate, i_angle_measured), "i_angle_measured"), }; 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 48a3afc15..ee0052125 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 @@ -549,11 +549,13 @@ static_assert(std::same_as::measured_ob static_assert(std::same_as::measured_terminal_type), decltype(GenericCurrentSensorInput::measured_terminal_type)>); static_assert(std::same_as::angle_measurement_type), decltype(GenericCurrentSensorInput::angle_measurement_type)>); static_assert(std::same_as::i_sigma), decltype(GenericCurrentSensorInput::i_sigma)>); +static_assert(std::same_as::i_angle_sigma), decltype(GenericCurrentSensorInput::i_angle_sigma)>); static_assert(offsetof(CurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); static_assert(offsetof(CurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(CurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(CurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); +static_assert(offsetof(CurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); // static asserts for CurrentSensorInput static_assert(std::is_standard_layout_v>); // static asserts for conversion of CurrentSensorInput to BaseInput @@ -573,11 +575,13 @@ static_assert(std::same_as::measured_o static_assert(std::same_as::measured_terminal_type), decltype(GenericCurrentSensorInput::measured_terminal_type)>); static_assert(std::same_as::angle_measurement_type), decltype(GenericCurrentSensorInput::angle_measurement_type)>); static_assert(std::same_as::i_sigma), decltype(GenericCurrentSensorInput::i_sigma)>); +static_assert(std::same_as::i_angle_sigma), decltype(GenericCurrentSensorInput::i_angle_sigma)>); static_assert(offsetof(CurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(CurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); static_assert(offsetof(CurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(CurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(CurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); +static_assert(offsetof(CurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); // static asserts for SymCurrentSensorInput static_assert(std::is_standard_layout_v); // static asserts for conversion of SymCurrentSensorInput to BaseInput @@ -597,11 +601,13 @@ static_assert(std::same_as); static_assert(std::same_as); static_assert(std::same_as); +static_assert(std::same_as); static_assert(offsetof(SymCurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(SymCurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); static_assert(offsetof(SymCurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(SymCurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(SymCurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); +static_assert(offsetof(SymCurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); // static asserts for AsymCurrentSensorInput static_assert(std::is_standard_layout_v); // static asserts for conversion of AsymCurrentSensorInput to BaseInput @@ -621,11 +627,13 @@ static_assert(std::same_as); static_assert(std::same_as); static_assert(std::same_as); +static_assert(std::same_as); static_assert(offsetof(AsymCurrentSensorInput, id) == offsetof(GenericCurrentSensorInput, id)); static_assert(offsetof(AsymCurrentSensorInput, measured_object) == offsetof(GenericCurrentSensorInput, measured_object)); static_assert(offsetof(AsymCurrentSensorInput, measured_terminal_type) == offsetof(GenericCurrentSensorInput, measured_terminal_type)); static_assert(offsetof(AsymCurrentSensorInput, angle_measurement_type) == offsetof(GenericCurrentSensorInput, angle_measurement_type)); static_assert(offsetof(AsymCurrentSensorInput, i_sigma) == offsetof(GenericCurrentSensorInput, i_sigma)); +static_assert(offsetof(AsymCurrentSensorInput, i_angle_sigma) == offsetof(GenericCurrentSensorInput, i_angle_sigma)); diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp index 71252e64f..a30b69fba 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/update.hpp @@ -215,6 +215,7 @@ struct CurrentSensorUpdate { ID id{na_IntID}; // ID of the object double i_sigma{nan}; // sigma of error margin of current (angle) measurement + double i_angle_sigma{nan}; // sigma of error margin of current (angle) measurement RealValue i_measured{nan}; // measured current and current angle RealValue i_angle_measured{nan}; // measured current and current angle From dade51361b0970d541cca43f360399facf5f947b Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Mon, 30 Dec 2024 15:32:13 +0100 Subject: [PATCH 13/38] i_angle_sigma in constructor Signed-off-by: petersalemink95 --- .../include/power_grid_model/component/current_sensor.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index f7b947734..76b7bcdf5 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -82,7 +82,9 @@ template class CurrentSensor : public Ge // TODO: add u_rated to calculate base_current = base_power_3p / u_rated / sqrt3 explicit CurrentSensor(CurrentSensorInput const& current_sensor_input) : GenericCurrentSensor{current_sensor_input}, - i_sigma_{current_sensor_input.i_sigma / base_power}, + i_sigma_{current_sensor_input.i_sigma / base_power}, // TODO use base_current + i_angle_sigma_{current_sensor_input.i_angle_sigma / + base_power}, // TODO use base_current i_angle_measured_{current_sensor_input.i_angle_measured} { set_current(current_sensor_input.i_measured); }; @@ -102,6 +104,7 @@ template class CurrentSensor : public Ge ComplexValue i_measured_{}; RealValue i_angle_measured_{}; double i_sigma_{}; + double i_angle_sigma_{}; void set_current(RealValue const& i_measured) { // TODO From 235c14e1656936786c9a068b84d75fa42a4cd250 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Mon, 30 Dec 2024 15:58:46 +0100 Subject: [PATCH 14/38] calculate + use base_current Signed-off-by: petersalemink95 --- .../component/current_sensor.hpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 76b7bcdf5..33c65b213 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -79,14 +79,9 @@ template class CurrentSensor : public Ge using UpdateType = CurrentSensorUpdate; template using OutputType = CurrentSensorOutput; - // TODO: add u_rated to calculate base_current = base_power_3p / u_rated / sqrt3 - explicit CurrentSensor(CurrentSensorInput const& current_sensor_input) - : GenericCurrentSensor{current_sensor_input}, - i_sigma_{current_sensor_input.i_sigma / base_power}, // TODO use base_current - i_angle_sigma_{current_sensor_input.i_angle_sigma / - base_power}, // TODO use base_current - i_angle_measured_{current_sensor_input.i_angle_measured} { - set_current(current_sensor_input.i_measured); + explicit CurrentSensor(CurrentSensorInput const& current_sensor_input, double u_rated) + : GenericCurrentSensor{current_sensor_input}, i_angle_measured_{current_sensor_input.i_angle_measured} { + set_current(current_sensor_input, u_rated); }; UpdateChange update(CurrentSensorUpdate const& update_data) { @@ -106,8 +101,11 @@ template class CurrentSensor : public Ge double i_sigma_{}; double i_angle_sigma_{}; - void set_current(RealValue const& i_measured) { - // TODO + void set_current(CurrentSensorInput const& input, double const& u_rated) { + double base_current = base_power_3p / u_rated / sqrt3 double scalar = convert_direction() / base_current; + i_sigma_ = input.i_sigma / base_current; + i_angle_sigma_ = input.i_angle_sigma / base_current; // TODO i_angle_sigma is optional + i_measured_ = input.i_measured / base_current; } CurrentSensorCalcParam sym_calc_param() const final { From 901107d5df97c63287754bcefdb393c337074193 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 31 Dec 2024 09:53:30 +0100 Subject: [PATCH 15/38] i angle sigma without division Signed-off-by: petersalemink95 --- .../include/power_grid_model/component/current_sensor.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 33c65b213..489303e84 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -80,7 +80,9 @@ template class CurrentSensor : public Ge template using OutputType = CurrentSensorOutput; explicit CurrentSensor(CurrentSensorInput const& current_sensor_input, double u_rated) - : GenericCurrentSensor{current_sensor_input}, i_angle_measured_{current_sensor_input.i_angle_measured} { + : GenericCurrentSensor{current_sensor_input}, + i_angle_measured_{current_sensor_input.i_angle_measured}, + i_angle_sigma_{current_sensor_input.i_angle_sigma} { // TODO i_angle_sigma is optional set_current(current_sensor_input, u_rated); }; @@ -102,9 +104,9 @@ template class CurrentSensor : public Ge double i_angle_sigma_{}; void set_current(CurrentSensorInput const& input, double const& u_rated) { - double base_current = base_power_3p / u_rated / sqrt3 double scalar = convert_direction() / base_current; + double base_current = base_power_3p / u_rated / sqrt3; + double scalar = convert_direction() / base_current; i_sigma_ = input.i_sigma / base_current; - i_angle_sigma_ = input.i_angle_sigma / base_current; // TODO i_angle_sigma is optional i_measured_ = input.i_measured / base_current; } From 8a30ac762cafa1f4774d7fb53154aea5a0990657 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 31 Dec 2024 10:01:46 +0100 Subject: [PATCH 16/38] use scalar Signed-off-by: petersalemink95 --- .../include/power_grid_model/component/current_sensor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 489303e84..a0c02fb45 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -107,7 +107,7 @@ template class CurrentSensor : public Ge double base_current = base_power_3p / u_rated / sqrt3; double scalar = convert_direction() / base_current; i_sigma_ = input.i_sigma / base_current; - i_measured_ = input.i_measured / base_current; + i_measured_ = input.i_measured * scalar; } CurrentSensorCalcParam sym_calc_param() const final { From 5983d7f9a16acd02957b5a60df2a606ea366433d Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 31 Dec 2024 10:14:12 +0100 Subject: [PATCH 17/38] add dummy variables for passing build Signed-off-by: petersalemink95 --- .../include/power_grid_model/component/current_sensor.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index a0c02fb45..5dd682879 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -88,6 +88,7 @@ template class CurrentSensor : public Ge UpdateChange update(CurrentSensorUpdate const& update_data) { // TODO + auto const dummy = update_data; // TODO: remove this line return {false, false}; } @@ -129,6 +130,8 @@ template class CurrentSensor : public Ge template CurrentSensorOutput get_generic_output(ComplexValue const& i) const { CurrentSensorOutput output{}; + // TODO + auto const dummy = i; // TODO: remove this line return output; } }; From 5db6375b9d4c5deed0e8c4992f78a16673751965 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 31 Dec 2024 11:21:48 +0100 Subject: [PATCH 18/38] DCO Remediation Commit for petersalemink95 I, petersalemink95 , hereby add my Signed-off-by to this commit: 7c32e89118f18a12462a8e5c68d098782b22460f Signed-off-by: petersalemink95 --- tests/cpp_unit_tests/test_current_sensor.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index 367f3ab4a..ee8eb94d5 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -6,4 +6,7 @@ #include -namespace power_grid_model {} // namespace power_grid_model +namespace power_grid_model { +TEST_CASE("Test current sensor") {} + +} // namespace power_grid_model From 768037e35a252d71f363f3362b9c1876a14f18a9 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 31 Dec 2024 13:46:46 +0100 Subject: [PATCH 19/38] calc param with separate i and i_angle variance Signed-off-by: petersalemink95 --- .../calculation_parameters.hpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp index 39a8e7318..663e942a0 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp @@ -94,11 +94,6 @@ template struct UniformComplexRandomVariable { // If the imaginary part is NaN, it means the angle calculation is not correct template using VoltageSensorCalcParam = UniformComplexRandomVariable; -// current sensor calculation parameters for state estimation -// The value is the complex current -// If the imaginary part is NaN, it means the angle calculation is not correct -template using CurrentSensorCalcParam = UniformComplexRandomVariable; - // power sensor calculation parameters for state estimation // The value is the complex power // * for appliances, it is always in injection direction @@ -113,6 +108,20 @@ template struct PowerSensorCalcParam { RealValue q_variance{}; // variance (sigma^2) of the error range of the reactive power, in p.u. }; +// current sensor calculation parameters for state estimation +// The value is the complex current +// * for appliances, it is always in injection direction +// * for branches, the direction is node -> branch +template struct CurrentSensorCalcParam { + using sym = sym_type; + + static constexpr bool symmetric{is_symmetric_v}; + + ComplexValue value{}; + RealValue i_variance{}; // variance (sigma^2) of the error range of the current, in p.u. + RealValue i_angle_variance{}; // variance (sigma^2) of the error range of the current angle, in p.u. +}; + template concept sensor_calc_param_type = std::derived_from> || From 48656f6f5ec39e04a6ec95d9d2df7b161cd82424 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 31 Dec 2024 14:03:51 +0100 Subject: [PATCH 20/38] first tests - temp save Signed-off-by: petersalemink95 --- .../component/current_sensor.hpp | 2 +- tests/cpp_unit_tests/test_current_sensor.cpp | 60 ++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 5dd682879..8b6598b9f 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -39,7 +39,7 @@ class GenericCurrentSensor : public Sensor { SensorShortCircuitOutput get_null_sc_output() const { return {.id = id(), .energized = 0}; } // getter for calculation param - template PowerSensorCalcParam calc_param() const { + template CurrentSensorCalcParam calc_param() const { if constexpr (is_symmetric_v) { return sym_calc_param(); } else { diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index ee8eb94d5..6c3fcac5c 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -7,6 +7,64 @@ #include namespace power_grid_model { -TEST_CASE("Test current sensor") {} +TEST_CASE("Test current sensor") { + SUBCASE("Symmetric Current Sensor - generator, branch_from, branch_to, source") { + for (auto const terminal_type : {MeasuredTerminalType::generator, MeasuredTerminalType::branch_from, + MeasuredTerminalType::branch_to, MeasuredTerminalType::source}) { + CAPTURE(terminal_type); + + CurrentSensorInput sym_current_sensor_input{}; + sym_current_sensor_input.id = 0; + sym_current_sensor_input.measured_object = 1; + sym_current_sensor_input.measured_terminal_type = terminal_type; + sym_current_sensor_input.angle_measurement_type = AngleMeasurementType::local; + sym_current_sensor_input.i_sigma = 1.0; + sym_current_sensor_input.i_measured = 1.0 * 1e3; + sym_current_sensor_input.i_angle_measured = 0.0; + sym_current_sensor_input.i_angle_sigma = nan; + + double const u_rated = 10.0e3; + double const base_current = base_power_3p / u_rated / sqrt3; + + ComplexValue const i_sym = (1.0 * 1e3 + 1i * 0.0) / base_current; + ComplexValue const i_asym = i_sym * RealValue{1.0}; + + CurrentSensor sym_current_sensor{sym_current_sensor_input, u_rated}; + + CurrentSensorCalcParam sym_sensor_param = sym_current_sensor.calc_param(); + CurrentSensorCalcParam asym_sensor_param = sym_current_sensor.calc_param(); + + CurrentSensorOutput sym_sensor_output = sym_current_sensor.get_output(i_sym); + CurrentSensorOutput sym_sensor_output_asym_param = + sym_current_sensor.get_output(i_asym); + + // Check symmetric sensor output for symmetric parameters + CHECK(sym_sensor_param.i_variance == doctest::Approx(0.0)); + CHECK(sym_sensor_param.i_angle_variance == doctest::Approx(0.0)); + CHECK(real(sym_sensor_param.value) == doctest::Approx(0.0)); + CHECK(imag(sym_sensor_param.value) == doctest::Approx(0.0)); + + CHECK(sym_sensor_output.id == 0); + CHECK(sym_sensor_output.energized == 0); + CHECK(sym_sensor_output.i_residual == doctest::Approx(0.0)); + CHECK(sym_sensor_output.i_angle_residual == doctest::Approx(0.0)); + + // Check symmetric sensor output for asymmetric parameters + CHECK(asym_sensor_param.i_variance[0] == doctest::Approx(0.0)); + CHECK(asym_sensor_param.i_angle_variance[1] == doctest::Approx(0.0)); + CHECK(real(asym_sensor_param.value[0]) == doctest::Approx(0.0)); + CHECK(imag(asym_sensor_param.value[1]) == doctest::Approx(0.0)); + + CHECK(sym_sensor_output_asym_param.id == 0); + CHECK(sym_sensor_output_asym_param.energized == 0); + CHECK(sym_sensor_output_asym_param.i_residual[0] == doctest::Approx(0.0)); + CHECK(sym_sensor_output_asym_param.i_angle_residual[1] == doctest::Approx(0.0)); + + CHECK(sym_current_sensor.get_terminal_type() == terminal_type); + + CHECK(sym_current_sensor.get_angle_measurement_type() == AngleMeasurementType::local); + } + } +} } // namespace power_grid_model From 513ce1e1d3888331294b513fc50c899461a2d60f Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 31 Dec 2024 14:08:39 +0100 Subject: [PATCH 21/38] unused vairables Signed-off-by: petersalemink95 --- .../include/power_grid_model/component/current_sensor.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 8b6598b9f..602503681 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -88,7 +88,7 @@ template class CurrentSensor : public Ge UpdateChange update(CurrentSensorUpdate const& update_data) { // TODO - auto const dummy = update_data; // TODO: remove this line + (void)update_data; // Suppress unused variable warning return {false, false}; } @@ -131,7 +131,7 @@ template class CurrentSensor : public Ge CurrentSensorOutput get_generic_output(ComplexValue const& i) const { CurrentSensorOutput output{}; // TODO - auto const dummy = i; // TODO: remove this line + (void)i; // Suppress unused variable warning return output; } }; From 812f018ee3f77704c1282c4e0be6cc3406bc5a9a Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 31 Dec 2024 14:19:55 +0100 Subject: [PATCH 22/38] passing tests Signed-off-by: petersalemink95 --- tests/cpp_unit_tests/test_current_sensor.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index 6c3fcac5c..a637dd536 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -44,10 +44,10 @@ TEST_CASE("Test current sensor") { CHECK(real(sym_sensor_param.value) == doctest::Approx(0.0)); CHECK(imag(sym_sensor_param.value) == doctest::Approx(0.0)); - CHECK(sym_sensor_output.id == 0); - CHECK(sym_sensor_output.energized == 0); - CHECK(sym_sensor_output.i_residual == doctest::Approx(0.0)); - CHECK(sym_sensor_output.i_angle_residual == doctest::Approx(0.0)); + CHECK(is_nan(sym_sensor_output.id)); + CHECK(is_nan(sym_sensor_output.energized)); + CHECK(is_nan(sym_sensor_output.i_residual)); + CHECK(is_nan(sym_sensor_output.i_angle_residual)); // Check symmetric sensor output for asymmetric parameters CHECK(asym_sensor_param.i_variance[0] == doctest::Approx(0.0)); @@ -55,10 +55,10 @@ TEST_CASE("Test current sensor") { CHECK(real(asym_sensor_param.value[0]) == doctest::Approx(0.0)); CHECK(imag(asym_sensor_param.value[1]) == doctest::Approx(0.0)); - CHECK(sym_sensor_output_asym_param.id == 0); - CHECK(sym_sensor_output_asym_param.energized == 0); - CHECK(sym_sensor_output_asym_param.i_residual[0] == doctest::Approx(0.0)); - CHECK(sym_sensor_output_asym_param.i_angle_residual[1] == doctest::Approx(0.0)); + CHECK(is_nan(sym_sensor_output_asym_param.id)); + CHECK(is_nan(sym_sensor_output_asym_param.energized)); + CHECK(is_nan(sym_sensor_output_asym_param.i_residual[0])); + CHECK(is_nan(sym_sensor_output_asym_param.i_angle_residual[1])); CHECK(sym_current_sensor.get_terminal_type() == terminal_type); From d1fbb473260b0d1293e982dceb69d691ab25daa7 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Thu, 2 Jan 2025 10:56:33 +0100 Subject: [PATCH 23/38] fill update function Signed-off-by: petersalemink95 --- .../component/current_sensor.hpp | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 602503681..790b04771 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -86,9 +86,17 @@ template class CurrentSensor : public Ge set_current(current_sensor_input, u_rated); }; - UpdateChange update(CurrentSensorUpdate const& update_data) { - // TODO - (void)update_data; // Suppress unused variable warning + UpdateChange update(CurrentSensorUpdate const& update_data, double const& u_rated) { + double const base_current = base_power_3p / u_rated / sqrt3; + double const scalar = convert_direction() / base_current; + if (!is_nan(update_data.i_sigma)) { + i_sigma_ = update_data.i_sigma * scalar; + } + if (!is_nan(update_data.i_angle_sigma)) { + i_angle_sigma_ = update_data.i_angle_sigma; + } + update_real_value(update_data.i_measured, i_measured_, scalar); + update_real_value(update_data.i_angle_measured, i_angle_measured_, 1.0); return {false, false}; } @@ -105,9 +113,9 @@ template class CurrentSensor : public Ge double i_angle_sigma_{}; void set_current(CurrentSensorInput const& input, double const& u_rated) { - double base_current = base_power_3p / u_rated / sqrt3; - double scalar = convert_direction() / base_current; - i_sigma_ = input.i_sigma / base_current; + double const base_current = base_power_3p / u_rated / sqrt3; + double const scalar = convert_direction() / base_current; + i_sigma_ = input.i_sigma * scalar; i_measured_ = input.i_measured * scalar; } From d9c5ab2756855b819648153d73d2a94b93625cd6 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Thu, 2 Jan 2025 14:13:08 +0100 Subject: [PATCH 24/38] implement inverse + test sym inverse Signed-off-by: petersalemink95 --- .../component/current_sensor.hpp | 16 +++- tests/cpp_unit_tests/test_current_sensor.cpp | 73 +++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 790b04771..194eb994e 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -89,6 +89,7 @@ template class CurrentSensor : public Ge UpdateChange update(CurrentSensorUpdate const& update_data, double const& u_rated) { double const base_current = base_power_3p / u_rated / sqrt3; double const scalar = convert_direction() / base_current; + if (!is_nan(update_data.i_sigma)) { i_sigma_ = update_data.i_sigma * scalar; } @@ -100,14 +101,23 @@ template class CurrentSensor : public Ge return {false, false}; } - PowerSensorUpdate inverse(PowerSensorUpdate update_data) const { - // TODO + CurrentSensorUpdate inverse(CurrentSensorUpdate update_data, + double const& u_rated) const { + assert(update_data.id == this->id() || is_nan(update_data.id)); + + double const base_current = base_power_3p / u_rated / sqrt3; + double const scalar = convert_direction() * base_current; + + set_if_not_nan(update_data.i_sigma, i_sigma_ * scalar); + set_if_not_nan(update_data.i_angle_sigma, i_angle_sigma_); + set_if_not_nan(update_data.i_measured, i_measured_ * scalar); + set_if_not_nan(update_data.i_angle_measured, i_angle_measured_); return update_data; } private: - ComplexValue i_measured_{}; + RealValue i_measured_{}; RealValue i_angle_measured_{}; double i_sigma_{}; double i_angle_sigma_{}; diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index a637dd536..eafa5c747 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -7,6 +7,18 @@ #include namespace power_grid_model { +namespace { +auto const r_nan = RealValue{nan}; + +void check_nan_preserving_equality(std::floating_point auto actual, std::floating_point auto expected) { + if (is_nan(expected)) { + is_nan(actual); + } else { + CHECK(actual == doctest::Approx(expected)); + } +} +} // namespace + TEST_CASE("Test current sensor") { SUBCASE("Symmetric Current Sensor - generator, branch_from, branch_to, source") { for (auto const terminal_type : {MeasuredTerminalType::generator, MeasuredTerminalType::branch_from, @@ -65,6 +77,67 @@ TEST_CASE("Test current sensor") { CHECK(sym_current_sensor.get_angle_measurement_type() == AngleMeasurementType::local); } } + SUBCASE("Update inverse - sym") { + constexpr auto i_measured = 1.0; + constexpr auto i_angle_measured = 2.0; + constexpr auto i_sigma = 3.0; + constexpr auto i_angle_sigma = 4.0; + constexpr auto u_rated = 10.0e3; + CurrentSensor const current_sensor{{1, 1, MeasuredTerminalType::branch3_1, + AngleMeasurementType::local, i_sigma, i_angle_sigma, + i_measured, i_angle_measured}, + u_rated}; + + CurrentSensorUpdate cs_update{1, nan, nan, nan, nan}; + auto expected = cs_update; + + SUBCASE("Identical") { + // default values + } + + SUBCASE("i_sigma") { + SUBCASE("same") { cs_update.i_sigma = i_sigma; } + SUBCASE("different") { cs_update.i_sigma = 0.0; } + expected.i_sigma = i_sigma; + } + + SUBCASE("i_angle_sigma") { + SUBCASE("same") { cs_update.i_angle_sigma = i_angle_sigma; } + SUBCASE("different") { cs_update.i_angle_sigma = 0.0; } + expected.i_angle_sigma = i_angle_sigma; + } + + SUBCASE("i_measured") { + SUBCASE("same") { cs_update.i_measured = i_measured; } + SUBCASE("different") { cs_update.i_measured = 0.0; } + expected.i_measured = i_measured; + } + + SUBCASE("i_angle_measured") { + SUBCASE("same") { cs_update.i_angle_measured = i_angle_measured; } + SUBCASE("different") { cs_update.i_angle_measured = 0.0; } + expected.i_angle_measured = i_angle_measured; + } + + SUBCASE("multiple") { + cs_update.i_sigma = 0.0; + cs_update.i_angle_sigma = 0.0; + cs_update.i_measured = 0.0; + cs_update.i_angle_measured = 0.0; + expected.i_sigma = i_sigma; + expected.i_angle_sigma = i_angle_sigma; + expected.i_measured = i_measured; + expected.i_angle_measured = i_angle_measured; + } + + auto const inv = current_sensor.inverse(cs_update, u_rated); + + CHECK(inv.id == expected.id); + check_nan_preserving_equality(inv.i_sigma, expected.i_sigma); + check_nan_preserving_equality(inv.i_angle_sigma, expected.i_angle_sigma); + check_nan_preserving_equality(inv.i_measured, expected.i_measured); + check_nan_preserving_equality(inv.i_angle_measured, expected.i_angle_measured); + } } } // namespace power_grid_model From 19ca13f29e6e4a9c409f91d79e20f9bb342485a8 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Thu, 2 Jan 2025 15:37:25 +0100 Subject: [PATCH 25/38] fix scalars Signed-off-by: petersalemink95 --- .../include/power_grid_model/component/current_sensor.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 194eb994e..620df7498 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -91,7 +91,7 @@ template class CurrentSensor : public Ge double const scalar = convert_direction() / base_current; if (!is_nan(update_data.i_sigma)) { - i_sigma_ = update_data.i_sigma * scalar; + i_sigma_ = update_data.i_sigma / base_current; } if (!is_nan(update_data.i_angle_sigma)) { i_angle_sigma_ = update_data.i_angle_sigma; @@ -108,7 +108,7 @@ template class CurrentSensor : public Ge double const base_current = base_power_3p / u_rated / sqrt3; double const scalar = convert_direction() * base_current; - set_if_not_nan(update_data.i_sigma, i_sigma_ * scalar); + set_if_not_nan(update_data.i_sigma, i_sigma_ * base_current); set_if_not_nan(update_data.i_angle_sigma, i_angle_sigma_); set_if_not_nan(update_data.i_measured, i_measured_ * scalar); set_if_not_nan(update_data.i_angle_measured, i_angle_measured_); @@ -125,7 +125,7 @@ template class CurrentSensor : public Ge void set_current(CurrentSensorInput const& input, double const& u_rated) { double const base_current = base_power_3p / u_rated / sqrt3; double const scalar = convert_direction() / base_current; - i_sigma_ = input.i_sigma * scalar; + i_sigma_ = input.i_sigma / base_current; i_measured_ = input.i_measured * scalar; } From b1ca230d4cbe36aa6c920d434b12a061b8c644dc Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Thu, 2 Jan 2025 15:56:24 +0100 Subject: [PATCH 26/38] test asym inverse Signed-off-by: petersalemink95 --- tests/cpp_unit_tests/test_current_sensor.cpp | 83 ++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index eafa5c747..f693372e4 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -17,6 +17,12 @@ void check_nan_preserving_equality(std::floating_point auto actual, std::floatin CHECK(actual == doctest::Approx(expected)); } } +void check_nan_preserving_equality(RealValue const& actual, RealValue const& expected) { + for (auto i : {0, 1, 2}) { + CAPTURE(i); + check_nan_preserving_equality(actual(i), expected(i)); + } +} } // namespace TEST_CASE("Test current sensor") { @@ -138,6 +144,83 @@ TEST_CASE("Test current sensor") { check_nan_preserving_equality(inv.i_measured, expected.i_measured); check_nan_preserving_equality(inv.i_angle_measured, expected.i_angle_measured); } + + SUBCASE("Update inverse - asym") { + RealValue i_measured = {1.0, 2.0, 3.0}; + RealValue i_angle_measured = {4.0, 5.0, 6.0}; + constexpr auto i_sigma = 3.0; + constexpr auto i_angle_sigma = 4.0; + constexpr auto u_rated = 10.0e3; + + CurrentSensorUpdate cs_update{1, nan, nan, r_nan, r_nan}; + auto expected = cs_update; + + SUBCASE("Identical") { + // default values + } + + SUBCASE("i_sigma") { + SUBCASE("same") { cs_update.i_sigma = i_sigma; } + SUBCASE("different") { cs_update.i_sigma = 0.0; } + expected.i_sigma = i_sigma; + } + + SUBCASE("i_angle_sigma") { + SUBCASE("same") { cs_update.i_angle_sigma = i_angle_sigma; } + SUBCASE("different") { cs_update.i_angle_sigma = 0.0; } + expected.i_angle_sigma = i_angle_sigma; + } + + SUBCASE("i_measured") { + SUBCASE("same") { cs_update.i_measured = i_measured; } + SUBCASE("1 different") { + cs_update.i_measured = {0.0, nan, nan}; + expected.i_measured = {i_measured(0), nan, nan}; + } + SUBCASE("all different") { + cs_update.i_measured = {0.0, 0.1, 0.2}; + expected.i_measured = i_measured; + } + } + + SUBCASE("i_angle_measured") { + SUBCASE("same") { cs_update.i_angle_measured = i_angle_measured; } + SUBCASE("1 different") { + cs_update.i_angle_measured = {0.0, nan, nan}; + expected.i_angle_measured = {i_angle_measured(0), nan, nan}; + } + SUBCASE("all different") { + cs_update.i_angle_measured = {0.0, 0.1, 0.2}; + expected.i_angle_measured = i_angle_measured; + } + } + + SUBCASE("multiple") { + cs_update.i_sigma = 0.0; + cs_update.i_angle_sigma = 0.1; + cs_update.i_measured = {0.0, 0.2, 0.4}; + cs_update.i_angle_measured = {0.0, 0.3, 0.6}; + expected.i_sigma = i_sigma; + expected.i_angle_sigma = i_angle_sigma; + expected.i_measured = i_measured; + expected.i_angle_measured = i_angle_measured; + } + + for (auto const measured_terminal_type : + {MeasuredTerminalType::branch_from, MeasuredTerminalType::generator, MeasuredTerminalType::load}) { + CurrentSensor const current_sensor{{1, 1, measured_terminal_type, AngleMeasurementType::local, + i_sigma, i_angle_sigma, i_measured, i_angle_measured}, + u_rated}; + + auto const inv = current_sensor.inverse(cs_update, u_rated); + + CHECK(inv.id == expected.id); + check_nan_preserving_equality(inv.i_sigma, expected.i_sigma); + check_nan_preserving_equality(inv.i_angle_sigma, expected.i_angle_sigma); + check_nan_preserving_equality(inv.i_measured, expected.i_measured); + check_nan_preserving_equality(inv.i_angle_measured, expected.i_angle_measured); + } + } } } // namespace power_grid_model From 285f5f6c696adbc7476a2de173d4f98b7921d448 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Thu, 2 Jan 2025 16:01:38 +0100 Subject: [PATCH 27/38] move comment Signed-off-by: petersalemink95 --- .../include/power_grid_model/component/current_sensor.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 620df7498..3a0d6258a 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -82,7 +82,7 @@ template class CurrentSensor : public Ge explicit CurrentSensor(CurrentSensorInput const& current_sensor_input, double u_rated) : GenericCurrentSensor{current_sensor_input}, i_angle_measured_{current_sensor_input.i_angle_measured}, - i_angle_sigma_{current_sensor_input.i_angle_sigma} { // TODO i_angle_sigma is optional + i_angle_sigma_{current_sensor_input.i_angle_sigma} { set_current(current_sensor_input, u_rated); }; @@ -129,6 +129,8 @@ template class CurrentSensor : public Ge i_measured_ = input.i_measured * scalar; } + // TODO when filling the functions below take in mind that i_angle_sigma is optional + CurrentSensorCalcParam sym_calc_param() const final { CurrentSensorCalcParam calc_param{}; // TODO From 87fb7c124fdb263fcdb0d01dc7b5c64eb19d1a7e Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Fri, 3 Jan 2025 08:54:55 +0100 Subject: [PATCH 28/38] double variances Signed-off-by: petersalemink95 --- .../include/power_grid_model/calculation_parameters.hpp | 4 ++-- tests/cpp_unit_tests/test_current_sensor.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp index 663e942a0..5c3b970f8 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp @@ -118,8 +118,8 @@ template struct CurrentSensorCalcParam { static constexpr bool symmetric{is_symmetric_v}; ComplexValue value{}; - RealValue i_variance{}; // variance (sigma^2) of the error range of the current, in p.u. - RealValue i_angle_variance{}; // variance (sigma^2) of the error range of the current angle, in p.u. + double i_variance{}; // variance (sigma^2) of the error range of the current, in p.u. + double i_angle_variance{}; // variance (sigma^2) of the error range of the current angle, in p.u. }; template diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index f693372e4..da6dffb69 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -68,8 +68,8 @@ TEST_CASE("Test current sensor") { CHECK(is_nan(sym_sensor_output.i_angle_residual)); // Check symmetric sensor output for asymmetric parameters - CHECK(asym_sensor_param.i_variance[0] == doctest::Approx(0.0)); - CHECK(asym_sensor_param.i_angle_variance[1] == doctest::Approx(0.0)); + CHECK(asym_sensor_param.i_variance == doctest::Approx(0.0)); + CHECK(asym_sensor_param.i_angle_variance == doctest::Approx(0.0)); CHECK(real(asym_sensor_param.value[0]) == doctest::Approx(0.0)); CHECK(imag(asym_sensor_param.value[1]) == doctest::Approx(0.0)); From 4885381d495e3658fe8becaf6f3f265ee5e4025e Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Fri, 3 Jan 2025 09:09:51 +0100 Subject: [PATCH 29/38] add angle measurement type to calc param Signed-off-by: petersalemink95 --- .../include/power_grid_model/calculation_parameters.hpp | 1 + tests/cpp_unit_tests/test_current_sensor.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp index 5c3b970f8..8c92a6cdc 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp @@ -117,6 +117,7 @@ template struct CurrentSensorCalcParam { static constexpr bool symmetric{is_symmetric_v}; + AngleMeasurementType angle_measurement_type{}; ComplexValue value{}; double i_variance{}; // variance (sigma^2) of the error range of the current, in p.u. double i_angle_variance{}; // variance (sigma^2) of the error range of the current angle, in p.u. diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index da6dffb69..78b6ee8c2 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -57,6 +57,7 @@ TEST_CASE("Test current sensor") { sym_current_sensor.get_output(i_asym); // Check symmetric sensor output for symmetric parameters + CHECK(sym_sensor_param.angle_measurement_type == AngleMeasurementType::local); CHECK(sym_sensor_param.i_variance == doctest::Approx(0.0)); CHECK(sym_sensor_param.i_angle_variance == doctest::Approx(0.0)); CHECK(real(sym_sensor_param.value) == doctest::Approx(0.0)); From ac3511e2cafcd7a963ef0b372cf1b67375d67cbb Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 7 Jan 2025 08:39:33 +0100 Subject: [PATCH 30/38] use inv_sqrt3 Signed-off-by: petersalemink95 --- .../include/power_grid_model/component/current_sensor.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 3a0d6258a..5911d9d47 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -87,7 +87,7 @@ template class CurrentSensor : public Ge }; UpdateChange update(CurrentSensorUpdate const& update_data, double const& u_rated) { - double const base_current = base_power_3p / u_rated / sqrt3; + double const base_current = base_power_3p * inv_sqrt3 / u_rated; double const scalar = convert_direction() / base_current; if (!is_nan(update_data.i_sigma)) { @@ -105,7 +105,7 @@ template class CurrentSensor : public Ge double const& u_rated) const { assert(update_data.id == this->id() || is_nan(update_data.id)); - double const base_current = base_power_3p / u_rated / sqrt3; + double const base_current = base_power_3p * inv_sqrt3 / u_rated; double const scalar = convert_direction() * base_current; set_if_not_nan(update_data.i_sigma, i_sigma_ * base_current); @@ -123,7 +123,7 @@ template class CurrentSensor : public Ge double i_angle_sigma_{}; void set_current(CurrentSensorInput const& input, double const& u_rated) { - double const base_current = base_power_3p / u_rated / sqrt3; + double const base_current = base_power_3p * inv_sqrt3 / u_rated; double const scalar = convert_direction() / base_current; i_sigma_ = input.i_sigma / base_current; i_measured_ = input.i_measured * scalar; From da8c0ce53498221fe00811bf8ff24ee03479883c Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 7 Jan 2025 09:58:05 +0100 Subject: [PATCH 31/38] remove convert_direction + test only branch Signed-off-by: petersalemink95 --- .../component/current_sensor.hpp | 16 +++----------- tests/cpp_unit_tests/test_current_sensor.cpp | 22 +++++++++---------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 5911d9d47..c3e3aaf87 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -47,15 +47,6 @@ class GenericCurrentSensor : public Sensor { } } - protected: - double convert_direction() const { - if (terminal_type_ == MeasuredTerminalType::load || terminal_type_ == MeasuredTerminalType::shunt) { - return -1.0; // For shunt and load the direction in the math model is opposite to the direction in the - // physical model - } - return 1.0; - } - private: MeasuredTerminalType terminal_type_; AngleMeasurementType angle_measurement_type_; @@ -88,7 +79,7 @@ template class CurrentSensor : public Ge UpdateChange update(CurrentSensorUpdate const& update_data, double const& u_rated) { double const base_current = base_power_3p * inv_sqrt3 / u_rated; - double const scalar = convert_direction() / base_current; + double const scalar = 1.0 / base_current; if (!is_nan(update_data.i_sigma)) { i_sigma_ = update_data.i_sigma / base_current; @@ -106,11 +97,10 @@ template class CurrentSensor : public Ge assert(update_data.id == this->id() || is_nan(update_data.id)); double const base_current = base_power_3p * inv_sqrt3 / u_rated; - double const scalar = convert_direction() * base_current; set_if_not_nan(update_data.i_sigma, i_sigma_ * base_current); set_if_not_nan(update_data.i_angle_sigma, i_angle_sigma_); - set_if_not_nan(update_data.i_measured, i_measured_ * scalar); + set_if_not_nan(update_data.i_measured, i_measured_ * base_current); set_if_not_nan(update_data.i_angle_measured, i_angle_measured_); return update_data; @@ -124,7 +114,7 @@ template class CurrentSensor : public Ge void set_current(CurrentSensorInput const& input, double const& u_rated) { double const base_current = base_power_3p * inv_sqrt3 / u_rated; - double const scalar = convert_direction() / base_current; + double const scalar = 1.0 / base_current; i_sigma_ = input.i_sigma / base_current; i_measured_ = input.i_measured * scalar; } diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index 78b6ee8c2..1955518d6 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -152,6 +152,7 @@ TEST_CASE("Test current sensor") { constexpr auto i_sigma = 3.0; constexpr auto i_angle_sigma = 4.0; constexpr auto u_rated = 10.0e3; + MeasuredTerminalType const measured_terminal_type = MeasuredTerminalType::branch_from; CurrentSensorUpdate cs_update{1, nan, nan, r_nan, r_nan}; auto expected = cs_update; @@ -207,20 +208,17 @@ TEST_CASE("Test current sensor") { expected.i_angle_measured = i_angle_measured; } - for (auto const measured_terminal_type : - {MeasuredTerminalType::branch_from, MeasuredTerminalType::generator, MeasuredTerminalType::load}) { - CurrentSensor const current_sensor{{1, 1, measured_terminal_type, AngleMeasurementType::local, - i_sigma, i_angle_sigma, i_measured, i_angle_measured}, - u_rated}; + CurrentSensor const current_sensor{{1, 1, measured_terminal_type, AngleMeasurementType::local, + i_sigma, i_angle_sigma, i_measured, i_angle_measured}, + u_rated}; - auto const inv = current_sensor.inverse(cs_update, u_rated); + auto const inv = current_sensor.inverse(cs_update, u_rated); - CHECK(inv.id == expected.id); - check_nan_preserving_equality(inv.i_sigma, expected.i_sigma); - check_nan_preserving_equality(inv.i_angle_sigma, expected.i_angle_sigma); - check_nan_preserving_equality(inv.i_measured, expected.i_measured); - check_nan_preserving_equality(inv.i_angle_measured, expected.i_angle_measured); - } + CHECK(inv.id == expected.id); + check_nan_preserving_equality(inv.i_sigma, expected.i_sigma); + check_nan_preserving_equality(inv.i_angle_sigma, expected.i_angle_sigma); + check_nan_preserving_equality(inv.i_measured, expected.i_measured); + check_nan_preserving_equality(inv.i_angle_measured, expected.i_angle_measured); } } From 3691a732968e05c44bf8af3e9b5cb34c6cba2362 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Tue, 7 Jan 2025 11:37:04 +0100 Subject: [PATCH 32/38] only accept branches Signed-off-by: petersalemink95 --- .../power_grid_model/common/exception.hpp | 8 ++++++++ .../component/current_sensor.hpp | 12 ++++++++++++ tests/cpp_unit_tests/test_current_sensor.cpp | 17 ++++++++++++++--- 3 files changed, 34 insertions(+), 3 deletions(-) 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 c97c84e93..a995401cf 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 @@ -163,6 +163,14 @@ class InvalidMeasuredObject : public PowerGridError { } }; +class InvalidMeasuredTerminalType : public PowerGridError { + public: + InvalidMeasuredTerminalType(MeasuredTerminalType const terminal_type, std::string const& sensor) { + append_msg(sensor + " measurement is not supported for object of type " + + detail::to_string(static_cast(terminal_type))); + } +}; + class InvalidRegulatedObject : public PowerGridError { public: InvalidRegulatedObject(std::string const& object, std::string const& regulator) { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index c3e3aaf87..95fd3ca59 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -9,6 +9,7 @@ #include "../calculation_parameters.hpp" #include "../common/common.hpp" #include "../common/enum.hpp" +#include "../common/exception.hpp" namespace power_grid_model { @@ -75,6 +76,17 @@ template class CurrentSensor : public Ge i_angle_measured_{current_sensor_input.i_angle_measured}, i_angle_sigma_{current_sensor_input.i_angle_sigma} { set_current(current_sensor_input, u_rated); + + switch (current_sensor_input.measured_terminal_type) { + case MeasuredTerminalType::branch_from: + case MeasuredTerminalType::branch_to: + case MeasuredTerminalType::branch3_1: + case MeasuredTerminalType::branch3_2: + case MeasuredTerminalType::branch3_3: + break; + default: + throw InvalidMeasuredTerminalType{current_sensor_input.measured_terminal_type, "Current sensor"}; + } }; UpdateChange update(CurrentSensorUpdate const& update_data, double const& u_rated) { diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index 1955518d6..2403331d1 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -26,9 +26,10 @@ void check_nan_preserving_equality(RealValue const& actual, RealVa } // namespace TEST_CASE("Test current sensor") { - SUBCASE("Symmetric Current Sensor - generator, branch_from, branch_to, source") { - for (auto const terminal_type : {MeasuredTerminalType::generator, MeasuredTerminalType::branch_from, - MeasuredTerminalType::branch_to, MeasuredTerminalType::source}) { + SUBCASE("Symmetric Current Sensor") { + for (auto const terminal_type : + {MeasuredTerminalType::branch_from, MeasuredTerminalType::branch_to, MeasuredTerminalType::branch3_1, + MeasuredTerminalType::branch3_2, MeasuredTerminalType::branch3_3}) { CAPTURE(terminal_type); CurrentSensorInput sym_current_sensor_input{}; @@ -82,6 +83,16 @@ TEST_CASE("Test current sensor") { CHECK(sym_current_sensor.get_terminal_type() == terminal_type); CHECK(sym_current_sensor.get_angle_measurement_type() == AngleMeasurementType::local); + + SUBCASE("Wrong measured terminal type") { + for (auto const terminal_type : + {MeasuredTerminalType::source, MeasuredTerminalType::shunt, MeasuredTerminalType::load, + MeasuredTerminalType::generator, MeasuredTerminalType::node}) { + CHECK_THROWS_AS((CurrentSensor{ + {1, 1, terminal_type, AngleMeasurementType::local, 1.0, 1.0, 1.0, 1.0}, 1.0}), + InvalidMeasuredTerminalType); + } + } } } SUBCASE("Update inverse - sym") { From f30dd34e7abd1d953a1967b17952e75e23ed7361 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Wed, 8 Jan 2025 08:49:47 +0100 Subject: [PATCH 33/38] single base_current_ Signed-off-by: petersalemink95 --- .../component/current_sensor.hpp | 31 +++++++++---------- tests/cpp_unit_tests/test_current_sensor.cpp | 4 +-- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 95fd3ca59..b03bfffb0 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -74,8 +74,9 @@ template class CurrentSensor : public Ge explicit CurrentSensor(CurrentSensorInput const& current_sensor_input, double u_rated) : GenericCurrentSensor{current_sensor_input}, i_angle_measured_{current_sensor_input.i_angle_measured}, - i_angle_sigma_{current_sensor_input.i_angle_sigma} { - set_current(current_sensor_input, u_rated); + i_angle_sigma_{current_sensor_input.i_angle_sigma}, + base_current_{base_power_3p * inv_sqrt3 / u_rated} { + set_current(current_sensor_input); switch (current_sensor_input.measured_terminal_type) { case MeasuredTerminalType::branch_from: @@ -89,12 +90,11 @@ template class CurrentSensor : public Ge } }; - UpdateChange update(CurrentSensorUpdate const& update_data, double const& u_rated) { - double const base_current = base_power_3p * inv_sqrt3 / u_rated; - double const scalar = 1.0 / base_current; + UpdateChange update(CurrentSensorUpdate const& update_data) { + double const scalar = 1.0 / base_current_; if (!is_nan(update_data.i_sigma)) { - i_sigma_ = update_data.i_sigma / base_current; + i_sigma_ = update_data.i_sigma / base_current_; } if (!is_nan(update_data.i_angle_sigma)) { i_angle_sigma_ = update_data.i_angle_sigma; @@ -104,15 +104,13 @@ template class CurrentSensor : public Ge return {false, false}; } - CurrentSensorUpdate inverse(CurrentSensorUpdate update_data, - double const& u_rated) const { + CurrentSensorUpdate + inverse(CurrentSensorUpdate update_data) const { assert(update_data.id == this->id() || is_nan(update_data.id)); - double const base_current = base_power_3p * inv_sqrt3 / u_rated; - - set_if_not_nan(update_data.i_sigma, i_sigma_ * base_current); + set_if_not_nan(update_data.i_sigma, i_sigma_ * base_current_); set_if_not_nan(update_data.i_angle_sigma, i_angle_sigma_); - set_if_not_nan(update_data.i_measured, i_measured_ * base_current); + set_if_not_nan(update_data.i_measured, i_measured_ * base_current_); set_if_not_nan(update_data.i_angle_measured, i_angle_measured_); return update_data; @@ -123,12 +121,11 @@ template class CurrentSensor : public Ge RealValue i_angle_measured_{}; double i_sigma_{}; double i_angle_sigma_{}; + double base_current_{}; - void set_current(CurrentSensorInput const& input, double const& u_rated) { - double const base_current = base_power_3p * inv_sqrt3 / u_rated; - double const scalar = 1.0 / base_current; - i_sigma_ = input.i_sigma / base_current; - i_measured_ = input.i_measured * scalar; + void set_current(CurrentSensorInput const& input) { + i_sigma_ = input.i_sigma / base_current_; + i_measured_ = input.i_measured / base_current_; } // TODO when filling the functions below take in mind that i_angle_sigma is optional diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index 2403331d1..8b4ebd639 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -148,7 +148,7 @@ TEST_CASE("Test current sensor") { expected.i_angle_measured = i_angle_measured; } - auto const inv = current_sensor.inverse(cs_update, u_rated); + auto const inv = current_sensor.inverse(cs_update); CHECK(inv.id == expected.id); check_nan_preserving_equality(inv.i_sigma, expected.i_sigma); @@ -223,7 +223,7 @@ TEST_CASE("Test current sensor") { i_sigma, i_angle_sigma, i_measured, i_angle_measured}, u_rated}; - auto const inv = current_sensor.inverse(cs_update, u_rated); + auto const inv = current_sensor.inverse(cs_update); CHECK(inv.id == expected.id); check_nan_preserving_equality(inv.i_sigma, expected.i_sigma); From 00ab5e52a554c89ff9188896feb9753dfd7ad8d4 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Wed, 8 Jan 2025 09:26:39 +0100 Subject: [PATCH 34/38] update switch statement Signed-off-by: petersalemink95 --- .../power_grid_model/component/current_sensor.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index b03bfffb0..4eebdc863 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -79,11 +79,12 @@ template class CurrentSensor : public Ge set_current(current_sensor_input); switch (current_sensor_input.measured_terminal_type) { - case MeasuredTerminalType::branch_from: - case MeasuredTerminalType::branch_to: - case MeasuredTerminalType::branch3_1: - case MeasuredTerminalType::branch3_2: - case MeasuredTerminalType::branch3_3: + using enum MeasuredTerminalType; + case branch_from: + case branch_to: + case branch3_1: + case branch3_2: + case branch3_3: break; default: throw InvalidMeasuredTerminalType{current_sensor_input.measured_terminal_type, "Current sensor"}; From c250f3bf2a2ae71d1ae399312dbf257899cd26e2 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Wed, 8 Jan 2025 09:34:16 +0100 Subject: [PATCH 35/38] fix indent Signed-off-by: petersalemink95 --- tests/cpp_unit_tests/test_current_sensor.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index 8b4ebd639..a48d0a8cc 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -83,15 +83,14 @@ TEST_CASE("Test current sensor") { CHECK(sym_current_sensor.get_terminal_type() == terminal_type); CHECK(sym_current_sensor.get_angle_measurement_type() == AngleMeasurementType::local); - - SUBCASE("Wrong measured terminal type") { - for (auto const terminal_type : - {MeasuredTerminalType::source, MeasuredTerminalType::shunt, MeasuredTerminalType::load, - MeasuredTerminalType::generator, MeasuredTerminalType::node}) { - CHECK_THROWS_AS((CurrentSensor{ - {1, 1, terminal_type, AngleMeasurementType::local, 1.0, 1.0, 1.0, 1.0}, 1.0}), - InvalidMeasuredTerminalType); - } + } + SUBCASE("Wrong measured terminal type") { + for (auto const terminal_type : + {MeasuredTerminalType::source, MeasuredTerminalType::shunt, MeasuredTerminalType::load, + MeasuredTerminalType::generator, MeasuredTerminalType::node}) { + CHECK_THROWS_AS((CurrentSensor{ + {1, 1, terminal_type, AngleMeasurementType::local, 1.0, 1.0, 1.0, 1.0}, 1.0}), + InvalidMeasuredTerminalType); } } } From 87b323f3ce8e1635482c831a018f8781ffb462ac Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Wed, 8 Jan 2025 13:53:43 +0100 Subject: [PATCH 36/38] update calc_param Signed-off-by: petersalemink95 --- .../include/power_grid_model/calculation_parameters.hpp | 5 ++--- tests/cpp_unit_tests/test_current_sensor.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp index 8c92a6cdc..8e70e3f11 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/calculation_parameters.hpp @@ -110,7 +110,6 @@ template struct PowerSensorCalcParam { // current sensor calculation parameters for state estimation // The value is the complex current -// * for appliances, it is always in injection direction // * for branches, the direction is node -> branch template struct CurrentSensorCalcParam { using sym = sym_type; @@ -119,8 +118,8 @@ template struct CurrentSensorCalcParam { AngleMeasurementType angle_measurement_type{}; ComplexValue value{}; - double i_variance{}; // variance (sigma^2) of the error range of the current, in p.u. - double i_angle_variance{}; // variance (sigma^2) of the error range of the current angle, in p.u. + double i_real_variance{}; // variance (sigma^2) of the error range of real part of the current, in p.u. + double i_imag_variance{}; // variance (sigma^2) of the error range of imaginary part of the current, in p.u. }; template diff --git a/tests/cpp_unit_tests/test_current_sensor.cpp b/tests/cpp_unit_tests/test_current_sensor.cpp index a48d0a8cc..d5f0e1920 100644 --- a/tests/cpp_unit_tests/test_current_sensor.cpp +++ b/tests/cpp_unit_tests/test_current_sensor.cpp @@ -59,8 +59,8 @@ TEST_CASE("Test current sensor") { // Check symmetric sensor output for symmetric parameters CHECK(sym_sensor_param.angle_measurement_type == AngleMeasurementType::local); - CHECK(sym_sensor_param.i_variance == doctest::Approx(0.0)); - CHECK(sym_sensor_param.i_angle_variance == doctest::Approx(0.0)); + CHECK(sym_sensor_param.i_real_variance == doctest::Approx(0.0)); + CHECK(sym_sensor_param.i_imag_variance == doctest::Approx(0.0)); CHECK(real(sym_sensor_param.value) == doctest::Approx(0.0)); CHECK(imag(sym_sensor_param.value) == doctest::Approx(0.0)); @@ -70,8 +70,8 @@ TEST_CASE("Test current sensor") { CHECK(is_nan(sym_sensor_output.i_angle_residual)); // Check symmetric sensor output for asymmetric parameters - CHECK(asym_sensor_param.i_variance == doctest::Approx(0.0)); - CHECK(asym_sensor_param.i_angle_variance == doctest::Approx(0.0)); + CHECK(asym_sensor_param.i_real_variance == doctest::Approx(0.0)); + CHECK(asym_sensor_param.i_imag_variance == doctest::Approx(0.0)); CHECK(real(asym_sensor_param.value[0]) == doctest::Approx(0.0)); CHECK(imag(asym_sensor_param.value[1]) == doctest::Approx(0.0)); From dc5310a5f5c84fc89d0e1b2f089d081275dc2f64 Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Wed, 8 Jan 2025 13:58:33 +0100 Subject: [PATCH 37/38] use scalar Signed-off-by: petersalemink95 --- .../include/power_grid_model/component/current_sensor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index 4eebdc863..cdaf0bd2d 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -95,7 +95,7 @@ template class CurrentSensor : public Ge double const scalar = 1.0 / base_current_; if (!is_nan(update_data.i_sigma)) { - i_sigma_ = update_data.i_sigma / base_current_; + i_sigma_ = update_data.i_sigma * scalar; } if (!is_nan(update_data.i_angle_sigma)) { i_angle_sigma_ = update_data.i_angle_sigma; From 1d149acd3706db782a522d2e7568478d9e8908ff Mon Sep 17 00:00:00 2001 From: petersalemink95 Date: Wed, 8 Jan 2025 14:12:26 +0100 Subject: [PATCH 38/38] base_current_inv_ Signed-off-by: petersalemink95 --- .../power_grid_model/component/current_sensor.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp index cdaf0bd2d..cbfd1ac8c 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/component/current_sensor.hpp @@ -75,7 +75,8 @@ template class CurrentSensor : public Ge : GenericCurrentSensor{current_sensor_input}, i_angle_measured_{current_sensor_input.i_angle_measured}, i_angle_sigma_{current_sensor_input.i_angle_sigma}, - base_current_{base_power_3p * inv_sqrt3 / u_rated} { + base_current_{base_power_3p * inv_sqrt3 / u_rated}, + base_current_inv_{1.0 / base_current_} { set_current(current_sensor_input); switch (current_sensor_input.measured_terminal_type) { @@ -92,15 +93,13 @@ template class CurrentSensor : public Ge }; UpdateChange update(CurrentSensorUpdate const& update_data) { - double const scalar = 1.0 / base_current_; - if (!is_nan(update_data.i_sigma)) { - i_sigma_ = update_data.i_sigma * scalar; + i_sigma_ = update_data.i_sigma * base_current_inv_; } if (!is_nan(update_data.i_angle_sigma)) { i_angle_sigma_ = update_data.i_angle_sigma; } - update_real_value(update_data.i_measured, i_measured_, scalar); + update_real_value(update_data.i_measured, i_measured_, base_current_inv_); update_real_value(update_data.i_angle_measured, i_angle_measured_, 1.0); return {false, false}; } @@ -123,10 +122,11 @@ template class CurrentSensor : public Ge double i_sigma_{}; double i_angle_sigma_{}; double base_current_{}; + double base_current_inv_{}; void set_current(CurrentSensorInput const& input) { - i_sigma_ = input.i_sigma / base_current_; - i_measured_ = input.i_measured / base_current_; + i_sigma_ = input.i_sigma * base_current_inv_; + i_measured_ = input.i_measured * base_current_inv_; } // TODO when filling the functions below take in mind that i_angle_sigma is optional