From 463d51ca8dbf3bc5743281f6fb97fa5ef7b845ae Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 31 Mar 2026 09:34:38 +0200 Subject: [PATCH 1/5] apply hardening fixes from #1241 without enabling hardening itself Signed-off-by: Martijn Govers --- .../power_grid_model/auxiliary/dataset.hpp | 27 ++++++---- .../common/three_phase_tensor.hpp | 2 +- .../power_grid_model/math_solver/y_bus.hpp | 53 +++++++++++-------- 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp index b6b3391cb5..b11f76cecf 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp @@ -90,10 +90,15 @@ class ColumnarAttributeRange : public std::ranges::view_interface { - AttributeType* buffer_ptr = reinterpret_cast(attribute_buffer.data) + idx_; - auto const& attribute_ref = meta_attribute.template get_attribute( - reinterpret_cast(&value)); - *buffer_ptr = attribute_ref; + if constexpr (sizeof(AttributeType) <= sizeof(value_type)) { + AttributeType* buffer_ptr = reinterpret_cast(attribute_buffer.data) + idx_; + auto const& attribute_ref = meta_attribute.template get_attribute( + reinterpret_cast(&value)); + *buffer_ptr = attribute_ref; + } else { + throw UnreachableHit{"ColumnarAttributeRange::operator=", + "AttributeType larger than value_type!"}; + } }); } return *this; @@ -104,14 +109,18 @@ class ColumnarAttributeRange : public std::ranges::view_interface { + ctype_func_selector(meta_attribute.ctype, [&result, &attribute_buffer, &meta_attribute, + idx = idx_] { + if constexpr (sizeof(AttributeType) <= sizeof(value_type)) { AttributeType const* buffer_ptr = - reinterpret_cast(attribute_buffer.data) + idx_; - auto& attribute_ref = + reinterpret_cast(attribute_buffer.data) + idx; + AttributeType& attribute_ref = meta_attribute.template get_attribute(reinterpret_cast(&result)); attribute_ref = *buffer_ptr; - }); + } else { + throw UnreachableHit{"ColumnarAttributeRange::get", "AttributeType larger than value_type!"}; + } + }); } return result; } diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/common/three_phase_tensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/common/three_phase_tensor.hpp index b0b8a6b33d..d5ba7d4ab0 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/common/three_phase_tensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/common/three_phase_tensor.hpp @@ -34,7 +34,7 @@ template using EigenDiagonalTensor3 = Eigen::DiagonalMatrix; template class Vector : public EigenVector3 { public: - Vector() { (*this) = EigenVector3::Zero(); }; + Vector() { this->setConstant(T{}); }; // eigen expression template Vector(Eigen::ArrayBase const& other) : EigenVector3{other} {} template Vector& operator=(Eigen::ArrayBase const& other) { diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp index 3cfc4c641f..c7436f6050 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/y_bus.hpp @@ -302,6 +302,9 @@ template class YBus { std::shared_ptr const> const& param, std::shared_ptr const& y_bus_struct = {}) : math_topology_{topo_ptr} { + assert(math_topology_ != nullptr); + assert(param != nullptr); + // use existing struct or make new struct if (y_bus_struct) { y_bus_struct_ = y_bus_struct; @@ -455,29 +458,31 @@ template class YBus { template requires std::same_as> || std::same_as> std::vector calculate_branch_flow(ComplexValueVector const& u) const { - std::vector branch_flow(math_topology_->branch_bus_idx.size()); - std::transform(math_topology_->branch_bus_idx.cbegin(), math_topology_->branch_bus_idx.cend(), - math_model_param_->branch_param.cbegin(), branch_flow.begin(), - [&u](BranchIdx branch_idx, BranchCalcParam const& param) { - auto const [f, t] = branch_idx; - // if one side is disconnected, use zero voltage at that side - ComplexValue const uf = f != -1 ? u[f] : ComplexValue{0.0}; - ComplexValue const ut = t != -1 ? u[t] : ComplexValue{0.0}; - T output; - - // See "Branch Flow Calculation" in "State Estimation Alliander" - output.i_f = dot(param.yff(), uf) + dot(param.yft(), ut); - output.i_t = dot(param.ytf(), uf) + dot(param.ytt(), ut); - - if constexpr (std::same_as>) { - // See "Shunt Injection Flow Calculation" in "State Estimation Alliander" - output.s_f = uf * conj(output.i_f); - output.s_t = ut * conj(output.i_t); - } - - return output; - }); - return branch_flow; + assert(math_topology_ != nullptr); + + return std::views::zip(math_topology_->branch_bus_idx, math_model_param_->branch_param) | + std::views::transform([&u](auto const& branch_idx_params) -> T { + auto const& [branch_idx, param] = branch_idx_params; + + auto const [f, t] = branch_idx; + // if one side is disconnected, use zero voltage at that side + ComplexValue const uf = f != -1 ? u[f] : ComplexValue{0.0}; + ComplexValue const ut = t != -1 ? u[t] : ComplexValue{0.0}; + T output; + + // See "Branch Flow Calculation" in "State Estimation Alliander" + output.i_f = dot(param.yff(), uf) + dot(param.yft(), ut); + output.i_t = dot(param.ytf(), uf) + dot(param.ytt(), ut); + + if constexpr (std::same_as>) { + // See "Shunt Injection Flow Calculation" in "State Estimation Alliander" + output.s_f = uf * conj(output.i_f); + output.s_t = ut * conj(output.i_t); + } + + return output; + }) | + std::ranges::to>(); } // calculate shunt flow based on voltage, injection direction @@ -485,6 +490,8 @@ template class YBus { requires std::same_as> || std::same_as> std::vector calculate_shunt_flow(ComplexValueVector const& u) const { + assert(math_topology_ != nullptr); + std::vector shunt_flow(math_topology_->n_shunt()); for (auto const [bus, shunts] : enumerated_zip_sequence(math_topology_->shunts_per_bus)) { for (Idx const shunt : shunts) { From 6e29f4dc90b1293760e6cbe0efd7bcf390d378fd Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 31 Mar 2026 11:20:54 +0200 Subject: [PATCH 2/5] clang-tidy Signed-off-by: Martijn Govers --- .../include/power_grid_model/auxiliary/dataset.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp index b11f76cecf..3fbe7f3eff 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp @@ -114,7 +114,7 @@ class ColumnarAttributeRange : public std::ranges::view_interface(attribute_buffer.data) + idx; - AttributeType& attribute_ref = + auto& attribute_ref = meta_attribute.template get_attribute(reinterpret_cast(&result)); attribute_ref = *buffer_ptr; } else { From 3d91519f7b3580704295d00f698b70c0c455105c Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 31 Mar 2026 11:22:45 +0200 Subject: [PATCH 3/5] fix clangd config Signed-off-by: Martijn Govers --- .clangd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.clangd b/.clangd index 08921ed350..e7181556e5 100644 --- a/.clangd +++ b/.clangd @@ -9,4 +9,5 @@ Diagnostics: UnusedIncludes: Strict MissingIncludes: Strict Includes: - IgnoreHeader: Eigen/Dense + IgnoreHeader: + - Eigen/.* From ffce86cb7c03b8ca6a92c311279349ad05d3085a Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 31 Mar 2026 11:41:13 +0200 Subject: [PATCH 4/5] harden using assert instead of throwing Signed-off-by: Martijn Govers --- .../include/power_grid_model/auxiliary/dataset.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp index 3fbe7f3eff..a0ed74d51e 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp @@ -90,14 +90,13 @@ class ColumnarAttributeRange : public std::ranges::view_interface { - if constexpr (sizeof(AttributeType) <= sizeof(value_type)) { + if constexpr (sizeof(AttributeType) == sizeof(value_type)) { AttributeType* buffer_ptr = reinterpret_cast(attribute_buffer.data) + idx_; auto const& attribute_ref = meta_attribute.template get_attribute( reinterpret_cast(&value)); *buffer_ptr = attribute_ref; } else { - throw UnreachableHit{"ColumnarAttributeRange::operator=", - "AttributeType larger than value_type!"}; + assert(false && "ColumnarAttributeRange::operator= AttributeType not equal to value_type!"); } }); } @@ -111,14 +110,14 @@ class ColumnarAttributeRange : public std::ranges::view_interface { - if constexpr (sizeof(AttributeType) <= sizeof(value_type)) { + if constexpr (sizeof(AttributeType) == sizeof(value_type)) { AttributeType const* buffer_ptr = reinterpret_cast(attribute_buffer.data) + idx; auto& attribute_ref = meta_attribute.template get_attribute(reinterpret_cast(&result)); attribute_ref = *buffer_ptr; } else { - throw UnreachableHit{"ColumnarAttributeRange::get", "AttributeType larger than value_type!"}; + assert(false && "ColumnarAttributeRange::get AttributeType not equal to value_type!"); } }); } From 182e1c5a317c0f65d5b2cce39e66b2b87584e092 Mon Sep 17 00:00:00 2001 From: Martijn Govers Date: Tue, 31 Mar 2026 11:46:54 +0200 Subject: [PATCH 5/5] fix attribute type vs underlying type Signed-off-by: Martijn Govers --- .../include/power_grid_model/auxiliary/dataset.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp index a0ed74d51e..0e77d13b12 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp @@ -90,7 +90,7 @@ class ColumnarAttributeRange : public std::ranges::view_interface { - if constexpr (sizeof(AttributeType) == sizeof(value_type)) { + if constexpr (sizeof(AttributeType) <= sizeof(value_type)) { AttributeType* buffer_ptr = reinterpret_cast(attribute_buffer.data) + idx_; auto const& attribute_ref = meta_attribute.template get_attribute( reinterpret_cast(&value)); @@ -110,7 +110,7 @@ class ColumnarAttributeRange : public std::ranges::view_interface { - if constexpr (sizeof(AttributeType) == sizeof(value_type)) { + if constexpr (sizeof(AttributeType) <= sizeof(value_type)) { AttributeType const* buffer_ptr = reinterpret_cast(attribute_buffer.data) + idx; auto& attribute_ref =