diff --git a/docs/advanced_documentation/build-guide.md b/docs/advanced_documentation/build-guide.md index 0cd7d55ad..32f697e5a 100644 --- a/docs/advanced_documentation/build-guide.md +++ b/docs/advanced_documentation/build-guide.md @@ -41,8 +41,9 @@ You need a C++ compiler with C++20 support. Below is a list of tested compilers: **Linux** -* gcc >= 10.0 - * Version 10.0 tested using the version in the `manylinux2014` container. +* gcc >= 11.0 + * Version 12.x tested using the version in the `manylinux_2_28` container. + * Version 12.x tested using the musllinux build with custom compiler * Version 11.x tested in CI * Clang >= 14.0 * Version 14.x tested in CI 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 21606f4c3..771862082 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 @@ -107,7 +107,7 @@ class DataPointer { // conversion to const iterator template > - operator std::enable_if_t() const { + requires(!is_const) operator UX() const { return DataPointer{ptr_, indptr_, batch_size_, elements_per_scenario_}; } diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_data.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_data.hpp index 8a5ea8cac..bb70bc785 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_data.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_data.hpp @@ -136,9 +136,8 @@ struct DataAttribute { }; template -inline std::enable_if_t::struct_type>, - size_t> -get_offset() { +requires std::same_as::struct_type> +inline size_t get_offset() { using struct_type = typename trait_pointer_to_member::struct_type; struct_type const obj{}; return (size_t)(&(obj.*member_ptr)) - (size_t)&obj; @@ -149,9 +148,8 @@ constexpr bool is_little_endian() { } template -inline std::enable_if_t::struct_type>, - DataAttribute> -get_data_attribute(std::string const& name) { +requires std::same_as::struct_type> +inline DataAttribute get_data_attribute(std::string_view const& name) { using value_type = typename trait_pointer_to_member::value_type; using single_data_type = data_type; DataAttribute attr{}; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_data_gen.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_data_gen.hpp index 32b325714..a144d51da 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_data_gen.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_data_gen.hpp @@ -23,11 +23,8 @@ namespace meta_data { // template function to add meta data template void add_meta_data(AllPowerGridMetaData& meta) { - // TODO, remove this separate definition for UpdateType after migrating to gcc-11 - // this is due to a wired bug in gcc-10 - using UpdateType = typename CT::UpdateType; meta["input"][CT::name] = get_meta{}(); - meta["update"][CT::name] = get_meta{}(); + meta["update"][CT::name] = get_meta{}(); meta["sym_output"][CT::name] = get_meta>{}(); meta["asym_output"][CT::name] = get_meta>{}(); meta["sc_output"][CT::name] = get_meta{}(); diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/container.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/container.hpp index f8bf87829..fd11a7d30 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/container.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/container.hpp @@ -227,13 +227,11 @@ class Container, StorageableTypes...> { // get item per type template - GettableBaseType& get_raw(Idx pos) { - static_assert(std::is_base_of_v); + requires std::derived_from GettableBaseType& get_raw(Idx pos) { return std::get>(vectors_)[pos]; } template - GettableBaseType const& get_raw(Idx pos) const { - static_assert(std::is_base_of_v); + requires std::derived_from GettableBaseType const& get_raw(Idx pos) const { return std::get>(vectors_)[pos]; } @@ -248,8 +246,8 @@ class Container, StorageableTypes...> { static constexpr GetItemFuncPtrConst ptr_const = nullptr; }; template - struct select_get_item_func_ptr>> { + requires std::derived_from + struct select_get_item_func_ptr { static constexpr GetItemFuncPtr ptr = &Container::get_raw; static constexpr GetItemFuncPtrConst ptr_const = @@ -309,7 +307,7 @@ class Container, StorageableTypes...> { } // conversion to const iterator template - operator std::enable_if_t>() const { + requires(!is_const) explicit operator Iterator() const { return Iterator{container_ptr_, idx_}; } diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp index 5c7d8a043..0bb668190 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/main_model.hpp @@ -138,12 +138,9 @@ class MainModelImpl, ComponentLis // template to construct components // using forward interators // different selection based on component type - template - std::enable_if_t> add_component(ForwardIterator begin, ForwardIterator end) { + template CompType, std::forward_iterator ForwardIterator> + void add_component(ForwardIterator begin, ForwardIterator end) { assert(!construction_complete_); - // check forward iterator - static_assert(std::is_base_of_v::iterator_category>); size_t size = std::distance(begin, end); components_.template reserve(size); // loop to add component @@ -158,7 +155,7 @@ class MainModelImpl, ComponentLis double const u1 = components_.template get_item(input.from_node).u_rated(); double const u2 = components_.template get_item(input.to_node).u_rated(); // set system frequency for line - if constexpr (std::is_same_v) { + if constexpr (std::same_as) { components_.template emplace(id, input, system_frequency_, u1, u2); } else { @@ -226,12 +223,9 @@ class MainModelImpl, ComponentLis // using forward interators // different selection based on component type // if sequence_idx is given, it will be used to load the object instead of using IDs via hash map. - template + template void update_component(ForwardIterator begin, ForwardIterator end, std::vector const& sequence_idx = {}) { assert(construction_complete_); - // check forward iterator - static_assert(std::is_base_of_v::iterator_category>); bool const has_sequence_id = !sequence_idx.empty(); Idx seq = 0; // loop to to update component @@ -719,12 +713,8 @@ class MainModelImpl, ComponentLis } // output node - template - std::enable_if_t< - std::is_base_of_v::iterator_category> && - std::is_same_v, - ResIt> - output_result(std::vector> const& math_output, ResIt res_it) { + template Component, std::forward_iterator ResIt> + ResIt output_result(std::vector> const& math_output, ResIt res_it) { assert(construction_complete_); return std::transform(components_.template citer().begin(), components_.template citer().end(), comp_coup_->node.cbegin(), res_it, @@ -738,12 +728,8 @@ class MainModelImpl, ComponentLis } // output branch - template - std::enable_if_t< - std::is_base_of_v::iterator_category> && - std::is_base_of_v, - ResIt> - output_result(std::vector> const& math_output, ResIt res_it) { + template Component, std::forward_iterator ResIt> + ResIt output_result(std::vector> const& math_output, ResIt res_it) { assert(construction_complete_); return std::transform(components_.template citer().begin(), components_.template citer().end(), @@ -757,12 +743,8 @@ class MainModelImpl, ComponentLis } // output branch3 - template - std::enable_if_t< - std::is_base_of_v::iterator_category> && - std::is_base_of_v, - ResIt> - output_result(std::vector> const& math_output, ResIt res_it) { + template Component, std::forward_iterator ResIt> + ResIt output_result(std::vector> const& math_output, ResIt res_it) { assert(construction_complete_); return std::transform(components_.template citer().begin(), components_.template citer().end(), @@ -779,12 +761,8 @@ class MainModelImpl, ComponentLis } // output source, load_gen, shunt individually - template - std::enable_if_t< - std::is_base_of_v::iterator_category> && - std::is_same_v, - ResIt> - output_result(std::vector> const& math_output, ResIt res_it) { + template Component, std::forward_iterator ResIt> + ResIt output_result(std::vector> const& math_output, ResIt res_it) { assert(construction_complete_); res_it = output_result(math_output, res_it); res_it = output_result(math_output, res_it); @@ -793,12 +771,8 @@ class MainModelImpl, ComponentLis } // output source - template - std::enable_if_t< - std::is_base_of_v::iterator_category> && - std::is_same_v, - ResIt> - output_result(std::vector> const& math_output, ResIt res_it) { + template Component, std::forward_iterator ResIt> + ResIt output_result(std::vector> const& math_output, ResIt res_it) { assert(construction_complete_); return std::transform(components_.template citer().begin(), components_.template citer().end(), comp_coup_->source.cbegin(), res_it, @@ -811,12 +785,8 @@ class MainModelImpl, ComponentLis } // output load gen - template - std::enable_if_t< - std::is_base_of_v::iterator_category> && - std::is_base_of_v, - ResIt> - output_result(std::vector> const& math_output, ResIt res_it) { + template Component, std::forward_iterator ResIt> + ResIt output_result(std::vector> const& math_output, ResIt res_it) { assert(construction_complete_); return std::transform( components_.template citer().begin(), components_.template citer().end(), @@ -830,12 +800,8 @@ class MainModelImpl, ComponentLis } // output shunt - template - std::enable_if_t< - std::is_base_of_v::iterator_category> && - std::is_same_v, - ResIt> - output_result(std::vector> const& math_output, ResIt res_it) { + template Component, std::forward_iterator ResIt> + ResIt output_result(std::vector> const& math_output, ResIt res_it) { assert(construction_complete_); return std::transform(components_.template citer().begin(), components_.template citer().end(), comp_coup_->shunt.cbegin(), res_it, @@ -848,12 +814,8 @@ class MainModelImpl, ComponentLis } // output voltage sensor - template - std::enable_if_t< - std::is_base_of_v::iterator_category> && - std::is_base_of_v, - ResIt> - output_result(std::vector> const& math_output, ResIt res_it) { + template Component, std::forward_iterator ResIt> + ResIt output_result(std::vector> const& math_output, ResIt res_it) { assert(construction_complete_); return std::transform( components_.template citer().begin(), components_.template citer().end(), @@ -869,12 +831,8 @@ class MainModelImpl, ComponentLis } // output power sensor - template - std::enable_if_t< - std::is_base_of_v::iterator_category> && - std::is_base_of_v, - ResIt> - output_result(std::vector> const& math_output, ResIt res_it) { + template Component, std::forward_iterator ResIt> + ResIt output_result(std::vector> const& math_output, ResIt res_it) { assert(construction_complete_); return std::transform( components_.template citer().begin(), components_.template citer().end(), diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/block_matrix.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/block_matrix.hpp index 9f9bb9f69..33b461322 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/block_matrix.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/block_matrix.hpp @@ -17,7 +17,7 @@ namespace power_grid_model { // hide implementation in inside namespace namespace math_model_impl { -template >> +template struct block_trait { static constexpr int n_row = sym ? n_sub_block : n_sub_block * 3; static constexpr int n_col = is_tensor ? (sym ? n_sub_block : n_sub_block * 3) : 1; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_lu_solver.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_lu_solver.hpp index 5309fda4e..0b6858bb5 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_lu_solver.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/math_solver/sparse_lu_solver.hpp @@ -21,30 +21,30 @@ template struct sparse_lu_entry_trait; template -using enable_scalar_lu_t = - std::enable_if_t && std::is_same_v && check_scalar_v>; +concept scalar_value_lu = scalar_value && std::same_as && std::same_as; +// TODO(mgovers) improve this concept template int check_array_base(Eigen::ArrayBase const&) { return 0; } +template +concept eigen_array = std::same_as; // should be an eigen array + +template +concept matrix_multiplicable = eigen_array && eigen_array && + (static_cast(LHSArrayLike::ColsAtCompileTime) == static_cast(RHSArrayLike::RowsAtCompileTime)); template -using enable_tensor_lu_t = std::enable_if_t< - std::is_same_v && // tensor should be an eigen array - std::is_same_v && // rhs vector should be an eigen array - std::is_same_v && // x vector should be an eigen array - (Idx)Tensor::RowsAtCompileTime == (Idx)Tensor::ColsAtCompileTime && // tensor should be square - RHSVector::ColsAtCompileTime == 1 && // rhs vector should be column vector - (Idx)RHSVector::RowsAtCompileTime == (Idx)Tensor::RowsAtCompileTime && // rhs vector should be column vector - XVector::ColsAtCompileTime == 1 && // x vector should be column vector - (Idx)XVector::RowsAtCompileTime == (Idx)Tensor::RowsAtCompileTime && // x vector should be column vector - std::is_same_v && // all entries should have same scalar type - std::is_same_v && // all entries should have same scalar type - check_scalar_v>; // scalar can only be double or complex double +concept tensor_lu = rk2_tensor && column_vector && column_vector && + matrix_multiplicable && matrix_multiplicable && + std::same_as && // all entries should have same scalar type + std::same_as && // all entries should have same scalar type + scalar_value; // scalar can only be double or complex double template -struct sparse_lu_entry_trait> { +requires scalar_value_lu +struct sparse_lu_entry_trait { static constexpr bool is_block = false; static constexpr Idx block_size = 1; using Scalar = Tensor; @@ -55,7 +55,8 @@ struct sparse_lu_entry_trait -struct sparse_lu_entry_trait> { +requires tensor_lu +struct sparse_lu_entry_trait { static constexpr bool is_block = true; static constexpr Idx block_size = Tensor::RowsAtCompileTime; using Scalar = typename Tensor::Scalar; diff --git a/power_grid_model_c/power_grid_model/include/power_grid_model/three_phase_tensor.hpp b/power_grid_model_c/power_grid_model/include/power_grid_model/three_phase_tensor.hpp index ccc646080..d2a12307e 100644 --- a/power_grid_model_c/power_grid_model/include/power_grid_model/three_phase_tensor.hpp +++ b/power_grid_model_c/power_grid_model/include/power_grid_model/three_phase_tensor.hpp @@ -19,9 +19,7 @@ namespace power_grid_model { // enable scalar template -constexpr bool check_scalar_v = std::is_same_v || std::is_same_v; -template -using enable_scalar_t = std::enable_if_t>; +concept scalar_value = std::same_as || std::same_as; namespace three_phase_tensor { @@ -30,7 +28,7 @@ using Eigen3Vector = Eigen::Array; template using Eigen3Tensor = Eigen::Array; -template > +template class Vector : public Eigen3Vector { public: Vector() { @@ -49,7 +47,7 @@ class Vector : public Eigen3Vector { // for complex number, rotate the single value by 120 and 240 degrees for 1st and 2nd entry // this will create a symmetric phasor based on one phasor explicit Vector(T const& x) { - if constexpr (std::is_same_v) { + if constexpr (std::same_as) { (*this) << x, x, x; } else { @@ -67,7 +65,7 @@ class Vector : public Eigen3Vector { } }; -template > +template class Tensor : public Eigen3Tensor { public: Tensor() { @@ -125,17 +123,12 @@ static_assert(std::is_trivially_destructible_v>); // enabler template -constexpr bool check_vector_v = T::ColsAtCompileTime == 1; -template -constexpr bool check_tensor_v = (Idx)T::RowsAtCompileTime == (Idx)T::ColsAtCompileTime; -template -constexpr bool check_all_v = check_tensor_v || check_vector_v; -template -using enable_vector_t = std::enable_if_t>; +concept column_vector = (T::ColsAtCompileTime == 1); template -using enable_tensor_t = std::enable_if_t>; +concept rk2_tensor = (static_cast(T::RowsAtCompileTime) == + static_cast(T::ColsAtCompileTime)); // rank 2 tensor template -using enable_all_t = std::enable_if_t>; +concept column_vector_or_tensor = column_vector || rk2_tensor; // piecewise factory construction for complex vector template @@ -148,7 +141,7 @@ inline ComplexValue piecewise_complex_value(DoubleComplex const& x) { } } -template > +template inline ComplexValue piecewise_complex_value(Eigen::ArrayBase const& val) { return val; } @@ -163,7 +156,7 @@ inline double cabs(DoubleComplex const& x) { inline double abs2(DoubleComplex const& x) { return std::norm(x); } -template > +template inline auto cabs(Eigen::ArrayBase const& m) { return sqrt(abs2(m)); } @@ -172,7 +165,7 @@ inline auto cabs(Eigen::ArrayBase const& m) { inline double vector_outer_product(double x, double y) { return x * y; } -template , class = enable_vector_t> +template inline auto vector_outer_product(Eigen::ArrayBase const& x, Eigen::ArrayBase const& y) { return (x.matrix() * y.matrix().transpose()).array(); } @@ -185,12 +178,12 @@ inline DoubleComplex dot(DoubleComplex const& x, DoubleComplex const& y) { return x * y; } -template && ...)>> +template inline auto dot(T const&... x) { return (... * x); } -template && ...)>> +template inline auto dot(Eigen::ArrayBase const&... x) { auto res_mat = (... * x.matrix()); return res_mat.array(); @@ -200,13 +193,13 @@ inline auto dot(Eigen::ArrayBase const&... x) { inline double max_val(double val) { return val; } -template > +template inline double max_val(Eigen::ArrayBase const& val) { return val.maxCoeff(); } // function to sum rows of tensor -template > +template inline auto sum_row(Eigen::ArrayBase const& m) { return m.rowwise().sum(); } @@ -216,7 +209,7 @@ inline double sum_row(double d) { } // function to sum vector -template > +template inline auto sum_val(Eigen::ArrayBase const& m) { return m.sum(); } @@ -229,7 +222,7 @@ inline DoubleComplex sum_val(DoubleComplex const& z) { } // function to mean vector -template > +template inline auto mean_val(Eigen::ArrayBase const& m) { return m.mean(); } @@ -251,8 +244,7 @@ inline auto process_mean_val(T&& m) { } // diagonal multiply -template , - class = enable_tensor_t, class = enable_vector_t> +template inline auto diag_mult(Eigen::ArrayBase const& x, Eigen::ArrayBase const& y, Eigen::ArrayBase const& z) { return (x.matrix().asDiagonal() * y.matrix() * z.matrix().asDiagonal()).array(); @@ -263,7 +255,7 @@ inline double diag_mult(double x, double y, double z) { } // calculate positive sequence -template > +template inline DoubleComplex pos_seq(Eigen::ArrayBase const& val) { return (val(0) + a * val(1) + a2 * val(2)) / 3.0; } @@ -287,11 +279,11 @@ inline void add_diag(double& x, double y) { inline void add_diag(DoubleComplex& x, DoubleComplex const& y) { x += y; } -template , class = enable_vector_t> +template inline void add_diag(Eigen::ArrayBase& x, Eigen::ArrayBase const& y) { x.matrix().diagonal() += y.matrix(); } -template , class = enable_vector_t> +template inline void add_diag(Eigen::ArrayBase&& x, Eigen::ArrayBase const& y) { x.matrix().diagonal() += y.matrix(); } @@ -368,7 +360,7 @@ inline DoubleComplex hermitian_transpose(DoubleComplex const& z) { inline double hermitian_transpose(double x) { return x; } -template > +template inline auto hermitian_transpose(Eigen::ArrayBase const& x) { return x.matrix().adjoint().array(); } diff --git a/tests/cpp_unit_tests/test_container.cpp b/tests/cpp_unit_tests/test_container.cpp index 404017c22..17b05f233 100644 --- a/tests/cpp_unit_tests/test_container.cpp +++ b/tests/cpp_unit_tests/test_container.cpp @@ -72,8 +72,8 @@ TEST_CASE("Test component container") { CHECK(c.a == i); i++; } - auto it_begin = container.iter().begin(); - auto it_end = container.iter().end(); + auto it_begin = container.iter().begin(); + auto it_end = container.iter().end(); auto const_it_begin = const_container.iter().begin(); auto const_it_end = const_container.iter().end(); CHECK(it_begin != const_it_end); diff --git a/tests/cpp_unit_tests/test_sparse_lu_solver.cpp b/tests/cpp_unit_tests/test_sparse_lu_solver.cpp index 808cf8370..63b7a0a06 100644 --- a/tests/cpp_unit_tests/test_sparse_lu_solver.cpp +++ b/tests/cpp_unit_tests/test_sparse_lu_solver.cpp @@ -23,7 +23,7 @@ template void check_result(std::vector const& x, std::vector const& x_solver) { CHECK(x.size() == x_solver.size()); for (size_t i = 0; i < x.size(); i++) { - if constexpr (check_scalar_v) { + if constexpr (scalar_value) { CHECK(cabs(x[i] - x_solver[i]) < numerical_tolerance); } else {