diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp index e4b52dc2277b95381213bff69af42749783fb655..08df9ba86ecb63a18bbb9e55fae1adfa544fcb23 100644 --- a/src/language/modules/SchemeModule.cpp +++ b/src/language/modules/SchemeModule.cpp @@ -91,6 +91,27 @@ SchemeModule::SchemeModule() )); + this->_addBuiltinFunction("integrate", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< + const IDiscreteFunction>(std::shared_ptr<const IMesh>, + const std::vector<std::shared_ptr<const IZoneDescriptor>>&, + std::shared_ptr<const IQuadratureDescriptor>, + std::shared_ptr<const IDiscreteFunctionDescriptor>, + const std::vector<FunctionSymbolId>&)>>( + [](std::shared_ptr<const IMesh> mesh, + const std::vector<std::shared_ptr<const IZoneDescriptor>>& integration_zone_list, + std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor, + std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor, + const std::vector<FunctionSymbolId>& function_id_list) + -> std::shared_ptr<const IDiscreteFunction> { + return DiscreteFunctionVectorIntegrator{mesh, integration_zone_list, + quadrature_descriptor, + discrete_function_descriptor, function_id_list} + .integrate(); + } + + )); + this ->_addBuiltinFunction("integrate", std::make_shared<BuiltinFunctionEmbedder< @@ -110,6 +131,20 @@ SchemeModule::SchemeModule() )); + this->_addBuiltinFunction( + "integrate", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< + const IDiscreteFunction>(std::shared_ptr<const IMesh>, const std::vector<std::shared_ptr<const IZoneDescriptor>>&, + std::shared_ptr<const IQuadratureDescriptor>, const FunctionSymbolId&)>>( + [](std::shared_ptr<const IMesh> mesh, + const std::vector<std::shared_ptr<const IZoneDescriptor>>& integration_zone_list, + std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor, + const FunctionSymbolId& function_id) -> std::shared_ptr<const IDiscreteFunction> { + return DiscreteFunctionIntegrator{mesh, integration_zone_list, quadrature_descriptor, function_id}.integrate(); + } + + )); + this->_addBuiltinFunction("integrate", std::make_shared<BuiltinFunctionEmbedder< std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IMesh>, @@ -136,6 +171,24 @@ SchemeModule::SchemeModule() )); + this->_addBuiltinFunction("interpolate", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< + const IDiscreteFunction>(std::shared_ptr<const IMesh>, + const std::vector<std::shared_ptr<const IZoneDescriptor>>&, + std::shared_ptr<const IDiscreteFunctionDescriptor>, + const std::vector<FunctionSymbolId>&)>>( + [](std::shared_ptr<const IMesh> mesh, + const std::vector<std::shared_ptr<const IZoneDescriptor>>& interpolation_zone_list, + std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor, + const std::vector<FunctionSymbolId>& function_id_list) + -> std::shared_ptr<const IDiscreteFunction> { + return DiscreteFunctionVectorInterpoler{mesh, interpolation_zone_list, + discrete_function_descriptor, function_id_list} + .interpolate(); + } + + )); + this->_addBuiltinFunction( "interpolate", std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< @@ -159,24 +212,6 @@ SchemeModule::SchemeModule() )); - this->_addBuiltinFunction("interpolate", - std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< - const IDiscreteFunction>(std::shared_ptr<const IMesh>, - const std::vector<std::shared_ptr<const IZoneDescriptor>>&, - std::shared_ptr<const IDiscreteFunctionDescriptor>, - const std::vector<FunctionSymbolId>&)>>( - [](std::shared_ptr<const IMesh> mesh, - const std::vector<std::shared_ptr<const IZoneDescriptor>>& interpolation_zone_list, - std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor, - const std::vector<FunctionSymbolId>& function_id_list) - -> std::shared_ptr<const IDiscreteFunction> { - return DiscreteFunctionVectorInterpoler{mesh, interpolation_zone_list, - discrete_function_descriptor, function_id_list} - .interpolate(); - } - - )); - this->_addBuiltinFunction("interpolate", std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< const IDiscreteFunction>(std::shared_ptr<const IMesh>, diff --git a/src/scheme/DiscreteFunctionIntegrator.cpp b/src/scheme/DiscreteFunctionIntegrator.cpp index 91cf921df2764ad13f4470687fc4cc5f4d6bced1..fe0757cc0ef74e52b887e751fa678e7be6bdb186 100644 --- a/src/scheme/DiscreteFunctionIntegrator.cpp +++ b/src/scheme/DiscreteFunctionIntegrator.cpp @@ -1,13 +1,75 @@ #include <scheme/DiscreteFunctionIntegrator.hpp> #include <language/utils/IntegrateCellValue.hpp> +#include <mesh/MeshCellZone.hpp> #include <scheme/DiscreteFunctionP0.hpp> #include <utils/Exceptions.hpp> template <size_t Dimension, typename DataType, typename ValueType> std::shared_ptr<IDiscreteFunction> -DiscreteFunctionIntegrator::_integrate() const +DiscreteFunctionIntegrator::_integrateOnZoneList() const +{ + static_assert(std::is_convertible_v<DataType, ValueType>); + Assert(m_zone_list.size() > 0, "no zone list provided"); + + using MeshType = Mesh<Connectivity<Dimension>>; + + std::shared_ptr p_mesh = std::dynamic_pointer_cast<const MeshType>(m_mesh); + + CellValue<bool> is_in_zone{p_mesh->connectivity()}; + is_in_zone.fill(false); + + size_t number_of_cells = 0; + for (const auto& zone : m_zone_list) { + auto mesh_cell_zone = getMeshCellZone(*p_mesh, *zone); + const auto& cell_list = mesh_cell_zone.cellList(); + for (size_t i_cell = 0; i_cell < cell_list.size(); ++i_cell) { + const CellId cell_id = cell_list[i_cell]; + if (is_in_zone[cell_id]) { + std::ostringstream os; + os << "cell " << cell_id << " (number " << p_mesh->connectivity().cellNumber()[cell_id] + << ") is present multiple times in zone list"; + throw NormalError(os.str()); + } + ++number_of_cells; + is_in_zone[cell_id] = true; + } + } + + Array<CellId> zone_cell_list{number_of_cells}; + { + size_t i_cell = 0; + for (CellId cell_id = 0; cell_id < p_mesh->numberOfCells(); ++cell_id) { + if (is_in_zone[cell_id]) { + zone_cell_list[i_cell++] = cell_id; + } + } + } + + Array<DataType> array = + IntegrateCellValue<DataType(TinyVector<Dimension>)>::template integrate<MeshType>(m_function_id, + *m_quadrature_descriptor, *p_mesh, + zone_cell_list); + + CellValue<ValueType> cell_value{p_mesh->connectivity()}; + if constexpr (is_tiny_vector_v<ValueType> or is_tiny_matrix_v<ValueType>) { + cell_value.fill(zero); + } else { + cell_value.fill(0); + } + + parallel_for( + zone_cell_list.size(), PUGS_LAMBDA(const size_t i_cell) { cell_value[zone_cell_list[i_cell]] = array[i_cell]; }); + + return std::make_shared<DiscreteFunctionP0<Dimension, ValueType>>(p_mesh, cell_value); +} + +template <size_t Dimension, typename DataType, typename ValueType> +std::shared_ptr<IDiscreteFunction> +DiscreteFunctionIntegrator::_integrateGlobally() const { + Assert(m_zone_list.size() == 0, "invalid call when zones are defined"); + using MeshType = Mesh<Connectivity<Dimension>>; std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(m_mesh); @@ -33,6 +95,17 @@ DiscreteFunctionIntegrator::_integrate() const } } +template <size_t Dimension, typename DataType, typename ValueType> +std::shared_ptr<IDiscreteFunction> +DiscreteFunctionIntegrator::_integrate() const +{ + if (m_zone_list.size() == 0) { + return this->_integrateGlobally<Dimension, DataType, ValueType>(); + } else { + return this->_integrateOnZoneList<Dimension, DataType, ValueType>(); + } +} + template <size_t Dimension> std::shared_ptr<IDiscreteFunction> DiscreteFunctionIntegrator::_integrate() const diff --git a/src/scheme/DiscreteFunctionIntegrator.hpp b/src/scheme/DiscreteFunctionIntegrator.hpp index 1784f891eaa6fd7471b17006b3c9f277c31e51dd..21a461d54561d67f1f745d3257ec76ee514d264a 100644 --- a/src/scheme/DiscreteFunctionIntegrator.hpp +++ b/src/scheme/DiscreteFunctionIntegrator.hpp @@ -4,6 +4,7 @@ #include <analysis/IQuadratureDescriptor.hpp> #include <language/utils/FunctionSymbolId.hpp> #include <mesh/IMesh.hpp> +#include <mesh/IZoneDescriptor.hpp> #include <scheme/IDiscreteFunction.hpp> #include <memory> @@ -12,9 +13,16 @@ class DiscreteFunctionIntegrator { private: std::shared_ptr<const IMesh> m_mesh; + const std::vector<std::shared_ptr<const IZoneDescriptor>> m_zone_list; std::shared_ptr<const IQuadratureDescriptor> m_quadrature_descriptor; const FunctionSymbolId m_function_id; + template <size_t Dimension, typename DataType, typename ValueType = DataType> + std::shared_ptr<IDiscreteFunction> _integrateOnZoneList() const; + + template <size_t Dimension, typename DataType, typename ValueType = DataType> + std::shared_ptr<IDiscreteFunction> _integrateGlobally() const; + template <size_t Dimension, typename DataType, typename ValueType = DataType> std::shared_ptr<IDiscreteFunction> _integrate() const; @@ -30,6 +38,13 @@ class DiscreteFunctionIntegrator : m_mesh{mesh}, m_quadrature_descriptor{quadrature_descriptor}, m_function_id{function_id} {} + DiscreteFunctionIntegrator(const std::shared_ptr<const IMesh>& mesh, + const std::vector<std::shared_ptr<const IZoneDescriptor>>& zone_list, + const std::shared_ptr<const IQuadratureDescriptor>& quadrature_descriptor, + const FunctionSymbolId& function_id) + : m_mesh{mesh}, m_zone_list{zone_list}, m_quadrature_descriptor{quadrature_descriptor}, m_function_id{function_id} + {} + DiscreteFunctionIntegrator(const DiscreteFunctionIntegrator&) = delete; DiscreteFunctionIntegrator(DiscreteFunctionIntegrator&&) = delete; diff --git a/src/scheme/DiscreteFunctionVectorIntegrator.cpp b/src/scheme/DiscreteFunctionVectorIntegrator.cpp index 6d8937f84aeba6ae96ac5fc6e5ba523e5781f239..105dd0ff9ef05a9af8bf6389ac886f810421f6d1 100644 --- a/src/scheme/DiscreteFunctionVectorIntegrator.cpp +++ b/src/scheme/DiscreteFunctionVectorIntegrator.cpp @@ -1,14 +1,76 @@ #include <scheme/DiscreteFunctionVectorIntegrator.hpp> #include <language/utils/IntegrateCellArray.hpp> - +#include <mesh/MeshCellZone.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> #include <utils/Exceptions.hpp> template <size_t Dimension, typename DataType> std::shared_ptr<IDiscreteFunction> -DiscreteFunctionVectorIntegrator::_integrate() const +DiscreteFunctionVectorIntegrator::_integrateOnZoneList() const +{ + Assert(m_zone_list.size() > 0, "no zone list provided"); + + std::shared_ptr p_mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(m_mesh); + + CellValue<bool> is_in_zone{p_mesh->connectivity()}; + is_in_zone.fill(false); + + size_t number_of_cells = 0; + for (const auto& zone : m_zone_list) { + auto mesh_cell_zone = getMeshCellZone(*p_mesh, *zone); + const auto& cell_list = mesh_cell_zone.cellList(); + for (size_t i_cell = 0; i_cell < cell_list.size(); ++i_cell) { + const CellId cell_id = cell_list[i_cell]; + if (is_in_zone[cell_id]) { + std::ostringstream os; + os << "cell " << cell_id << " (number " << p_mesh->connectivity().cellNumber()[cell_id] + << ") is present multiple times in zone list"; + throw NormalError(os.str()); + } + ++number_of_cells; + is_in_zone[cell_id] = true; + } + } + + Array<CellId> zone_cell_list{number_of_cells}; + { + size_t i_cell = 0; + for (CellId cell_id = 0; cell_id < p_mesh->numberOfCells(); ++cell_id) { + if (is_in_zone[cell_id]) { + zone_cell_list[i_cell++] = cell_id; + } + } + } + + Table<const DataType> table = + IntegrateCellArray<DataType(TinyVector<Dimension>)>::template integrate(m_function_id_list, + *m_quadrature_descriptor, *p_mesh, + zone_cell_list); + + CellArray<DataType> cell_array{p_mesh->connectivity(), m_function_id_list.size()}; + if constexpr (is_tiny_vector_v<DataType> or is_tiny_matrix_v<DataType>) { + cell_array.fill(zero); + } else { + cell_array.fill(0); + } + + parallel_for( + zone_cell_list.size(), PUGS_LAMBDA(const size_t i_cell) { + for (size_t i = 0; i < table.numberOfColumns(); ++i) { + cell_array[zone_cell_list[i_cell]][i] = table[i_cell][i]; + } + }); + + return std::make_shared<DiscreteFunctionP0Vector<Dimension, DataType>>(p_mesh, cell_array); +} + +template <size_t Dimension, typename DataType> +std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVectorIntegrator::_integrateGlobally() const { + Assert(m_zone_list.size() == 0, "invalid call when zones are defined"); + std::shared_ptr mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(m_mesh); return std::make_shared< @@ -17,6 +79,17 @@ DiscreteFunctionVectorIntegrator::_integrate() const *m_quadrature_descriptor, *mesh)); } +template <size_t Dimension, typename DataType> +std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVectorIntegrator::_integrate() const +{ + if (m_zone_list.size() == 0) { + return this->_integrateGlobally<Dimension, DataType>(); + } else { + return this->_integrateOnZoneList<Dimension, DataType>(); + } +} + template <size_t Dimension> std::shared_ptr<IDiscreteFunction> DiscreteFunctionVectorIntegrator::_integrate() const diff --git a/src/scheme/DiscreteFunctionVectorIntegrator.hpp b/src/scheme/DiscreteFunctionVectorIntegrator.hpp index 01e086e7efd9c2334d07dfdb3cf8dce1f33e49f1..55f5fe3572cbb237e28b9bf86ff7bda19db20a98 100644 --- a/src/scheme/DiscreteFunctionVectorIntegrator.hpp +++ b/src/scheme/DiscreteFunctionVectorIntegrator.hpp @@ -4,6 +4,7 @@ #include <analysis/IQuadratureDescriptor.hpp> #include <language/utils/FunctionSymbolId.hpp> #include <mesh/IMesh.hpp> +#include <mesh/IZoneDescriptor.hpp> #include <scheme/IDiscreteFunction.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> @@ -14,10 +15,17 @@ class DiscreteFunctionVectorIntegrator { private: std::shared_ptr<const IMesh> m_mesh; + const std::vector<std::shared_ptr<const IZoneDescriptor>> m_zone_list; std::shared_ptr<const IQuadratureDescriptor> m_quadrature_descriptor; std::shared_ptr<const IDiscreteFunctionDescriptor> m_discrete_function_descriptor; const std::vector<FunctionSymbolId> m_function_id_list; + template <size_t Dimension, typename DataType> + std::shared_ptr<IDiscreteFunction> _integrateOnZoneList() const; + + template <size_t Dimension, typename DataType> + std::shared_ptr<IDiscreteFunction> _integrateGlobally() const; + template <size_t Dimension, typename DataType> std::shared_ptr<IDiscreteFunction> _integrate() const; @@ -38,6 +46,19 @@ class DiscreteFunctionVectorIntegrator m_function_id_list{function_id_list} {} + DiscreteFunctionVectorIntegrator( + const std::shared_ptr<const IMesh>& mesh, + const std::vector<std::shared_ptr<const IZoneDescriptor>>& zone_list, + const std::shared_ptr<const IQuadratureDescriptor>& quadrature_descriptor, + const std::shared_ptr<const IDiscreteFunctionDescriptor>& discrete_function_descriptor, + const std::vector<FunctionSymbolId>& function_id_list) + : m_mesh{mesh}, + m_zone_list{zone_list}, + m_quadrature_descriptor(quadrature_descriptor), + m_discrete_function_descriptor{discrete_function_descriptor}, + m_function_id_list{function_id_list} + {} + DiscreteFunctionVectorIntegrator(const DiscreteFunctionVectorIntegrator&) = delete; DiscreteFunctionVectorIntegrator(DiscreteFunctionVectorIntegrator&&) = delete;