diff --git a/src/language/modules/MathFunctionRegisterForVh.cpp b/src/language/modules/MathFunctionRegisterForVh.cpp index 7617463648fdee030760ef65ed9dec50bdb21232..22f7866bddd9a0539d9d2cb669c69d69c0be23a8 100644 --- a/src/language/modules/MathFunctionRegisterForVh.cpp +++ b/src/language/modules/MathFunctionRegisterForVh.cpp @@ -253,49 +253,97 @@ MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module double b) -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); })); scheme_module - ._addBuiltinFunction("sum_to_R", + ._addBuiltinFunction("sum_of_R", std::make_shared<BuiltinFunctionEmbedder<double(std::shared_ptr<const IDiscreteFunction>)>>( - [](std::shared_ptr<const IDiscreteFunction> a) -> double { return sum_to<double>(a); })); + [](std::shared_ptr<const IDiscreteFunction> a) -> double { return sum_of<double>(a); })); - scheme_module._addBuiltinFunction("sum_to_R1", + scheme_module._addBuiltinFunction("sum_of_R1", std::make_shared< BuiltinFunctionEmbedder<TinyVector<1>(std::shared_ptr<const IDiscreteFunction>)>>( [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<1> { - return sum_to<TinyVector<1>>(a); + return sum_of<TinyVector<1>>(a); })); - scheme_module._addBuiltinFunction("sum_to_R2", + scheme_module._addBuiltinFunction("sum_of_R2", std::make_shared< BuiltinFunctionEmbedder<TinyVector<2>(std::shared_ptr<const IDiscreteFunction>)>>( [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<2> { - return sum_to<TinyVector<2>>(a); + return sum_of<TinyVector<2>>(a); })); - scheme_module._addBuiltinFunction("sum_to_R3", + scheme_module._addBuiltinFunction("sum_of_R3", std::make_shared< BuiltinFunctionEmbedder<TinyVector<3>(std::shared_ptr<const IDiscreteFunction>)>>( [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<3> { - return sum_to<TinyVector<3>>(a); + return sum_of<TinyVector<3>>(a); })); - scheme_module._addBuiltinFunction("sum_to_R1x1", + scheme_module._addBuiltinFunction("sum_of_R1x1", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<1>(std::shared_ptr<const IDiscreteFunction>)>>( [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<1> { - return sum_to<TinyMatrix<1>>(a); + return sum_of<TinyMatrix<1>>(a); })); - scheme_module._addBuiltinFunction("sum_to_R2x2", + scheme_module._addBuiltinFunction("sum_of_R2x2", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<2>(std::shared_ptr<const IDiscreteFunction>)>>( [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<2> { - return sum_to<TinyMatrix<2>>(a); + return sum_of<TinyMatrix<2>>(a); })); - scheme_module._addBuiltinFunction("sum_to_R3x3", + scheme_module._addBuiltinFunction("sum_of_R3x3", std::make_shared< BuiltinFunctionEmbedder<TinyMatrix<3>(std::shared_ptr<const IDiscreteFunction>)>>( [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<3> { - return sum_to<TinyMatrix<3>>(a); + return sum_of<TinyMatrix<3>>(a); + })); + scheme_module + ._addBuiltinFunction("integral_of_R", + std::make_shared<BuiltinFunctionEmbedder<double(std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) -> double { + return integral_of<double>(a); + })); + + scheme_module._addBuiltinFunction("integral_of_R1", + std::make_shared< + BuiltinFunctionEmbedder<TinyVector<1>(std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<1> { + return integral_of<TinyVector<1>>(a); + })); + + scheme_module._addBuiltinFunction("integral_of_R2", + std::make_shared< + BuiltinFunctionEmbedder<TinyVector<2>(std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<2> { + return integral_of<TinyVector<2>>(a); + })); + + scheme_module._addBuiltinFunction("integral_of_R3", + std::make_shared< + BuiltinFunctionEmbedder<TinyVector<3>(std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<3> { + return integral_of<TinyVector<3>>(a); + })); + + scheme_module._addBuiltinFunction("integral_of_R1x1", + std::make_shared< + BuiltinFunctionEmbedder<TinyMatrix<1>(std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<1> { + return integral_of<TinyMatrix<1>>(a); + })); + + scheme_module._addBuiltinFunction("integral_of_R2x2", + std::make_shared< + BuiltinFunctionEmbedder<TinyMatrix<2>(std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<2> { + return integral_of<TinyMatrix<2>>(a); + })); + + scheme_module._addBuiltinFunction("integral_of_R3x3", + std::make_shared< + BuiltinFunctionEmbedder<TinyMatrix<3>(std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<3> { + return integral_of<TinyMatrix<3>>(a); })); } diff --git a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp index 0c5f23fb63210a8f72ddda25688fc758f743c13c..a688acf1372f93b10192fec99abe0bd15de52683 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp @@ -722,7 +722,7 @@ max(const std::shared_ptr<const IDiscreteFunction>& f, const double a) template <typename ValueT> ValueT -sum_to(const std::shared_ptr<const IDiscreteFunction>& f) +sum_of(const std::shared_ptr<const IDiscreteFunction>& f) { if (f->dataType() == ast_node_data_type_from<ValueT> and f->descriptor().type() == DiscreteFunctionType::P0) { switch (f->mesh()->dimension()) { @@ -747,16 +747,57 @@ sum_to(const std::shared_ptr<const IDiscreteFunction>& f) } } -template double sum_to<double>(const std::shared_ptr<const IDiscreteFunction>&); +template double sum_of<double>(const std::shared_ptr<const IDiscreteFunction>&); -template TinyVector<1> sum_to<TinyVector<1>>(const std::shared_ptr<const IDiscreteFunction>&); +template TinyVector<1> sum_of<TinyVector<1>>(const std::shared_ptr<const IDiscreteFunction>&); -template TinyVector<2> sum_to<TinyVector<2>>(const std::shared_ptr<const IDiscreteFunction>&); +template TinyVector<2> sum_of<TinyVector<2>>(const std::shared_ptr<const IDiscreteFunction>&); -template TinyVector<3> sum_to<TinyVector<3>>(const std::shared_ptr<const IDiscreteFunction>&); +template TinyVector<3> sum_of<TinyVector<3>>(const std::shared_ptr<const IDiscreteFunction>&); -template TinyMatrix<1> sum_to<TinyMatrix<1>>(const std::shared_ptr<const IDiscreteFunction>&); +template TinyMatrix<1> sum_of<TinyMatrix<1>>(const std::shared_ptr<const IDiscreteFunction>&); -template TinyMatrix<2> sum_to<TinyMatrix<2>>(const std::shared_ptr<const IDiscreteFunction>&); +template TinyMatrix<2> sum_of<TinyMatrix<2>>(const std::shared_ptr<const IDiscreteFunction>&); -template TinyMatrix<3> sum_to<TinyMatrix<3>>(const std::shared_ptr<const IDiscreteFunction>&); +template TinyMatrix<3> sum_of<TinyMatrix<3>>(const std::shared_ptr<const IDiscreteFunction>&); + +template <typename ValueT> +ValueT +integral_of(const std::shared_ptr<const IDiscreteFunction>& f) +{ + if (f->dataType() == ast_node_data_type_from<ValueT> and f->descriptor().type() == DiscreteFunctionType::P0) { + switch (f->mesh()->dimension()) { + case 1: { + using DiscreteFunctionType = DiscreteFunctionP0<1, ValueT>; + return integrate(dynamic_cast<const DiscreteFunctionType&>(*f)); + } + case 2: { + using DiscreteFunctionType = DiscreteFunctionP0<2, ValueT>; + return integrate(dynamic_cast<const DiscreteFunctionType&>(*f)); + } + case 3: { + using DiscreteFunctionType = DiscreteFunctionP0<3, ValueT>; + return integrate(dynamic_cast<const DiscreteFunctionType&>(*f)); + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } else { + throw NormalError("invalid operand type " + operand_type_name(f)); + } +} + +template double integral_of<double>(const std::shared_ptr<const IDiscreteFunction>&); + +template TinyVector<1> integral_of<TinyVector<1>>(const std::shared_ptr<const IDiscreteFunction>&); + +template TinyVector<2> integral_of<TinyVector<2>>(const std::shared_ptr<const IDiscreteFunction>&); + +template TinyVector<3> integral_of<TinyVector<3>>(const std::shared_ptr<const IDiscreteFunction>&); + +template TinyMatrix<1> integral_of<TinyMatrix<1>>(const std::shared_ptr<const IDiscreteFunction>&); + +template TinyMatrix<2> integral_of<TinyMatrix<2>>(const std::shared_ptr<const IDiscreteFunction>&); + +template TinyMatrix<3> integral_of<TinyMatrix<3>>(const std::shared_ptr<const IDiscreteFunction>&); diff --git a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp index 6eef58101016b95411613677cef2d27e5e52eac1..582e63d8551842e9f93e3962a08669ba34baf756 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp @@ -84,6 +84,9 @@ std::shared_ptr<const IDiscreteFunction> max(const double, const std::shared_ptr std::shared_ptr<const IDiscreteFunction> max(const std::shared_ptr<const IDiscreteFunction>&, const double); template <typename ValueT> -ValueT sum_to(const std::shared_ptr<const IDiscreteFunction>&); +ValueT sum_of(const std::shared_ptr<const IDiscreteFunction>&); + +template <typename ValueT> +ValueT integral_of(const std::shared_ptr<const IDiscreteFunction>&); #endif // EMBEDDED_I_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP diff --git a/src/mesh/ItemValueUtils.hpp b/src/mesh/ItemValueUtils.hpp index c307ce4d6010e9ce0d40b4afdcb2ab4466e1d009..ab39d5c5c6423dac3d8c7d3fd2c1cbeffd1a9809 100644 --- a/src/mesh/ItemValueUtils.hpp +++ b/src/mesh/ItemValueUtils.hpp @@ -7,6 +7,7 @@ #include <mesh/ItemValue.hpp> #include <mesh/Synchronizer.hpp> #include <mesh/SynchronizerManager.hpp> +#include <utils/PugsTraits.hpp> #include <iostream> @@ -244,6 +245,7 @@ sum(const ItemValue<DataType, item_type>& item_value) if constexpr (std::is_arithmetic_v<data_type>) { value = 0; } else { + static_assert(is_tiny_vector_v<data_type> or is_tiny_matrix_v<data_type>, "invalid data type"); value = zero; } } diff --git a/src/scheme/DiscreteFunctionP0.hpp b/src/scheme/DiscreteFunctionP0.hpp index ccedb957d9e1fdb9b0c6643d66618709a9717cad..bb6b484a6bc10bd803e16b8bb54a7cba25a349de 100644 --- a/src/scheme/DiscreteFunctionP0.hpp +++ b/src/scheme/DiscreteFunctionP0.hpp @@ -659,6 +659,73 @@ class DiscreteFunctionP0 : public IDiscreteFunction return sum(f.m_cell_values); } + private: + class Integrator + { + private: + const DiscreteFunctionP0 m_function; + CellValue<const double> m_cell_volume; + CellValue<const bool> m_cell_is_owned; + + public: + PUGS_INLINE + operator data_type() + { + data_type reduced_value; + parallel_reduce(m_cell_volume.numberOfItems(), *this, reduced_value); + return reduced_value; + } + + PUGS_INLINE + void + operator()(const CellId& cell_id, data_type& data) const + { + if (m_cell_is_owned[cell_id]) { + data += m_cell_volume[cell_id] * m_function[cell_id]; + } + } + + PUGS_INLINE + void + join(volatile data_type& dst, const volatile data_type& src) const + { + dst += src; + } + + PUGS_INLINE + void + init(data_type& value) const + { + if constexpr (std::is_arithmetic_v<data_type>) { + value = 0; + } else { + static_assert(is_tiny_vector_v<data_type> or is_tiny_matrix_v<data_type>, "invalid data type"); + value = zero; + } + } + + PUGS_INLINE + Integrator(const DiscreteFunctionP0& function) : m_function(function) + { + const Mesh<Connectivity<Dimension>>& mesh = *function.m_mesh; + m_cell_volume = MeshDataManager::instance().getMeshData(mesh).Vj(); + m_cell_is_owned = mesh.connectivity().cellIsOwned(); + } + + PUGS_INLINE + ~Integrator() = default; + }; + + public: + PUGS_INLINE friend DataType + integrate(const DiscreteFunctionP0& f) + { + Assert(f.m_cell_values.isBuilt()); + const DataType integral = Integrator{f}; + + return parallel::allReduceSum(integral); + } + DiscreteFunctionP0(const std::shared_ptr<const MeshType>& mesh) : m_mesh{mesh}, m_cell_values{mesh->connectivity()} {} DiscreteFunctionP0(const std::shared_ptr<const MeshType>& mesh, const CellValue<DataType>& cell_value) diff --git a/src/utils/ArrayUtils.hpp b/src/utils/ArrayUtils.hpp index d85fb162756deb20d19971470ea1f40421dfdfa1..3b3438294291af1deafe733374e7de9ddf4982b6 100644 --- a/src/utils/ArrayUtils.hpp +++ b/src/utils/ArrayUtils.hpp @@ -2,6 +2,7 @@ #define ARRAY_UTILS_HPP #include <utils/PugsMacros.hpp> +#include <utils/PugsTraits.hpp> #include <utils/PugsUtils.hpp> #include <utils/Types.hpp> @@ -137,7 +138,7 @@ sum(const ArrayT<DataType>& array) class ArraySum { private: - const ArrayType& m_array; + const ArrayType m_array; public: PUGS_INLINE @@ -169,6 +170,7 @@ sum(const ArrayT<DataType>& array) if constexpr (std::is_arithmetic_v<data_type>) { value = 0; } else { + static_assert(is_tiny_vector_v<data_type> or is_tiny_matrix_v<data_type>, "invalid data type"); value = zero; } } diff --git a/src/utils/PugsUtils.hpp b/src/utils/PugsUtils.hpp index 91267a2af92928084ce07e1021baf6336e8a8f98..76d8ffd3feafd53d6fa2d5326fa18e8e65d95ca6 100644 --- a/src/utils/PugsUtils.hpp +++ b/src/utils/PugsUtils.hpp @@ -13,11 +13,11 @@ parallel_for(size_t size, const FunctionType& lambda, const std::string& label = Kokkos::parallel_for(size, lambda, label); } -template <typename ArrayType, typename ReturnType> +template <typename FunctorType, typename ReturnType> PUGS_FORCEINLINE void -parallel_reduce(size_t size, const ArrayType& array, ReturnType& value, const std::string& label = "") +parallel_reduce(size_t size, const FunctorType& functor, ReturnType& value, const std::string& label = "") { - Kokkos::parallel_reduce(label, size, array, value); + Kokkos::parallel_reduce(label, size, functor, value); } void setDefaultOMPEnvironment();