diff --git a/src/algebra/TinyMatrix.hpp b/src/algebra/TinyMatrix.hpp index bc64d550979c76055c2669b0555679daa5d351b5..636ff19c18112c582c8968e8dc6f4df5ebdee726 100644 --- a/src/algebra/TinyMatrix.hpp +++ b/src/algebra/TinyMatrix.hpp @@ -57,11 +57,11 @@ class [[nodiscard]] TinyMatrix PUGS_INLINE constexpr TinyMatrix operator-() const { - TinyMatrix opposed; + TinyMatrix opposite; for (size_t i = 0; i < N * N; ++i) { - opposed.m_values[i] = -m_values[i]; + opposite.m_values[i] = -m_values[i]; } - return opposed; + return opposite; } PUGS_INLINE diff --git a/src/algebra/TinyVector.hpp b/src/algebra/TinyVector.hpp index 3f3c10920f5ae75c6b37a0761393cad19a77786b..c3146a2be9932353388d34d15862056f952631fb 100644 --- a/src/algebra/TinyVector.hpp +++ b/src/algebra/TinyVector.hpp @@ -34,11 +34,11 @@ class [[nodiscard]] TinyVector PUGS_INLINE constexpr TinyVector operator-() const { - TinyVector opposed; + TinyVector opposite; for (size_t i = 0; i < N; ++i) { - opposed.m_values[i] = -m_values[i]; + opposite.m_values[i] = -m_values[i]; } - return opposed; + return opposite; } PUGS_INLINE diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp index 32117039587e2c53907ea030ac73a7e10e544255..cc26d368ee6cb0d6a3f105604ae6484628d69890 100644 --- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp @@ -37,6 +37,12 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode ASTNode& lhs_node = *node.children[0]; ASTNode& rhs_node = *node.children[1]; + if (rhs_node.m_data_type == ASTNodeDataType::list_t) { + if ((lhs_node.m_data_type == ASTNodeDataType::vector_t) or (lhs_node.m_data_type == ASTNodeDataType::matrix_t)) { + ASTNodeNaturalConversionChecker(rhs_node, lhs_node.m_data_type); + } + } + node.m_node_processor = optional_processor_builder.value()->getNodeProcessor(lhs_node, rhs_node); } else { std::ostringstream error_message; diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index 24841d797529750ba2adc6664c278a56c615fdd2..44e30ec2e11fba9db2701268d582089f9cb839f4 100644 --- a/src/language/ast/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp @@ -203,7 +203,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const if (nb_parameter_domains != nb_parameter_names) { std::ostringstream message; - message << "note: number of product spaces (" << nb_parameter_domains << ") " << rang::fgB::yellow + message << "number of product spaces (" << nb_parameter_domains << ") " << rang::fgB::yellow << parameters_domain_node.string() << rang::style::reset << rang::style::bold << " differs from number of variables (" << nb_parameter_names << ") " << rang::fgB::yellow << parameters_name_node.string() << rang::style::reset; @@ -255,7 +255,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const std::ostringstream message; message << "expecting " << image_type.dimension() << " scalar expressions or an " << dataTypeName(image_type) << ", found " << nb_image_expressions << " scalar expressions"; - throw ParseError(message.str(), image_domain_node.begin()); + throw ParseError(message.str(), image_expression_node.begin()); } } else if (image_domain_node.is_type<language::matrix_type>()) { ASTNodeDataType image_type = getMatrixDataType(image_domain_node); @@ -263,7 +263,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const std::ostringstream message; message << "expecting " << image_type.nbRows() * image_type.nbColumns() << " scalar expressions or an " << dataTypeName(image_type) << ", found " << nb_image_expressions << " scalar expressions"; - throw ParseError(message.str(), image_domain_node.begin()); + throw ParseError(message.str(), image_expression_node.begin()); } } else { std::ostringstream message; @@ -290,8 +290,26 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const } else if (symbol_table->has(n.string(), n.begin())) { n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>(); } else { + // LCOV_EXCL_START throw UnexpectedError("could not find symbol " + n.string()); + // LCOV_EXCL_STOP } + } else if (n.is_type<language::type_name_id>()) { + const std::string& type_name_id = n.string(); + + auto& symbol_table = *n.m_symbol_table; + + const auto [i_type_symbol, found] = symbol_table.find(type_name_id, n.begin()); + if (not found) { + throw ParseError("undefined type identifier", std::vector{n.begin()}); + } else if (i_type_symbol->attributes().dataType() != ASTNodeDataType::type_name_id_t) { + std::ostringstream os; + os << "invalid type identifier, '" << type_name_id << "' was previously defined as a '" + << dataTypeName(i_type_symbol->attributes().dataType()) << '\''; + throw ParseError(os.str(), std::vector{n.begin()}); + } + + n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::type_id_t>(type_name_id); } } for (auto& child : n.children) { @@ -339,22 +357,6 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const value_type = getMatrixDataType(image_node); } else if (image_node.is_type<language::string_type>()) { value_type = ASTNodeDataType::build<ASTNodeDataType::string_t>(); - } else if (image_node.is_type<language::type_name_id>()) { - const std::string& type_name_id = image_node.string(); - - auto& symbol_table = *image_node.m_symbol_table; - - const auto [i_type_symbol, found] = symbol_table.find(type_name_id, image_node.begin()); - if (not found) { - throw ParseError("undefined type identifier", std::vector{image_node.begin()}); - } else if (i_type_symbol->attributes().dataType() != ASTNodeDataType::type_name_id_t) { - std::ostringstream os; - os << "invalid type identifier, '" << type_name_id << "' was previously defined as a '" - << dataTypeName(i_type_symbol->attributes().dataType()) << '\''; - throw ParseError(os.str(), std::vector{image_node.begin()}); - } - - value_type = ASTNodeDataType::build<ASTNodeDataType::type_id_t>(type_name_id); } // LCOV_EXCL_START diff --git a/src/language/ast/ASTSymbolTableBuilder.cpp b/src/language/ast/ASTSymbolTableBuilder.cpp index 44058de6f3739580dbcf3d34e22970647c6bb2ad..2e019d8db10301f274cfa2946d39f290ed5a4da5 100644 --- a/src/language/ast/ASTSymbolTableBuilder.cpp +++ b/src/language/ast/ASTSymbolTableBuilder.cpp @@ -77,10 +77,12 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> } else if (n.is_type<language::function_definition>()) { auto register_and_initialize_symbol = [&](const ASTNode& argument_node) { if (symbol_table->getBuiltinFunctionSymbolList(argument_node.string(), argument_node.begin()).size() > 0) { + // LCOV_EXCL_START std::ostringstream error_message; error_message << "symbol '" << rang::fg::red << argument_node.string() << rang::fg::reset << "' already denotes a builtin function!"; throw ParseError(error_message.str(), std::vector{argument_node.begin()}); + // LCOV_EXCL_STOP } auto [i_symbol, success] = symbol_table->add(argument_node.string(), argument_node.begin()); diff --git a/src/language/modules/BinaryOperatorRegisterForVh.cpp b/src/language/modules/BinaryOperatorRegisterForVh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..90f0c295a77578a59a7eae42706333d37d9084cc --- /dev/null +++ b/src/language/modules/BinaryOperatorRegisterForVh.cpp @@ -0,0 +1,305 @@ +#include <language/modules/BinaryOperatorRegisterForVh.hpp> + +#include <language/modules/SchemeModule.hpp> +#include <language/utils/BinaryOperatorProcessorBuilder.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/DataVariant.hpp> +#include <language/utils/EmbeddedIDiscreteFunctionOperators.hpp> +#include <language/utils/OperatorRepository.hpp> +#include <scheme/IDiscreteFunction.hpp> + +void +BinaryOperatorRegisterForVh::_register_plus() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, bool, + std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + int64_t, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + uint64_t, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, double, + std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, bool>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, int64_t>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, uint64_t>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, double>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + TinyVector<1>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + TinyVector<2>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + TinyVector<3>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + TinyMatrix<1>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + TinyMatrix<2>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + TinyMatrix<3>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyVector<1>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyVector<2>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyVector<3>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyMatrix<1>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyMatrix<2>>>()); + + repository.addBinaryOperator<language::plus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyMatrix<3>>>()); +} + +void +BinaryOperatorRegisterForVh::_register_minus() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, bool, + std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + int64_t, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + uint64_t, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + double, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, bool>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, int64_t>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, uint64_t>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, double>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + TinyVector<1>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + TinyVector<2>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + TinyVector<3>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + TinyMatrix<1>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + TinyMatrix<2>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + TinyMatrix<3>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyVector<1>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyVector<2>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyVector<3>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyMatrix<1>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyMatrix<2>>>()); + + repository.addBinaryOperator<language::minus_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyMatrix<3>>>()); +} + +void +BinaryOperatorRegisterForVh::_register_multiply() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + bool, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + int64_t, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + uint64_t, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + double, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, bool>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, int64_t>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, uint64_t>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, double>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + TinyMatrix<1>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + TinyMatrix<2>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + TinyMatrix<3>, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyVector<1>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyVector<2>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyVector<3>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyMatrix<1>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyMatrix<2>>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, TinyMatrix<3>>>()); +} + +void +BinaryOperatorRegisterForVh::_register_divide() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addBinaryOperator<language::divide_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::divide_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const IDiscreteFunction>, bool, + std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::divide_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const IDiscreteFunction>, + int64_t, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::divide_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const IDiscreteFunction>, + uint64_t, std::shared_ptr<const IDiscreteFunction>>>()); + + repository.addBinaryOperator<language::divide_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const IDiscreteFunction>, + double, std::shared_ptr<const IDiscreteFunction>>>()); +} + +BinaryOperatorRegisterForVh::BinaryOperatorRegisterForVh() +{ + this->_register_plus(); + this->_register_minus(); + this->_register_multiply(); + this->_register_divide(); +} diff --git a/src/language/modules/BinaryOperatorRegisterForVh.hpp b/src/language/modules/BinaryOperatorRegisterForVh.hpp new file mode 100644 index 0000000000000000000000000000000000000000..86848e1b3037418aab36159b78d0c9f2578b4fde --- /dev/null +++ b/src/language/modules/BinaryOperatorRegisterForVh.hpp @@ -0,0 +1,16 @@ +#ifndef BINARY_OPERATOR_REGISTER_FOR_VH_HPP +#define BINARY_OPERATOR_REGISTER_FOR_VH_HPP + +class BinaryOperatorRegisterForVh +{ + private: + void _register_plus(); + void _register_minus(); + void _register_multiply(); + void _register_divide(); + + public: + BinaryOperatorRegisterForVh(); +}; + +#endif // BINARY_OPERATOR_REGISTER_FOR_VH_HPP diff --git a/src/language/modules/CMakeLists.txt b/src/language/modules/CMakeLists.txt index dfc777168d454337ffbd38ef084f37f50924b117..f7f1baeafe34261a38033dd3d2db828df334ce25 100644 --- a/src/language/modules/CMakeLists.txt +++ b/src/language/modules/CMakeLists.txt @@ -1,13 +1,16 @@ # ------------------- Source files -------------------- add_library(PugsLanguageModules + BinaryOperatorRegisterForVh.cpp BuiltinModule.cpp CoreModule.cpp LinearSolverModule.cpp + MathFunctionRegisterForVh.cpp MathModule.cpp MeshModule.cpp ModuleRepository.cpp SchemeModule.cpp + UnaryOperatorRegisterForVh.cpp UtilsModule.cpp WriterModule.cpp ) diff --git a/src/language/modules/MathFunctionRegisterForVh.cpp b/src/language/modules/MathFunctionRegisterForVh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..68b22b552f932a1fb48baeb96d6742a74a4717c2 --- /dev/null +++ b/src/language/modules/MathFunctionRegisterForVh.cpp @@ -0,0 +1,150 @@ +#include <language/modules/MathFunctionRegisterForVh.hpp> + +#include <language/modules/SchemeModule.hpp> +#include <language/utils/BuiltinFunctionEmbedder.hpp> +#include <language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp> +#include <scheme/IDiscreteFunction.hpp> +#include <scheme/IDiscreteFunctionDescriptor.hpp> + +MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module) +{ + scheme_module._addBuiltinFunction("sqrt", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return sqrt(a); })); + + scheme_module._addBuiltinFunction("abs", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return abs(a); })); + + scheme_module._addBuiltinFunction("sin", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return sin(a); })); + + scheme_module._addBuiltinFunction("cos", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return cos(a); })); + + scheme_module._addBuiltinFunction("tan", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return tan(a); })); + + scheme_module._addBuiltinFunction("asin", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return asin(a); })); + + scheme_module._addBuiltinFunction("acos", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return acos(a); })); + + scheme_module._addBuiltinFunction("atan", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return atan(a); })); + + scheme_module + ._addBuiltinFunction("atan2", + std::make_shared<BuiltinFunctionEmbedder< + std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a, std::shared_ptr<const IDiscreteFunction> b) + -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); })); + + scheme_module + ._addBuiltinFunction("atan2", + std::make_shared<BuiltinFunctionEmbedder< + std::shared_ptr<const IDiscreteFunction>(double, std::shared_ptr<const IDiscreteFunction>)>>( + [](double a, std::shared_ptr<const IDiscreteFunction> b) + -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); })); + + scheme_module + ._addBuiltinFunction("atan2", + std::make_shared<BuiltinFunctionEmbedder< + std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, double)>>( + [](std::shared_ptr<const IDiscreteFunction> a, + double b) -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); })); + + scheme_module._addBuiltinFunction("sinh", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return sinh(a); })); + + scheme_module._addBuiltinFunction("cosh", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return cosh(a); })); + + scheme_module._addBuiltinFunction("tanh", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return tanh(a); })); + + scheme_module._addBuiltinFunction("asinh", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return asinh(a); })); + + scheme_module._addBuiltinFunction("acosh", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return acosh(a); })); + + scheme_module._addBuiltinFunction("atanh", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return atanh(a); })); + + scheme_module._addBuiltinFunction("exp", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return exp(a); })); + + scheme_module._addBuiltinFunction("log", + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>( + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a) + -> std::shared_ptr<const IDiscreteFunction> { return log(a); })); + + scheme_module + ._addBuiltinFunction("pow", + std::make_shared<BuiltinFunctionEmbedder< + std::shared_ptr<const IDiscreteFunction>(double, std::shared_ptr<const IDiscreteFunction>)>>( + [](double a, std::shared_ptr<const IDiscreteFunction> b) + -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); })); + + scheme_module + ._addBuiltinFunction("pow", + std::make_shared<BuiltinFunctionEmbedder< + std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, double)>>( + [](std::shared_ptr<const IDiscreteFunction> a, + double b) -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); })); + + scheme_module + ._addBuiltinFunction("pow", + std::make_shared<BuiltinFunctionEmbedder< + std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>)>>( + [](std::shared_ptr<const IDiscreteFunction> a, std::shared_ptr<const IDiscreteFunction> b) + -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); })); +} diff --git a/src/language/modules/MathFunctionRegisterForVh.hpp b/src/language/modules/MathFunctionRegisterForVh.hpp new file mode 100644 index 0000000000000000000000000000000000000000..95ee461bc8e999fc75e273c31c0aea4505edda0e --- /dev/null +++ b/src/language/modules/MathFunctionRegisterForVh.hpp @@ -0,0 +1,12 @@ +#ifndef MATH_FUNCTION_REGISTER_FOR_VH_HPP +#define MATH_FUNCTION_REGISTER_FOR_VH_HPP + +class SchemeModule; + +class MathFunctionRegisterForVh +{ + public: + MathFunctionRegisterForVh(SchemeModule& module); +}; + +#endif // MATH_FUNCTION_REGISTER_FOR_VH_HPP diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp index 7c0d55cf1f23e9f5b186f220fbe2608e2ada7b7f..d6f9227f4b66e1f1abc442ca36f2cc21a8b9b04b 100644 --- a/src/language/modules/SchemeModule.cpp +++ b/src/language/modules/SchemeModule.cpp @@ -1,14 +1,16 @@ #include <language/modules/SchemeModule.hpp> +#include <language/modules/BinaryOperatorRegisterForVh.hpp> +#include <language/modules/MathFunctionRegisterForVh.hpp> +#include <language/modules/UnaryOperatorRegisterForVh.hpp> #include <language/utils/BinaryOperatorProcessorBuilder.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> -#include <language/utils/EmbeddedIDiscreteFunctionOperators.hpp> -#include <language/utils/OperatorRepository.hpp> #include <language/utils/TypeDescriptor.hpp> #include <mesh/Mesh.hpp> #include <scheme/AcousticSolver.hpp> #include <scheme/DirichletBoundaryConditionDescriptor.hpp> #include <scheme/DiscreteFunctionDescriptorP0.hpp> +#include <scheme/DiscreteFunctionDescriptorP0Vector.hpp> #include <scheme/DiscreteFunctionInterpoler.hpp> #include <scheme/DiscreteFunctionUtils.hpp> #include <scheme/DiscreteFunctionVectorInterpoler.hpp> @@ -43,6 +45,15 @@ SchemeModule::SchemeModule() )); + this->_addBuiltinFunction("P0Vector", + std::make_shared< + BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunctionDescriptor>()>>( + []() -> std::shared_ptr<const IDiscreteFunctionDescriptor> { + return std::make_shared<DiscreteFunctionDescriptorP0Vector>(); + } + + )); + this->_addBuiltinFunction( "interpolate", std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< @@ -64,7 +75,17 @@ SchemeModule::SchemeModule() [](std::shared_ptr<const IMesh> mesh, std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor, const FunctionSymbolId& function_id) -> std::shared_ptr<const IDiscreteFunction> { - return DiscreteFunctionInterpoler{mesh, discrete_function_descriptor, function_id}.interpolate(); + switch (discrete_function_descriptor->type()) { + case DiscreteFunctionType::P0: { + return DiscreteFunctionInterpoler{mesh, discrete_function_descriptor, function_id}.interpolate(); + } + case DiscreteFunctionType::P0Vector: { + return DiscreteFunctionVectorInterpoler{mesh, discrete_function_descriptor, {function_id}}.interpolate(); + } + default: { + throw NormalError("invalid function descriptor type"); + } + } } )); @@ -296,82 +317,13 @@ SchemeModule::SchemeModule() [](const std::shared_ptr<const IDiscreteFunction>& c) -> double { return acoustic_dt(c); } )); + + MathFunctionRegisterForVh{*this}; } void SchemeModule::registerOperators() const { - OperatorRepository& repository = OperatorRepository::instance(); - - repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::divide_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - bool, std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - int64_t, std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - uint64_t, std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - double, std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<1>, std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<2>, std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<3>, std::shared_ptr<const IDiscreteFunction>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, TinyVector<1>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, TinyVector<2>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, TinyVector<3>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, TinyMatrix<1>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, TinyMatrix<2>>>()); - - repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, TinyMatrix<3>>>()); + BinaryOperatorRegisterForVh{}; + UnaryOperatorRegisterForVh{}; } diff --git a/src/language/modules/SchemeModule.hpp b/src/language/modules/SchemeModule.hpp index 8e5ee95d8f6797e705cba0436829a565c7714e6c..758b5f9c56fcdc928adfc4678a0a02a8dcfa5bd8 100644 --- a/src/language/modules/SchemeModule.hpp +++ b/src/language/modules/SchemeModule.hpp @@ -27,6 +27,8 @@ inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IDiscreteFu class SchemeModule : public BuiltinModule { + friend class MathFunctionRegisterForVh; + public: std::string_view name() const final diff --git a/src/language/modules/UnaryOperatorRegisterForVh.cpp b/src/language/modules/UnaryOperatorRegisterForVh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1dc85aa9dd11be2f5a6d159d8f1a70254d68c7b --- /dev/null +++ b/src/language/modules/UnaryOperatorRegisterForVh.cpp @@ -0,0 +1,24 @@ +#include <language/modules/UnaryOperatorRegisterForVh.hpp> + +#include <language/modules/SchemeModule.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/DataVariant.hpp> +#include <language/utils/EmbeddedIDiscreteFunctionOperators.hpp> +#include <language/utils/OperatorRepository.hpp> +#include <language/utils/UnaryOperatorProcessorBuilder.hpp> +#include <scheme/IDiscreteFunction.hpp> + +void +UnaryOperatorRegisterForVh::_register_unary_minus() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + repository.addUnaryOperator<language::unary_minus>( + std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, std::shared_ptr<const IDiscreteFunction>, + std::shared_ptr<const IDiscreteFunction>>>()); +} + +UnaryOperatorRegisterForVh::UnaryOperatorRegisterForVh() +{ + this->_register_unary_minus(); +} diff --git a/src/language/modules/UnaryOperatorRegisterForVh.hpp b/src/language/modules/UnaryOperatorRegisterForVh.hpp new file mode 100644 index 0000000000000000000000000000000000000000..65ea35bb6d661e6257845141b4301ca8921bb169 --- /dev/null +++ b/src/language/modules/UnaryOperatorRegisterForVh.hpp @@ -0,0 +1,13 @@ +#ifndef UNARY_OPERATOR_REGISTER_FOR_VH_HPP +#define UNARY_OPERATOR_REGISTER_FOR_VH_HPP + +class UnaryOperatorRegisterForVh +{ + private: + void _register_unary_minus(); + + public: + UnaryOperatorRegisterForVh(); +}; + +#endif // UNARY_OPERATOR_REGISTER_FOR_VH_HPP diff --git a/src/language/node_processor/BinaryExpressionProcessor.hpp b/src/language/node_processor/BinaryExpressionProcessor.hpp index cfbff72617d7b99e68ea9693eca96fa718c3f918..3af45c3871d6d6b4886f3bd3bf510d7c53f333aa 100644 --- a/src/language/node_processor/BinaryExpressionProcessor.hpp +++ b/src/language/node_processor/BinaryExpressionProcessor.hpp @@ -8,6 +8,9 @@ #include <type_traits> +template <typename DataType> +class DataHandler; + template <typename Op> struct BinOp; @@ -201,4 +204,113 @@ struct BinaryExpressionProcessor final : public INodeProcessor BinaryExpressionProcessor(ASTNode& node) : m_node{node} {} }; +template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT> +struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared_ptr<A_DataT>, std::shared_ptr<B_DataT>> + final : public INodeProcessor +{ + private: + ASTNode& m_node; + + PUGS_INLINE DataVariant + _eval(const DataVariant& a, const DataVariant& b) + { + const auto& embedded_a = std::get<EmbeddedData>(a); + const auto& embedded_b = std::get<EmbeddedData>(b); + + std::shared_ptr a_ptr = dynamic_cast<const DataHandler<A_DataT>&>(embedded_a.get()).data_ptr(); + + std::shared_ptr b_ptr = dynamic_cast<const DataHandler<B_DataT>&>(embedded_b.get()).data_ptr(); + + return EmbeddedData(std::make_shared<DataHandler<ValueT>>(BinOp<BinaryOpT>().eval(a_ptr, b_ptr))); + } + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + try { + return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy)); + } + catch (const NormalError& error) { + throw ParseError(error.what(), m_node.begin()); + } + } + + BinaryExpressionProcessor(ASTNode& node) : m_node{node} {} +}; + +template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT> +struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, A_DataT, std::shared_ptr<B_DataT>> final + : public INodeProcessor +{ + private: + ASTNode& m_node; + + PUGS_INLINE DataVariant + _eval(const DataVariant& a, const DataVariant& b) + { + if constexpr ((std::is_arithmetic_v<A_DataT>) or (is_tiny_vector_v<A_DataT>) or (is_tiny_matrix_v<A_DataT>)) { + const auto& a_value = std::get<A_DataT>(a); + const auto& embedded_b = std::get<EmbeddedData>(b); + + std::shared_ptr b_ptr = dynamic_cast<const DataHandler<B_DataT>&>(embedded_b.get()).data_ptr(); + + return EmbeddedData(std::make_shared<DataHandler<ValueT>>(BinOp<BinaryOpT>().eval(a_value, b_ptr))); + } else { + static_assert(std::is_arithmetic_v<A_DataT>, "invalid left hand side type"); + } + } + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + try { + return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy)); + } + catch (const NormalError& error) { + throw ParseError(error.what(), m_node.begin()); + } + } + + BinaryExpressionProcessor(ASTNode& node) : m_node{node} {} +}; + +template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT> +struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared_ptr<A_DataT>, B_DataT> final + : public INodeProcessor +{ + private: + ASTNode& m_node; + + PUGS_INLINE DataVariant + _eval(const DataVariant& a, const DataVariant& b) + { + if constexpr ((std::is_arithmetic_v<B_DataT>) or (is_tiny_matrix_v<B_DataT>) or (is_tiny_vector_v<B_DataT>)) { + const auto& embedded_a = std::get<EmbeddedData>(a); + const auto& b_value = std::get<B_DataT>(b); + + std::shared_ptr a_ptr = dynamic_cast<const DataHandler<A_DataT>&>(embedded_a.get()).data_ptr(); + + return EmbeddedData(std::make_shared<DataHandler<ValueT>>(BinOp<BinaryOpT>().eval(a_ptr, b_value))); + } else { + static_assert(std::is_arithmetic_v<B_DataT>, "invalid right hand side type"); + } + } + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + try { + return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy)); + } + catch (const NormalError& error) { + throw ParseError(error.what(), m_node.begin()); + } + } + + BinaryExpressionProcessor(ASTNode& node) : m_node{node} {} +}; + #endif // BINARY_EXPRESSION_PROCESSOR_HPP diff --git a/src/language/node_processor/UnaryExpressionProcessor.hpp b/src/language/node_processor/UnaryExpressionProcessor.hpp index 055e3a028be043c8a30189b7e4cccddd99aeef4a..cdc4fc54111fd3a52854160347b5753e3787bcd5 100644 --- a/src/language/node_processor/UnaryExpressionProcessor.hpp +++ b/src/language/node_processor/UnaryExpressionProcessor.hpp @@ -5,6 +5,9 @@ #include <language/ast/ASTNode.hpp> #include <language/node_processor/INodeProcessor.hpp> +template <typename DataType> +class DataHandler; + template <typename Op> struct UnaryOp; @@ -52,4 +55,30 @@ class UnaryExpressionProcessor final : public INodeProcessor UnaryExpressionProcessor(ASTNode& node) : m_node{node} {} }; +template <typename UnaryOpT, typename ValueT, typename DataT> +class UnaryExpressionProcessor<UnaryOpT, std::shared_ptr<ValueT>, std::shared_ptr<DataT>> final : public INodeProcessor +{ + private: + ASTNode& m_node; + + PUGS_INLINE DataVariant + _eval(const DataVariant& a) + { + const auto& embedded_a = std::get<EmbeddedData>(a); + + std::shared_ptr a_ptr = dynamic_cast<const DataHandler<DataT>&>(embedded_a.get()).data_ptr(); + + return EmbeddedData(std::make_shared<DataHandler<ValueT>>(UnaryOp<UnaryOpT>().eval(a_ptr))); + } + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + return this->_eval(m_node.children[0]->execute(exec_policy)); + } + + UnaryExpressionProcessor(ASTNode& node) : m_node{node} {} +}; + #endif // UNARY_EXPRESSION_PROCESSOR_HPP diff --git a/src/language/utils/BinaryOperatorProcessorBuilder.hpp b/src/language/utils/BinaryOperatorProcessorBuilder.hpp index eb07b35d028f3eaea3f59537753dfd936a185837..053fd83f51e029b394302c1ef319421e60e4e38f 100644 --- a/src/language/utils/BinaryOperatorProcessorBuilder.hpp +++ b/src/language/utils/BinaryOperatorProcessorBuilder.hpp @@ -8,11 +8,6 @@ #include <language/utils/IBinaryOperatorProcessorBuilder.hpp> #include <language/utils/ParseError.hpp> -#include <type_traits> - -template <typename DataType> -class DataHandler; - template <typename OperatorT, typename ValueT, typename A_DataT, typename B_DataT> class BinaryOperatorProcessorBuilder final : public IBinaryOperatorProcessorBuilder { @@ -44,113 +39,4 @@ class BinaryOperatorProcessorBuilder final : public IBinaryOperatorProcessorBuil } }; -template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT> -struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared_ptr<A_DataT>, std::shared_ptr<B_DataT>> - final : public INodeProcessor -{ - private: - ASTNode& m_node; - - PUGS_INLINE DataVariant - _eval(const DataVariant& a, const DataVariant& b) - { - const auto& embedded_a = std::get<EmbeddedData>(a); - const auto& embedded_b = std::get<EmbeddedData>(b); - - std::shared_ptr a_ptr = dynamic_cast<const DataHandler<A_DataT>&>(embedded_a.get()).data_ptr(); - - std::shared_ptr b_ptr = dynamic_cast<const DataHandler<B_DataT>&>(embedded_b.get()).data_ptr(); - - return EmbeddedData(std::make_shared<DataHandler<ValueT>>(BinOp<BinaryOpT>().eval(a_ptr, b_ptr))); - } - - public: - DataVariant - execute(ExecutionPolicy& exec_policy) - { - try { - return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy)); - } - catch (const NormalError& error) { - throw ParseError(error.what(), m_node.begin()); - } - } - - BinaryExpressionProcessor(ASTNode& node) : m_node{node} {} -}; - -template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT> -struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, A_DataT, std::shared_ptr<B_DataT>> final - : public INodeProcessor -{ - private: - ASTNode& m_node; - - PUGS_INLINE DataVariant - _eval(const DataVariant& a, const DataVariant& b) - { - if constexpr ((std::is_arithmetic_v<A_DataT>) or (is_tiny_vector_v<A_DataT>) or (is_tiny_matrix_v<A_DataT>)) { - const auto& a_value = std::get<A_DataT>(a); - const auto& embedded_b = std::get<EmbeddedData>(b); - - std::shared_ptr b_ptr = dynamic_cast<const DataHandler<B_DataT>&>(embedded_b.get()).data_ptr(); - - return EmbeddedData(std::make_shared<DataHandler<ValueT>>(BinOp<BinaryOpT>().eval(a_value, b_ptr))); - } else { - static_assert(std::is_arithmetic_v<A_DataT>, "invalid left hand side type"); - } - } - - public: - DataVariant - execute(ExecutionPolicy& exec_policy) - { - try { - return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy)); - } - catch (const NormalError& error) { - throw ParseError(error.what(), m_node.begin()); - } - } - - BinaryExpressionProcessor(ASTNode& node) : m_node{node} {} -}; - -template <typename BinaryOpT, typename ValueT, typename A_DataT, typename B_DataT> -struct BinaryExpressionProcessor<BinaryOpT, std::shared_ptr<ValueT>, std::shared_ptr<A_DataT>, B_DataT> final - : public INodeProcessor -{ - private: - ASTNode& m_node; - - PUGS_INLINE DataVariant - _eval(const DataVariant& a, const DataVariant& b) - { - if constexpr ((std::is_arithmetic_v<B_DataT>) or (is_tiny_matrix_v<B_DataT>) or (is_tiny_vector_v<B_DataT>)) { - const auto& embedded_a = std::get<EmbeddedData>(a); - const auto& b_value = std::get<B_DataT>(b); - - std::shared_ptr a_ptr = dynamic_cast<const DataHandler<A_DataT>&>(embedded_a.get()).data_ptr(); - - return EmbeddedData(std::make_shared<DataHandler<ValueT>>(BinOp<BinaryOpT>().eval(a_ptr, b_value))); - } else { - static_assert(std::is_arithmetic_v<B_DataT>, "invalid right hand side type"); - } - } - - public: - DataVariant - execute(ExecutionPolicy& exec_policy) - { - try { - return this->_eval(m_node.children[0]->execute(exec_policy), m_node.children[1]->execute(exec_policy)); - } - catch (const NormalError& error) { - throw ParseError(error.what(), m_node.begin()); - } - } - - BinaryExpressionProcessor(ASTNode& node) : m_node{node} {} -}; - #endif // BINARY_OPERATOR_PROCESSOR_BUILDER_HPP diff --git a/src/language/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt index bed3da329d5534e8aa4f48ef48cc0751dfa00f3b..216a6be6a15971fe93ca2f4341f720e8b6e5cde3 100644 --- a/src/language/utils/CMakeLists.txt +++ b/src/language/utils/CMakeLists.txt @@ -24,6 +24,7 @@ add_library(PugsLanguageUtils DataVariant.cpp EmbeddedData.cpp EmbeddedIDiscreteFunctionOperators.cpp + EmbeddedIDiscreteFunctionMathFunctions.cpp FunctionSymbolId.cpp IncDecOperatorRegisterForN.cpp IncDecOperatorRegisterForR.cpp diff --git a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2939e011af950fc414cde730e2c1206bf8f4ae01 --- /dev/null +++ b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp @@ -0,0 +1,307 @@ +#include <language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp> + +#include <language/utils/EmbeddedIDiscreteFunctionUtils.hpp> +#include <mesh/IMesh.hpp> +#include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionUtils.hpp> +#include <scheme/IDiscreteFunction.hpp> +#include <scheme/IDiscreteFunctionDescriptor.hpp> + +#define DISCRETE_FUNCTION_CALL(FUNCTION, ARG) \ + if (ARG->dataType() == ASTNodeDataType::double_t and ARG->descriptor().type() == DiscreteFunctionType::P0) { \ + switch (f->mesh()->dimension()) { \ + case 1: { \ + using DiscreteFunctionType = DiscreteFunctionP0<1, double>; \ + return std::make_shared<const DiscreteFunctionType>(FUNCTION(dynamic_cast<const DiscreteFunctionType&>(*ARG))); \ + } \ + case 2: { \ + using DiscreteFunctionType = DiscreteFunctionP0<2, double>; \ + return std::make_shared<const DiscreteFunctionType>(FUNCTION(dynamic_cast<const DiscreteFunctionType&>(*ARG))); \ + } \ + case 3: { \ + using DiscreteFunctionType = DiscreteFunctionP0<3, double>; \ + return std::make_shared<const DiscreteFunctionType>(FUNCTION(dynamic_cast<const DiscreteFunctionType&>(*ARG))); \ + } \ + default: { \ + throw UnexpectedError("invalid mesh dimension"); \ + } \ + } \ + } else { \ + throw UnexpectedError("invalid operand type " + operand_type_name(ARG)); \ + } + +std::shared_ptr<const IDiscreteFunction> +sqrt(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(sqrt, f); +} + +std::shared_ptr<const IDiscreteFunction> +abs(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(abs, f); +} + +std::shared_ptr<const IDiscreteFunction> +sin(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(sin, f); +} + +std::shared_ptr<const IDiscreteFunction> +cos(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(cos, f); +} + +std::shared_ptr<const IDiscreteFunction> +tan(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(tan, f); +} + +std::shared_ptr<const IDiscreteFunction> +asin(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(asin, f); +} + +std::shared_ptr<const IDiscreteFunction> +acos(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(acos, f); +} + +std::shared_ptr<const IDiscreteFunction> +atan(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(atan, f); +} + +std::shared_ptr<const IDiscreteFunction> +atan2(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + if ((f->dataType() == ASTNodeDataType::double_t and f->descriptor().type() == DiscreteFunctionType::P0) and + (f->dataType() == ASTNodeDataType::double_t and g->descriptor().type() == DiscreteFunctionType::P0)) { + std::shared_ptr mesh = getCommonMesh({f, g}); + + if (mesh.use_count() == 0) { + throw NormalError("operands are defined on different meshes"); + } + + switch (mesh->dimension()) { + case 1: { + using DiscreteFunctionType = DiscreteFunctionP0<1, double>; + return std::make_shared<const DiscreteFunctionType>( + atan2(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); + } + case 2: { + using DiscreteFunctionType = DiscreteFunctionP0<2, double>; + return std::make_shared<const DiscreteFunctionType>( + atan2(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); + } + case 3: { + using DiscreteFunctionType = DiscreteFunctionP0<3, double>; + return std::make_shared<const DiscreteFunctionType>( + atan2(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } else { + std::stringstream os; + os << "incompatible operand types " << operand_type_name(f) << " and " << operand_type_name(g); + throw NormalError(os.str()); + } +} + +std::shared_ptr<const IDiscreteFunction> +atan2(const double a, const std::shared_ptr<const IDiscreteFunction>& f) +{ + if (f->dataType() == ASTNodeDataType::double_t and f->descriptor().type() == DiscreteFunctionType::P0) { + switch (f->mesh()->dimension()) { + case 1: { + using DiscreteFunctionType = DiscreteFunctionP0<1, double>; + return std::make_shared<const DiscreteFunctionType>(atan2(a, dynamic_cast<const DiscreteFunctionType&>(*f))); + } + case 2: { + using DiscreteFunctionType = DiscreteFunctionP0<2, double>; + return std::make_shared<const DiscreteFunctionType>(atan2(a, dynamic_cast<const DiscreteFunctionType&>(*f))); + } + case 3: { + using DiscreteFunctionType = DiscreteFunctionP0<3, double>; + return std::make_shared<const DiscreteFunctionType>(atan2(a, dynamic_cast<const DiscreteFunctionType&>(*f))); + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } else { + throw UnexpectedError("invalid operand type " + operand_type_name(f)); + } +} + +std::shared_ptr<const IDiscreteFunction> +atan2(const std::shared_ptr<const IDiscreteFunction>& f, const double a) +{ + if (f->dataType() == ASTNodeDataType::double_t and f->descriptor().type() == DiscreteFunctionType::P0) { + switch (f->mesh()->dimension()) { + case 1: { + using DiscreteFunctionType = DiscreteFunctionP0<1, double>; + return std::make_shared<const DiscreteFunctionType>(atan2(dynamic_cast<const DiscreteFunctionType&>(*f), a)); + } + case 2: { + using DiscreteFunctionType = DiscreteFunctionP0<2, double>; + return std::make_shared<const DiscreteFunctionType>(atan2(dynamic_cast<const DiscreteFunctionType&>(*f), a)); + } + case 3: { + using DiscreteFunctionType = DiscreteFunctionP0<3, double>; + return std::make_shared<const DiscreteFunctionType>(atan2(dynamic_cast<const DiscreteFunctionType&>(*f), a)); + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } else { + throw UnexpectedError("invalid operand type " + operand_type_name(f)); + } +} + +std::shared_ptr<const IDiscreteFunction> +sinh(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(sinh, f); +} + +std::shared_ptr<const IDiscreteFunction> +cosh(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(cosh, f); +} + +std::shared_ptr<const IDiscreteFunction> +tanh(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(tanh, f); +} + +std::shared_ptr<const IDiscreteFunction> +asinh(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(asinh, f); +} + +std::shared_ptr<const IDiscreteFunction> +acosh(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(acosh, f); +} + +std::shared_ptr<const IDiscreteFunction> +atanh(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(atanh, f); +} + +std::shared_ptr<const IDiscreteFunction> +exp(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(exp, f); +} + +std::shared_ptr<const IDiscreteFunction> +log(const std::shared_ptr<const IDiscreteFunction>& f) +{ + DISCRETE_FUNCTION_CALL(log, f); +} + +std::shared_ptr<const IDiscreteFunction> +pow(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + if ((f->dataType() == ASTNodeDataType::double_t and f->descriptor().type() == DiscreteFunctionType::P0) and + (f->dataType() == ASTNodeDataType::double_t and g->descriptor().type() == DiscreteFunctionType::P0)) { + std::shared_ptr mesh = getCommonMesh({f, g}); + + if (mesh.use_count() == 0) { + throw NormalError("operands are defined on different meshes"); + } + + switch (mesh->dimension()) { + case 1: { + using DiscreteFunctionType = DiscreteFunctionP0<1, double>; + return std::make_shared<const DiscreteFunctionType>( + pow(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); + } + case 2: { + using DiscreteFunctionType = DiscreteFunctionP0<2, double>; + return std::make_shared<const DiscreteFunctionType>( + pow(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); + } + case 3: { + using DiscreteFunctionType = DiscreteFunctionP0<3, double>; + return std::make_shared<const DiscreteFunctionType>( + pow(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } else { + std::stringstream os; + os << "incompatible operand types " << operand_type_name(f) << " and " << operand_type_name(g); + throw NormalError(os.str()); + } +} + +std::shared_ptr<const IDiscreteFunction> +pow(const double a, const std::shared_ptr<const IDiscreteFunction>& f) +{ + if (f->dataType() == ASTNodeDataType::double_t and f->descriptor().type() == DiscreteFunctionType::P0) { + switch (f->mesh()->dimension()) { + case 1: { + using DiscreteFunctionType = DiscreteFunctionP0<1, double>; + return std::make_shared<const DiscreteFunctionType>(pow(a, dynamic_cast<const DiscreteFunctionType&>(*f))); + } + case 2: { + using DiscreteFunctionType = DiscreteFunctionP0<2, double>; + return std::make_shared<const DiscreteFunctionType>(pow(a, dynamic_cast<const DiscreteFunctionType&>(*f))); + } + case 3: { + using DiscreteFunctionType = DiscreteFunctionP0<3, double>; + return std::make_shared<const DiscreteFunctionType>(pow(a, dynamic_cast<const DiscreteFunctionType&>(*f))); + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } else { + throw UnexpectedError("invalid operand type " + operand_type_name(f)); + } +} + +std::shared_ptr<const IDiscreteFunction> +pow(const std::shared_ptr<const IDiscreteFunction>& f, const double a) +{ + if (f->dataType() == ASTNodeDataType::double_t and f->descriptor().type() == DiscreteFunctionType::P0) { + switch (f->mesh()->dimension()) { + case 1: { + using DiscreteFunctionType = DiscreteFunctionP0<1, double>; + return std::make_shared<const DiscreteFunctionType>(pow(dynamic_cast<const DiscreteFunctionType&>(*f), a)); + } + case 2: { + using DiscreteFunctionType = DiscreteFunctionP0<2, double>; + return std::make_shared<const DiscreteFunctionType>(pow(dynamic_cast<const DiscreteFunctionType&>(*f), a)); + } + case 3: { + using DiscreteFunctionType = DiscreteFunctionP0<3, double>; + return std::make_shared<const DiscreteFunctionType>(pow(dynamic_cast<const DiscreteFunctionType&>(*f), a)); + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } else { + throw UnexpectedError("invalid operand type " + operand_type_name(f)); + } +} diff --git a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0030f46759dfe683a09228131140e98ec205fc8b --- /dev/null +++ b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp @@ -0,0 +1,57 @@ +#ifndef EMBEDDED_I_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP +#define EMBEDDED_I_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP + +#include <algebra/TinyMatrix.hpp> +#include <algebra/TinyVector.hpp> + +#include <memory> + +class IDiscreteFunction; + +std::shared_ptr<const IDiscreteFunction> sqrt(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> abs(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> sin(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> cos(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> tan(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> asin(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> acos(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> atan(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> atan2(const std::shared_ptr<const IDiscreteFunction>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> atan2(const double, const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> atan2(const std::shared_ptr<const IDiscreteFunction>&, const double); + +std::shared_ptr<const IDiscreteFunction> sinh(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> cosh(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> tanh(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> asinh(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> acosh(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> atanh(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> exp(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> log(const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> pow(const std::shared_ptr<const IDiscreteFunction>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> pow(const double, const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> pow(const std::shared_ptr<const IDiscreteFunction>&, const double); + +#endif // EMBEDDED_I_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP diff --git a/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp b/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp index af0ac957a430cecc6bcdd8b643064816a2402b94..0e5a789ce31e645b8ccdde6c48009eca4275d76b 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp @@ -1,56 +1,133 @@ #include <language/utils/EmbeddedIDiscreteFunctionOperators.hpp> #include <language/node_processor/BinaryExpressionProcessor.hpp> +#include <language/node_processor/UnaryExpressionProcessor.hpp> +#include <language/utils/EmbeddedIDiscreteFunctionUtils.hpp> #include <scheme/DiscreteFunctionP0.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionUtils.hpp> #include <scheme/IDiscreteFunction.hpp> #include <utils/Exceptions.hpp> -template <typename T> +template <typename LHS_T, typename RHS_T> PUGS_INLINE std::string -name(const T&) +invalid_operands(const LHS_T& f, const RHS_T& g) { - return dataTypeName(ast_node_data_type_from<T>); + std::ostringstream os; + os << "undefined binary operator\n"; + os << "note: incompatible operand types " << operand_type_name(f) << " and " << operand_type_name(g); + return os.str(); } -template <> -PUGS_INLINE std::string -name(const IDiscreteFunction& f) +// unary operators +template <typename UnaryOperatorT, typename DiscreteFunctionT> +std::shared_ptr<const IDiscreteFunction> +applyUnaryOperation(const DiscreteFunctionT& f) { - return "Vh(" + name(f.descriptor().type()) + ":" + dataTypeName(f.dataType()) + ")"; + return std::make_shared<decltype(UnaryOp<UnaryOperatorT>{}.eval(f))>(UnaryOp<UnaryOperatorT>{}.eval(f)); } -template <> -PUGS_INLINE std::string -name(const std::shared_ptr<const IDiscreteFunction>& f) +template <typename UnaryOperatorT, size_t Dimension> +std::shared_ptr<const IDiscreteFunction> +applyUnaryOperation(const std::shared_ptr<const IDiscreteFunction>& f) { - return "Vh(" + name(f->descriptor().type()) + ":" + dataTypeName(f->dataType()) + ")"; + switch (f->descriptor().type()) { + case DiscreteFunctionType::P0: { + switch (f->dataType()) { + case ASTNodeDataType::double_t: { + auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*f); + return applyUnaryOperation<UnaryOperatorT>(fh); + } + case ASTNodeDataType::vector_t: { + switch (f->dataType().dimension()) { + case 1: { + auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<1>>&>(*f); + return applyUnaryOperation<UnaryOperatorT>(fh); + } + case 2: { + auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<2>>&>(*f); + return applyUnaryOperation<UnaryOperatorT>(fh); + } + case 3: { + auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<3>>&>(*f); + return applyUnaryOperation<UnaryOperatorT>(fh); + } + default: { + throw UnexpectedError("invalid operand type " + operand_type_name(f)); + } + } + } + case ASTNodeDataType::matrix_t: { + Assert(f->dataType().nbRows() == f->dataType().nbColumns()); + switch (f->dataType().nbRows()) { + case 1: { + auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); + return applyUnaryOperation<UnaryOperatorT>(fh); + } + case 2: { + auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>&>(*f); + return applyUnaryOperation<UnaryOperatorT>(fh); + } + case 3: { + auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>&>(*f); + return applyUnaryOperation<UnaryOperatorT>(fh); + } + default: { + throw UnexpectedError("invalid operand type " + operand_type_name(f)); + } + } + } + default: { + throw UnexpectedError("invalid operand type " + operand_type_name(f)); + } + } + break; + } + case DiscreteFunctionType::P0Vector: { + switch (f->dataType()) { + case ASTNodeDataType::double_t: { + auto fh = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*f); + return applyUnaryOperation<UnaryOperatorT>(fh); + } + default: { + throw UnexpectedError("invalid operand type " + operand_type_name(f)); + } + } + break; + } + default: { + throw UnexpectedError("invalid operand type " + operand_type_name(f)); + } + } } -PUGS_INLINE -bool -isSameDiscretization(const IDiscreteFunction& f, const IDiscreteFunction& g) +template <typename UnaryOperatorT> +std::shared_ptr<const IDiscreteFunction> +applyUnaryOperation(const std::shared_ptr<const IDiscreteFunction>& f) { - return (f.dataType() == g.dataType()) and (f.descriptor().type() == g.descriptor().type()); + switch (f->mesh()->dimension()) { + case 1: { + return applyUnaryOperation<UnaryOperatorT, 1>(f); + } + case 2: { + return applyUnaryOperation<UnaryOperatorT, 2>(f); + } + case 3: { + return applyUnaryOperation<UnaryOperatorT, 3>(f); + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } } -PUGS_INLINE -bool -isSameDiscretization(const std::shared_ptr<const IDiscreteFunction>& f, - const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const IDiscreteFunction> +operator-(const std::shared_ptr<const IDiscreteFunction>& f) { - return (f->dataType() == g->dataType()) and (f->descriptor().type() == g->descriptor().type()); + return applyUnaryOperation<language::unary_minus>(f); } -template <typename LHS_T, typename RHS_T> -PUGS_INLINE std::string -invalid_operands(const LHS_T& f, const RHS_T& g) -{ - std::ostringstream os; - os << "undefined binary operator\n"; - os << "note: incompatible operand types " << name(f) << " and " << name(g); - return os.str(); -} +// binary operators template <typename BinOperatorT, typename DiscreteFunctionT> std::shared_ptr<const IDiscreteFunction> @@ -89,7 +166,7 @@ innerCompositionLaw(const std::shared_ptr<const IDiscreteFunction>& f, auto gh = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*g); if (fh.size() != gh.size()) { - throw NormalError(name(f) + " spaces have different sizes"); + throw NormalError(operand_type_name(f) + " spaces have different sizes"); } return innerCompositionLaw<BinOperatorT>(fh, gh); @@ -149,12 +226,12 @@ innerCompositionLaw(const std::shared_ptr<const IDiscreteFunction>& f, return innerCompositionLaw<BinOperatorT>(fh, gh); } default: { - throw UnexpectedError("invalid data type Vh(" + dataTypeName(g->dataType()) + ")"); + throw UnexpectedError("invalid data type " + operand_type_name(f)); } } } default: { - throw UnexpectedError("invalid data type Vh(" + dataTypeName(g->dataType()) + ")"); + throw UnexpectedError("invalid data type " + operand_type_name(f)); } } } @@ -164,14 +241,16 @@ std::shared_ptr<const IDiscreteFunction> innerCompositionLaw(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) { - if (f->mesh() != g->mesh()) { - throw NormalError("discrete functions defined on different meshes"); + std::shared_ptr mesh = getCommonMesh({f, g}); + if (mesh.use_count() == 0) { + throw NormalError("operands are defined on different meshes"); } + if (not isSameDiscretization(f, g)) { throw NormalError(invalid_operands(f, g)); } - switch (f->mesh()->dimension()) { + switch (mesh->dimension()) { case 1: { return innerCompositionLaw<BinOperatorT, 1>(f, g); } @@ -221,7 +300,6 @@ applyBinaryOperation(const DiscreteFunctionT& fh, const std::shared_ptr<const ID std::is_same_v<DiscreteFunctionT, DiscreteFunctionP0<Dimension, double>>) { if (g->descriptor().type() == DiscreteFunctionType::P0Vector) { auto gh = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*g); - return applyBinaryOperation<BinOperatorT>(fh, gh); } else { throw NormalError(invalid_operands(fh, g)); @@ -264,7 +342,7 @@ applyBinaryOperation(const DiscreteFunctionT& fh, const std::shared_ptr<const ID } } default: { - throw UnexpectedError("invalid rhs data type Vh(" + dataTypeName(g->dataType()) + ")"); + throw UnexpectedError("invalid rhs data type " + operand_type_name(g)); } } } else { @@ -291,7 +369,7 @@ applyBinaryOperation(const DiscreteFunctionT& fh, const std::shared_ptr<const ID return applyBinaryOperation<BinOperatorT>(fh, gh); } default: { - throw UnexpectedError("invalid rhs data type Vh(" + dataTypeName(g->dataType()) + ")"); + throw UnexpectedError("invalid rhs data type " + operand_type_name(g)); } } } else { @@ -299,7 +377,7 @@ applyBinaryOperation(const DiscreteFunctionT& fh, const std::shared_ptr<const ID } } default: { - throw UnexpectedError("invalid rhs data type Vh(" + dataTypeName(g->dataType()) + ")"); + throw UnexpectedError("invalid rhs data type " + operand_type_name(g)); } } } @@ -337,7 +415,7 @@ applyBinaryOperation(const std::shared_ptr<const IDiscreteFunction>& f, return applyBinaryOperation<BinOperatorT, Dimension>(fh, g); } default: { - throw UnexpectedError("invalid lhs data type Vh(" + dataTypeName(f->dataType()) + ")"); + throw UnexpectedError("invalid lhs data type " + operand_type_name(f)); } } } @@ -352,13 +430,14 @@ std::shared_ptr<const IDiscreteFunction> applyBinaryOperation(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) { - if (f->mesh() != g->mesh()) { - throw NormalError("functions defined on different meshes"); + std::shared_ptr mesh = getCommonMesh({f, g}); + if (mesh.use_count() == 0) { + throw NormalError("operands are defined on different meshes"); } Assert(not isSameDiscretization(f, g), "should call inner composition instead"); - switch (f->mesh()->dimension()) { + switch (mesh->dimension()) { case 1: { return applyBinaryOperation<BinOperatorT, 1>(f, g); } @@ -377,13 +456,21 @@ applyBinaryOperation(const std::shared_ptr<const IDiscreteFunction>& f, std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) { - return innerCompositionLaw<language::plus_op>(f, g); + if (isSameDiscretization(f, g)) { + return innerCompositionLaw<language::plus_op>(f, g); + } else { + throw NormalError(invalid_operands(f, g)); + } } std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) { - return innerCompositionLaw<language::minus_op>(f, g); + if (isSameDiscretization(f, g)) { + return innerCompositionLaw<language::minus_op>(f, g); + } else { + throw NormalError(invalid_operands(f, g)); + } } std::shared_ptr<const IDiscreteFunction> @@ -413,6 +500,42 @@ applyBinaryOperationWithLeftConstant(const DataType& a, const DiscreteFunctionT& using lhs_data_type = std::decay_t<DataType>; using rhs_data_type = std::decay_t<typename DiscreteFunctionT::data_type>; + if constexpr (std::is_same_v<language::multiply_op, BinOperatorT>) { + if constexpr (std::is_same_v<lhs_data_type, double>) { + return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(a, f))>(BinOp<BinOperatorT>{}.eval(a, f)); + } else if constexpr (is_tiny_matrix_v<lhs_data_type> and + (is_tiny_matrix_v<rhs_data_type> or is_tiny_vector_v<rhs_data_type>)) { + return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(a, f))>(BinOp<BinOperatorT>{}.eval(a, f)); + } else { + throw NormalError(invalid_operands(a, f)); + } + } else if constexpr (std::is_same_v<language::plus_op, BinOperatorT> or + std::is_same_v<language::minus_op, BinOperatorT>) { + if constexpr (std::is_same_v<lhs_data_type, double> and std::is_arithmetic_v<rhs_data_type>) { + return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(a, f))>(BinOp<BinOperatorT>{}.eval(a, f)); + } else if constexpr (std::is_same_v<lhs_data_type, rhs_data_type>) { + return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(a, f))>(BinOp<BinOperatorT>{}.eval(a, f)); + } else { + throw NormalError(invalid_operands(a, f)); + } + } else if constexpr (std::is_same_v<language::divide_op, BinOperatorT>) { + if constexpr (std::is_same_v<lhs_data_type, double> and std::is_arithmetic_v<rhs_data_type>) { + return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(a, f))>(BinOp<BinOperatorT>{}.eval(a, f)); + } else { + throw NormalError(invalid_operands(a, f)); + } + } else { + throw NormalError(invalid_operands(a, f)); + } +} + +template <typename BinOperatorT, typename DataType, typename DiscreteFunctionT> +std::shared_ptr<const IDiscreteFunction> +applyBinaryOperationToVectorWithLeftConstant(const DataType& a, const DiscreteFunctionT& f) +{ + using lhs_data_type = std::decay_t<DataType>; + using rhs_data_type = std::decay_t<typename DiscreteFunctionT::data_type>; + if constexpr (std::is_same_v<language::multiply_op, BinOperatorT>) { if constexpr (std::is_same_v<lhs_data_type, double>) { return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(a, f))>(BinOp<BinOperatorT>{}.eval(a, f)); @@ -441,7 +564,7 @@ applyBinaryOperationWithLeftConstant(const DataType& a, const std::shared_ptr<co return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); } else if (f->descriptor().type() == DiscreteFunctionType::P0Vector) { auto fh = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); + return applyBinaryOperationToVectorWithLeftConstant<BinOperatorT>(a, fh); } else { throw NormalError(invalid_operands(a, f)); } @@ -474,7 +597,7 @@ applyBinaryOperationWithLeftConstant(const DataType& a, const std::shared_ptr<co } } default: { - throw UnexpectedError("invalid lhs data type Vh(" + dataTypeName(f->dataType()) + ")"); + throw UnexpectedError("invalid lhs data type " + operand_type_name(f)); } } } else { @@ -492,7 +615,7 @@ applyBinaryOperationWithLeftConstant(const DataType& a, const std::shared_ptr<co return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); } default: { - throw UnexpectedError("invalid lhs data type Vh(" + dataTypeName(f->dataType()) + ")"); + throw UnexpectedError("invalid lhs data type " + operand_type_name(f)); } } } @@ -526,7 +649,7 @@ applyBinaryOperationWithLeftConstant(const DataType& a, const std::shared_ptr<co } } default: { - throw UnexpectedError("invalid lhs data type Vh(" + dataTypeName(f->dataType()) + ")"); + throw UnexpectedError("invalid lhs data type " + operand_type_name(f)); } } } else { @@ -544,7 +667,7 @@ applyBinaryOperationWithLeftConstant(const DataType& a, const std::shared_ptr<co return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); } default: { - throw UnexpectedError("invalid lhs data type Vh(" + dataTypeName(f->dataType()) + ")"); + throw UnexpectedError("invalid lhs data type " + operand_type_name(f)); } } } @@ -579,7 +702,7 @@ template <typename BinOperatorT, typename DataType, typename DiscreteFunctionT> std::shared_ptr<const IDiscreteFunction> applyBinaryOperationWithRightConstant(const DiscreteFunctionT& f, const DataType& a) { - Assert(f.descriptor().type() != DiscreteFunctionType::P0); + Assert(f.descriptor().type() == DiscreteFunctionType::P0); using lhs_data_type = std::decay_t<typename DiscreteFunctionT::data_type>; using rhs_data_type = std::decay_t<DataType>; @@ -588,7 +711,16 @@ applyBinaryOperationWithRightConstant(const DiscreteFunctionT& f, const DataType if constexpr (is_tiny_matrix_v<lhs_data_type> and is_tiny_matrix_v<rhs_data_type>) { return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(f, a))>(BinOp<BinOperatorT>{}.eval(f, a)); } else if constexpr (std::is_same_v<lhs_data_type, double> and - (is_tiny_matrix_v<rhs_data_type> or is_tiny_vector_v<rhs_data_type>)) { + (is_tiny_matrix_v<rhs_data_type> or is_tiny_vector_v<rhs_data_type> or + std::is_arithmetic_v<rhs_data_type>)) { + return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(f, a))>(BinOp<BinOperatorT>{}.eval(f, a)); + } else { + throw NormalError(invalid_operands(f, a)); + } + } else if constexpr (std::is_same_v<language::plus_op, BinOperatorT> or + std::is_same_v<language::minus_op, BinOperatorT>) { + if constexpr ((std::is_same_v<lhs_data_type, rhs_data_type>) or + (std::is_arithmetic_v<lhs_data_type> and std::is_arithmetic_v<rhs_data_type>)) { return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(f, a))>(BinOp<BinOperatorT>{}.eval(f, a)); } else { throw NormalError(invalid_operands(f, a)); @@ -643,7 +775,7 @@ applyBinaryOperationWithRightConstant(const std::shared_ptr<const IDiscreteFunct } } default: { - throw UnexpectedError("invalid lhs data type Vh(" + dataTypeName(f->dataType()) + ")"); + throw UnexpectedError("invalid lhs data type " + operand_type_name(f)); } } } else { @@ -661,7 +793,7 @@ applyBinaryOperationWithRightConstant(const std::shared_ptr<const IDiscreteFunct return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); } default: { - throw UnexpectedError("invalid lhs data type Vh(" + dataTypeName(f->dataType()) + ")"); + throw UnexpectedError("invalid lhs data type " + operand_type_name(f)); } } } @@ -692,12 +824,186 @@ applyBinaryOperationWithRightConstant(const std::shared_ptr<const IDiscreteFunct } } +std::shared_ptr<const IDiscreteFunction> +operator+(const double& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const std::shared_ptr<const IDiscreteFunction>& f, const double& g) +{ + return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const TinyVector<1>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const TinyVector<2>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const TinyVector<3>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const TinyMatrix<1>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const TinyMatrix<2>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const TinyMatrix<3>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<1>& g) +{ + return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<2>& g) +{ + return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<3>& g) +{ + return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<1>& g) +{ + return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<2>& g) +{ + return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<3>& g) +{ + return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const double& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const std::shared_ptr<const IDiscreteFunction>& f, const double& g) +{ + return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const TinyVector<1>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const TinyVector<2>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const TinyVector<3>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const TinyMatrix<1>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const TinyMatrix<2>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const TinyMatrix<3>& f, const std::shared_ptr<const IDiscreteFunction>& g) +{ + return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<1>& g) +{ + return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<2>& g) +{ + return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<3>& g) +{ + return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<1>& g) +{ + return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<2>& g) +{ + return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); +} + +std::shared_ptr<const IDiscreteFunction> +operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<3>& g) +{ + return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); +} + std::shared_ptr<const IDiscreteFunction> operator*(const double& a, const std::shared_ptr<const IDiscreteFunction>& f) { return applyBinaryOperationWithLeftConstant<language::multiply_op>(a, f); } +std::shared_ptr<const IDiscreteFunction> +operator*(const std::shared_ptr<const IDiscreteFunction>& f, const double& a) +{ + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, a); +} + std::shared_ptr<const IDiscreteFunction> operator*(const TinyMatrix<1>& A, const std::shared_ptr<const IDiscreteFunction>& B) { @@ -751,3 +1057,9 @@ operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyMatrix<3> { return applyBinaryOperationWithRightConstant<language::multiply_op>(a, A); } + +std::shared_ptr<const IDiscreteFunction> +operator/(const double& a, const std::shared_ptr<const IDiscreteFunction>& f) +{ + return applyBinaryOperationWithLeftConstant<language::divide_op>(a, f); +} diff --git a/src/language/utils/EmbeddedIDiscreteFunctionOperators.hpp b/src/language/utils/EmbeddedIDiscreteFunctionOperators.hpp index 7969828000c4440ea9aa9d36014ee18d55d643c1..f797a95d03e19a796d9af965d81bbd3970c6cddd 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionOperators.hpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionOperators.hpp @@ -8,20 +8,105 @@ class IDiscreteFunction; +// unary minus +std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&); + +// sum std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const IDiscreteFunction> operator+(const double&, const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, const double&); + +std::shared_ptr<const IDiscreteFunction> operator+(const TinyVector<1>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const TinyVector<2>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const TinyVector<3>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const TinyMatrix<1>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const TinyMatrix<2>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const TinyMatrix<3>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, + const TinyVector<1>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, + const TinyVector<2>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, + const TinyVector<3>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, + const TinyMatrix<1>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, + const TinyMatrix<2>&); + +std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, + const TinyMatrix<3>&); + +// difference std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, const std::shared_ptr<const IDiscreteFunction>&); -std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, +std::shared_ptr<const IDiscreteFunction> operator-(const double&, const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, const double&); + +std::shared_ptr<const IDiscreteFunction> operator-(const TinyVector<1>&, const std::shared_ptr<const IDiscreteFunction>&); -std::shared_ptr<const IDiscreteFunction> operator/(const std::shared_ptr<const IDiscreteFunction>&, +std::shared_ptr<const IDiscreteFunction> operator-(const TinyVector<2>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const TinyVector<3>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const TinyMatrix<1>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const TinyMatrix<2>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const TinyMatrix<3>&, + const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, + const TinyVector<1>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, + const TinyVector<2>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, + const TinyVector<3>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, + const TinyMatrix<1>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, + const TinyMatrix<2>&); + +std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, + const TinyMatrix<3>&); + +// product +std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, const std::shared_ptr<const IDiscreteFunction>&); std::shared_ptr<const IDiscreteFunction> operator*(const double&, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, const double&); + std::shared_ptr<const IDiscreteFunction> operator*(const TinyMatrix<1>&, const std::shared_ptr<const IDiscreteFunction>&); @@ -49,4 +134,10 @@ std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const I std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, const TinyMatrix<3>&); +// ratio +std::shared_ptr<const IDiscreteFunction> operator/(const double&, const std::shared_ptr<const IDiscreteFunction>&); + +std::shared_ptr<const IDiscreteFunction> operator/(const std::shared_ptr<const IDiscreteFunction>&, + const std::shared_ptr<const IDiscreteFunction>&); + #endif // EMBEDDED_I_DISCRETE_FUNCTION_OPERATORS_HPP diff --git a/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp b/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9321c3273d7955e77934f9f4233ae3603cf14990 --- /dev/null +++ b/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp @@ -0,0 +1,58 @@ +#ifndef EMBEDDED_I_DISCRETE_FUNCTION_UTILS_HPP +#define EMBEDDED_I_DISCRETE_FUNCTION_UTILS_HPP + +#include <scheme/IDiscreteFunction.hpp> +#include <scheme/IDiscreteFunctionDescriptor.hpp> +#include <utils/Exceptions.hpp> + +#include <sstream> +#include <string> + +template <typename T> +PUGS_INLINE std::string +operand_type_name(const T& t) +{ + if constexpr (is_shared_ptr_v<T>) { + Assert(t.use_count() > 0); + return operand_type_name(*t); + } else if constexpr (std::is_base_of_v<IDiscreteFunction, std::decay_t<T>>) { + return "Vh(" + name(t.descriptor().type()) + ':' + dataTypeName(t.dataType()) + ')'; + } else { + return dataTypeName(ast_node_data_type_from<T>); + } +} + +PUGS_INLINE +bool +isSameDiscretization(const IDiscreteFunction& f, const IDiscreteFunction& g) +{ + if ((f.dataType() == g.dataType()) and (f.descriptor().type() == g.descriptor().type())) { + switch (f.dataType()) { + case ASTNodeDataType::double_t: { + return true; + } + case ASTNodeDataType::vector_t: { + return f.dataType().dimension() == g.dataType().dimension(); + } + case ASTNodeDataType::matrix_t: { + return (f.dataType().nbRows() == g.dataType().nbRows()) and + (f.dataType().nbColumns() == g.dataType().nbColumns()); + } + default: { + throw UnexpectedError("invalid data type " + operand_type_name(f)); + } + } + } else { + return false; + } +} + +PUGS_INLINE +bool +isSameDiscretization(const std::shared_ptr<const IDiscreteFunction>& f, + const std::shared_ptr<const IDiscreteFunction>& g) +{ + return isSameDiscretization(*f, *g); +} + +#endif // EMBEDDED_I_DISCRETE_FUNCTION_UTILS_HPP diff --git a/src/language/utils/IUnaryOperatorProcessorBuilder.hpp b/src/language/utils/IUnaryOperatorProcessorBuilder.hpp index 19b36e2feb42b9efc558ff5e554532c0f3d32824..6868036e88ce63addcce46f16b1639af96fd21b0 100644 --- a/src/language/utils/IUnaryOperatorProcessorBuilder.hpp +++ b/src/language/utils/IUnaryOperatorProcessorBuilder.hpp @@ -13,6 +13,7 @@ class IUnaryOperatorProcessorBuilder public: [[nodiscard]] virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0; + [[nodiscard]] virtual ASTNodeDataType getOperandDataType() const = 0; [[nodiscard]] virtual ASTNodeDataType getReturnValueType() const = 0; virtual ~IUnaryOperatorProcessorBuilder() = default; diff --git a/src/language/utils/InterpolateItemArray.hpp b/src/language/utils/InterpolateItemArray.hpp index fcef1db90a2e17b07e54fe55966a96973d443b9e..c507c527ca9f1c59070410c09f802f524a3de083 100644 --- a/src/language/utils/InterpolateItemArray.hpp +++ b/src/language/utils/InterpolateItemArray.hpp @@ -16,7 +16,7 @@ class InterpolateItemArray<OutputType(InputType)> : public PugsFunctionAdapter<O public: template <ItemType item_type> - static inline ItemArray<OutputType, item_type> + PUGS_INLINE static ItemArray<OutputType, item_type> interpolate(const std::vector<FunctionSymbolId>& function_symbol_id_list, const ItemValue<const InputType, item_type>& position) { @@ -35,9 +35,9 @@ class InterpolateItemArray<OutputType(InputType)> : public PugsFunctionAdapter<O } template <ItemType item_type> - static inline Table<OutputType> + PUGS_INLINE static Table<OutputType> interpolate(const std::vector<FunctionSymbolId>& function_symbol_id_list, - const ItemArray<const InputType, item_type>& position, + const ItemValue<const InputType, item_type>& position, const Array<const ItemIdT<item_type>>& list_of_items) { Table<OutputType> table{list_of_items.size(), function_symbol_id_list.size()}; @@ -53,6 +53,15 @@ class InterpolateItemArray<OutputType(InputType)> : public PugsFunctionAdapter<O return table; } + + template <ItemType item_type> + PUGS_INLINE static Table<OutputType> + interpolate(const std::vector<FunctionSymbolId>& function_symbol_id_list, + const ItemValue<const InputType, item_type>& position, + const Array<ItemIdT<item_type>>& list_of_items) + { + return interpolate(function_symbol_id_list, position, Array<const ItemIdT<item_type>>{list_of_items}); + } }; #endif // INTERPOLATE_ITEM_ARRAY_HPP diff --git a/src/language/utils/InterpolateItemValue.hpp b/src/language/utils/InterpolateItemValue.hpp index 16a87b4952c7cb0c2907833705e8142d9c0a7178..de12b563a19ded640f0b4bbae3184f383d90a2f3 100644 --- a/src/language/utils/InterpolateItemValue.hpp +++ b/src/language/utils/InterpolateItemValue.hpp @@ -15,7 +15,7 @@ class InterpolateItemValue<OutputType(InputType)> : public PugsFunctionAdapter<O public: template <ItemType item_type> - static inline ItemValue<OutputType, item_type> + PUGS_INLINE static ItemValue<OutputType, item_type> interpolate(const FunctionSymbolId& function_symbol_id, const ItemValue<const InputType, item_type>& position) { auto& expression = Adapter::getFunctionExpression(function_symbol_id); @@ -46,7 +46,7 @@ class InterpolateItemValue<OutputType(InputType)> : public PugsFunctionAdapter<O } template <ItemType item_type> - static inline Array<OutputType> + PUGS_INLINE static Array<OutputType> interpolate(const FunctionSymbolId& function_symbol_id, const ItemValue<const InputType, item_type>& position, const Array<const ItemIdT<item_type>>& list_of_items) @@ -77,6 +77,15 @@ class InterpolateItemValue<OutputType(InputType)> : public PugsFunctionAdapter<O return value; } + + template <ItemType item_type> + PUGS_INLINE static Array<OutputType> + interpolate(const FunctionSymbolId& function_symbol_id, + const ItemValue<const InputType, item_type>& position, + const Array<ItemIdT<item_type>>& list_of_items) + { + return interpolate(function_symbol_id, position, Array<const ItemIdT<item_type>>{list_of_items}); + } }; #endif // INTERPOLATE_ITEM_VALUE_HPP diff --git a/src/language/utils/OperatorRepository.hpp b/src/language/utils/OperatorRepository.hpp index cf4b322e7f9da12311a0e1b1dcd47ee0c25e7936..4ce6ee83c7652a7e3cd93f5658b716a10b4e4b15 100644 --- a/src/language/utils/OperatorRepository.hpp +++ b/src/language/utils/OperatorRepository.hpp @@ -68,10 +68,11 @@ class OperatorRepository const std::string binary_operator_type_name = binaryOperatorMangler<BinaryOperatorTypeT>(processor_builder->getDataTypeOfA(), processor_builder->getDataTypeOfB()); - if (not m_binary_operator_builder_list - .try_emplace(binary_operator_type_name, - Descriptor{processor_builder->getReturnValueType(), processor_builder}) - .second) { + if (auto [i_descriptor, success] = + m_binary_operator_builder_list.try_emplace(binary_operator_type_name, + Descriptor{processor_builder->getReturnValueType(), + processor_builder}); + not success) { // LCOV_EXCL_START throw UnexpectedError(binary_operator_type_name + " has already an entry"); // LCOV_EXCL_STOP @@ -85,10 +86,11 @@ class OperatorRepository const std::shared_ptr<const IAffectationProcessorBuilder>& processor_builder) { const std::string affectation_type_name = affectationMangler<OperatorTypeT>(lhs_type, rhs_type); - if (not m_affectation_builder_list - .try_emplace(affectation_type_name, - Descriptor{ASTNodeDataType::build<ASTNodeDataType::void_t>(), processor_builder}) - .second) { + if (auto [i_descriptor, success] = + m_affectation_builder_list.try_emplace(affectation_type_name, + Descriptor{ASTNodeDataType::build<ASTNodeDataType::void_t>(), + processor_builder}); + not success) { // LCOV_EXCL_START throw UnexpectedError(affectation_type_name + " has already an entry"); // LCOV_EXCL_STOP @@ -114,10 +116,10 @@ class OperatorRepository template <typename OperatorTypeT> void - addUnaryOperator(const ASTNodeDataType& operand_type, - const std::shared_ptr<const IUnaryOperatorProcessorBuilder>& processor_builder) + addUnaryOperator(const std::shared_ptr<const IUnaryOperatorProcessorBuilder>& processor_builder) { - const std::string unary_operator_type_name = unaryOperatorMangler<OperatorTypeT>(operand_type); + const std::string unary_operator_type_name = + unaryOperatorMangler<OperatorTypeT>(processor_builder->getOperandDataType()); if (auto [i_descriptor, success] = m_unary_operator_builder_list.try_emplace(unary_operator_type_name, Descriptor{processor_builder->getReturnValueType(), diff --git a/src/language/utils/UnaryOperatorProcessorBuilder.hpp b/src/language/utils/UnaryOperatorProcessorBuilder.hpp index d99d2e17536de2b31a3ac2c48f39800a2461f17d..8dd4b283cf3c628db8cb98aba6b36147990c279d 100644 --- a/src/language/utils/UnaryOperatorProcessorBuilder.hpp +++ b/src/language/utils/UnaryOperatorProcessorBuilder.hpp @@ -15,6 +15,12 @@ class UnaryOperatorProcessorBuilder final : public IUnaryOperatorProcessorBuilde public: UnaryOperatorProcessorBuilder() = default; + ASTNodeDataType + getOperandDataType() const + { + return ast_node_data_type_from<DataT>; + } + ASTNodeDataType getReturnValueType() const { diff --git a/src/language/utils/UnaryOperatorRegisterForB.cpp b/src/language/utils/UnaryOperatorRegisterForB.cpp index 33173e82b896e8d013f125a3b47ce42682ac132d..9eabfbe255691c7cbe2601cfd86a7ef9d449e87d 100644 --- a/src/language/utils/UnaryOperatorRegisterForB.cpp +++ b/src/language/utils/UnaryOperatorRegisterForB.cpp @@ -8,10 +8,8 @@ UnaryOperatorRegisterForB::_register_unary_minus() { OperatorRepository& repository = OperatorRepository::instance(); - auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); - - repository.addUnaryOperator< - language::unary_minus>(B, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, bool>>()); + repository.addUnaryOperator<language::unary_minus>( + std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, bool>>()); } void @@ -19,10 +17,8 @@ UnaryOperatorRegisterForB::_register_unary_not() { OperatorRepository& repository = OperatorRepository::instance(); - auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); - - repository.addUnaryOperator< - language::unary_not>(B, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_not, bool, bool>>()); + repository.addUnaryOperator<language::unary_not>( + std::make_shared<UnaryOperatorProcessorBuilder<language::unary_not, bool, bool>>()); } UnaryOperatorRegisterForB::UnaryOperatorRegisterForB() diff --git a/src/language/utils/UnaryOperatorRegisterForN.cpp b/src/language/utils/UnaryOperatorRegisterForN.cpp index baed0e43eef169229cfbff58fb0592f894b83163..26af42be06cbf05ac070bc563af02a821dd526fa 100644 --- a/src/language/utils/UnaryOperatorRegisterForN.cpp +++ b/src/language/utils/UnaryOperatorRegisterForN.cpp @@ -8,11 +8,8 @@ UnaryOperatorRegisterForN::_register_unary_minus() { OperatorRepository& repository = OperatorRepository::instance(); - auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); - - repository.addUnaryOperator< - language::unary_minus>(N, - std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, uint64_t>>()); + repository.addUnaryOperator<language::unary_minus>( + std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, uint64_t>>()); } UnaryOperatorRegisterForN::UnaryOperatorRegisterForN() diff --git a/src/language/utils/UnaryOperatorRegisterForR.cpp b/src/language/utils/UnaryOperatorRegisterForR.cpp index c0c60a31f5f6c222232999c3b392a18f30a767c1..cc1f637fa839d54cf8a8b612f7abe9147f79b61c 100644 --- a/src/language/utils/UnaryOperatorRegisterForR.cpp +++ b/src/language/utils/UnaryOperatorRegisterForR.cpp @@ -8,10 +8,8 @@ UnaryOperatorRegisterForR::_register_unary_minus() { OperatorRepository& repository = OperatorRepository::instance(); - auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>(); - - repository.addUnaryOperator< - language::unary_minus>(R, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, double, double>>()); + repository.addUnaryOperator<language::unary_minus>( + std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, double, double>>()); } UnaryOperatorRegisterForR::UnaryOperatorRegisterForR() diff --git a/src/language/utils/UnaryOperatorRegisterForRn.cpp b/src/language/utils/UnaryOperatorRegisterForRn.cpp index 85cc03fa476a34a6bec65f2c7f88f1d76fbad809..a35b92d8a2e53d5850c18aa4e4891a1d4c27f822 100644 --- a/src/language/utils/UnaryOperatorRegisterForRn.cpp +++ b/src/language/utils/UnaryOperatorRegisterForRn.cpp @@ -9,12 +9,9 @@ UnaryOperatorRegisterForRn<Dimension>::_register_unary_minus() { OperatorRepository& repository = OperatorRepository::instance(); - auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension); - - repository - .addUnaryOperator<language::unary_minus>(Rn, - std::make_shared<UnaryOperatorProcessorBuilder< - language::unary_minus, TinyVector<Dimension>, TinyVector<Dimension>>>()); + repository.addUnaryOperator<language::unary_minus>( + std::make_shared< + UnaryOperatorProcessorBuilder<language::unary_minus, TinyVector<Dimension>, TinyVector<Dimension>>>()); } template <size_t Dimension> diff --git a/src/language/utils/UnaryOperatorRegisterForRnxn.cpp b/src/language/utils/UnaryOperatorRegisterForRnxn.cpp index 798a60086b30d008901f0d9b5fa2502e745d6fe9..01a53c096b8bc13481deb774fefa1d34b343338a 100644 --- a/src/language/utils/UnaryOperatorRegisterForRnxn.cpp +++ b/src/language/utils/UnaryOperatorRegisterForRnxn.cpp @@ -9,12 +9,9 @@ UnaryOperatorRegisterForRnxn<Dimension>::_register_unary_minus() { OperatorRepository& repository = OperatorRepository::instance(); - auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); - - repository - .addUnaryOperator<language::unary_minus>(Rnxn, - std::make_shared<UnaryOperatorProcessorBuilder< - language::unary_minus, TinyMatrix<Dimension>, TinyMatrix<Dimension>>>()); + repository.addUnaryOperator<language::unary_minus>( + std::make_shared< + UnaryOperatorProcessorBuilder<language::unary_minus, TinyMatrix<Dimension>, TinyMatrix<Dimension>>>()); } template <size_t Dimension> diff --git a/src/language/utils/UnaryOperatorRegisterForZ.cpp b/src/language/utils/UnaryOperatorRegisterForZ.cpp index 89e0b4972a0a1e2a2556d2210ab4658b35f7b976..5326157d43d621b30a238a758fe4a1feb0308204 100644 --- a/src/language/utils/UnaryOperatorRegisterForZ.cpp +++ b/src/language/utils/UnaryOperatorRegisterForZ.cpp @@ -8,11 +8,8 @@ UnaryOperatorRegisterForZ::_register_unary_minus() { OperatorRepository& repository = OperatorRepository::instance(); - auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); - - repository.addUnaryOperator< - language::unary_minus>(Z, - std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, int64_t>>()); + repository.addUnaryOperator<language::unary_minus>( + std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, int64_t>>()); } UnaryOperatorRegisterForZ::UnaryOperatorRegisterForZ() diff --git a/src/mesh/ItemArray.hpp b/src/mesh/ItemArray.hpp index 78e5f8dd64c430ec8149c3e608d444897987f108..1a2b004c9533921ab6531b6fa73c9a955badff57 100644 --- a/src/mesh/ItemArray.hpp +++ b/src/mesh/ItemArray.hpp @@ -47,6 +47,19 @@ class ItemArray return image; } + template <typename ConnectivityPtr2> + friend PUGS_INLINE void copy_to(const ItemArray<std::add_const_t<DataType>, item_type, ConnectivityPtr>& source, + const ItemArray<DataType, item_type, ConnectivityPtr2>& destination); + + template <typename ConnectivityPtr2> + friend PUGS_INLINE void + copy_to(const ItemArray<DataType, item_type, ConnectivityPtr>& source, + const ItemArray<std::remove_const_t<DataType>, item_type, ConnectivityPtr2>& destination) + { + Assert(destination.connectivity_ptr() == source.connectivity_ptr()); + copy_to(source.m_values, destination.m_values); + } + PUGS_INLINE bool isBuilt() const noexcept diff --git a/src/mesh/ItemValue.hpp b/src/mesh/ItemValue.hpp index 0f7fe61717fc9d8c571d0107b5ae422cc6b911bb..ebc5f40511a0be6d1eeb519a0660b494d268f150 100644 --- a/src/mesh/ItemValue.hpp +++ b/src/mesh/ItemValue.hpp @@ -47,6 +47,19 @@ class ItemValue return image; } + template <typename ConnectivityPtr2> + friend PUGS_INLINE void copy_to(const ItemValue<std::add_const_t<DataType>, item_type, ConnectivityPtr>& source, + const ItemValue<DataType, item_type, ConnectivityPtr2>& destination); + + template <typename ConnectivityPtr2> + friend PUGS_INLINE void + copy_to(const ItemValue<DataType, item_type, ConnectivityPtr>& source, + const ItemValue<std::remove_const_t<DataType>, item_type, ConnectivityPtr2>& destination) + { + Assert(destination.connectivity_ptr() == source.connectivity_ptr()); + copy_to(source.m_values, destination.m_values); + } + PUGS_INLINE bool isBuilt() const noexcept diff --git a/src/mesh/Mesh.hpp b/src/mesh/Mesh.hpp index 45f4c8d050d7fd7c63e44caf002b6bbcb1c7599a..e5817a2a9394b96bea04e78d061e166d3f0fbc02 100644 --- a/src/mesh/Mesh.hpp +++ b/src/mesh/Mesh.hpp @@ -18,7 +18,7 @@ class Mesh final : public IMesh private: const std::shared_ptr<const Connectivity> m_connectivity; - NodeValue<const Rd> m_xr; + const NodeValue<const Rd> m_xr; public: PUGS_INLINE @@ -85,7 +85,7 @@ class Mesh final : public IMesh } PUGS_INLINE - Mesh(const std::shared_ptr<const Connectivity>& connectivity, NodeValue<Rd>& xr) + Mesh(const std::shared_ptr<const Connectivity>& connectivity, const NodeValue<const Rd>& xr) : m_connectivity{connectivity}, m_xr{xr} { ; diff --git a/src/mesh/MeshData.hpp b/src/mesh/MeshData.hpp index 99cc8aeeb4ca127e8e60ba3e7ee75fcc93e8db76..f891f5ccb40e92cfbd0aa9e4cf3a600f352a8790 100644 --- a/src/mesh/MeshData.hpp +++ b/src/mesh/MeshData.hpp @@ -42,36 +42,75 @@ class MeshData : public IMeshData CellValue<const Rd> m_cell_iso_barycenter; CellValue<const double> m_Vj; CellValue<const double> m_sum_r_ljr; + FaceValue<const Rd> m_Nl; + FaceValue<const Rd> m_nl; FaceValue<const double> m_ll; PUGS_INLINE void - _compute_ll() + _computeNl() { if constexpr (Dimension == 1) { - static_assert(Dimension != 1, "ll does not make sense in 1d"); + static_assert(Dimension != 1, "Nl does not make sense in 1d"); } else { const auto& Nlr = this->Nlr(); - FaceValue<double> ll{m_mesh.connectivity()}; + FaceValue<Rd> Nl{m_mesh.connectivity()}; const auto& face_to_node_matrix = m_mesh.connectivity().faceToNodeMatrix(); parallel_for( m_mesh.numberOfFaces(), PUGS_LAMBDA(FaceId face_id) { const auto& face_nodes = face_to_node_matrix[face_id]; - double lenght = 0; + Rd N = zero; for (size_t i_node = 0; i_node < face_nodes.size(); ++i_node) { - lenght += l2Norm(Nlr(face_id, i_node)); + N += Nlr(face_id, i_node); } - - ll[face_id] = lenght; + Nl[face_id] = N; }); + m_Nl = Nl; + } + } + + PUGS_INLINE + void + _compute_ll() + { + if constexpr (Dimension == 1) { + static_assert(Dimension != 1, "ll does not make sense in 1d"); + } else { + const auto& Nl = this->Nl(); + + FaceValue<double> ll{m_mesh.connectivity()}; + + parallel_for( + m_mesh.numberOfFaces(), PUGS_LAMBDA(FaceId face_id) { ll[face_id] = L2Norm(Nl[face_id]); }); + m_ll = ll; } } + PUGS_INLINE + void + _compute_nl() + { + if constexpr (Dimension == 1) { + static_assert(Dimension != 1, "Nl does not make sense in 1d"); + } else { + const auto& Nl = this->Nl(); + const auto& ll = this->ll(); + + FaceValue<Rd> nl{m_mesh.connectivity()}; + + const auto& face_to_node_matrix = m_mesh.connectivity().faceToNodeMatrix(); + parallel_for( + m_mesh.numberOfFaces(), PUGS_LAMBDA(FaceId face_id) { nl[face_id] = (1. / ll[face_id]) * Nl[face_id]; }); + + m_Nl = Nl; + } + } + PUGS_INLINE void _compute_nlr() @@ -310,7 +349,7 @@ class MeshData : public IMeshData Rd Nr = zero; const Rd two_dxr = 2 * dxr[r]; for (size_t s = 0; s < nb_nodes; ++s) { - Nr += crossProduct((two_dxr - dxr[s]), xr[face_nodes[s]]); + Nr += crossProduct(two_dxr - dxr[s], xr[face_nodes[s]]); } Nr *= inv_12_nb_nodes; Nr -= (1. / 6.) * crossProduct(dxr[r], xr[face_nodes[r]]); @@ -358,8 +397,7 @@ class MeshData : public IMeshData const auto& cell_face_is_reversed = m_mesh.connectivity().cellFaceIsReversed(); NodeValuePerCell<Rd> Cjr(m_mesh.connectivity()); - parallel_for( - Cjr.numberOfValues(), PUGS_LAMBDA(size_t jr) { Cjr[jr] = zero; }); + Cjr.fill(zero); parallel_for( m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { @@ -491,6 +529,16 @@ class MeshData : public IMeshData return m_mesh; } + PUGS_INLINE + FaceValue<const Rd> + Nl() + { + if (not m_Nl.isBuilt()) { + this->_computeNl(); + } + return m_Nl; + } + PUGS_INLINE FaceValue<const double> ll() @@ -501,6 +549,16 @@ class MeshData : public IMeshData return m_ll; } + PUGS_INLINE + FaceValue<const Rd> + nl() + { + if (not m_nl.isBuilt()) { + this->_compute_nl(); + } + return m_nl; + } + PUGS_INLINE NodeValuePerFace<const Rd> Nlr() diff --git a/src/mesh/SubItemArrayPerItem.hpp b/src/mesh/SubItemArrayPerItem.hpp index d39bff6a3015b61fbbe853dbeb9970e237068068..501762ea6270b7ebf59b26c4afdea6edd552cc3e 100644 --- a/src/mesh/SubItemArrayPerItem.hpp +++ b/src/mesh/SubItemArrayPerItem.hpp @@ -10,8 +10,6 @@ #include <utils/PugsAssert.hpp> #include <utils/Table.hpp> -#include <utils/SubArray.hpp> - #include <memory> template <typename DataType, typename ItemOfItem, typename ConnectivityPtr = std::shared_ptr<const IConnectivity>> diff --git a/src/scheme/AcousticSolver.cpp b/src/scheme/AcousticSolver.cpp index 3336fd716822a86f86fc335a3f02cb80882a26fc..6bac5a6b3d920f9f3b5654e826bf9b974a9fcd0f 100644 --- a/src/scheme/AcousticSolver.cpp +++ b/src/scheme/AcousticSolver.cpp @@ -1,5 +1,6 @@ #include <scheme/AcousticSolver.hpp> +#include <language/utils/InterpolateItemValue.hpp> #include <mesh/ItemValueUtils.hpp> #include <mesh/MeshNodeBoundary.hpp> #include <scheme/DirichletBoundaryConditionDescriptor.hpp> diff --git a/src/scheme/DiscreteFunctionInterpoler.cpp b/src/scheme/DiscreteFunctionInterpoler.cpp index fda64fdcb82d1eb36b8925e9cdc438989cd92306..c8eeaf94cb8d4f1037b28ebf65d377660464c093 100644 --- a/src/scheme/DiscreteFunctionInterpoler.cpp +++ b/src/scheme/DiscreteFunctionInterpoler.cpp @@ -1,5 +1,6 @@ #include <scheme/DiscreteFunctionInterpoler.hpp> +#include <language/utils/InterpolateItemValue.hpp> #include <scheme/DiscreteFunctionP0.hpp> #include <utils/Exceptions.hpp> @@ -7,8 +8,14 @@ template <size_t Dimension, typename DataType> std::shared_ptr<IDiscreteFunction> DiscreteFunctionInterpoler::_interpolate() const { - std::shared_ptr mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(m_mesh); - return std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh, m_function_id); + std::shared_ptr mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(m_mesh); + using MeshDataType = MeshData<Dimension>; + MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*mesh); + + return std::make_shared< + DiscreteFunctionP0<Dimension, DataType>>(mesh, + InterpolateItemValue<DataType(TinyVector<Dimension>)>:: + template interpolate<ItemType::cell>(m_function_id, mesh_data.xj())); } template <size_t Dimension> diff --git a/src/scheme/DiscreteFunctionP0.hpp b/src/scheme/DiscreteFunctionP0.hpp index d41d98db99a0fa74bbe8e05496d5324f33db0634..0b77aaea481451c6662dd450756affc02ce0226d 100644 --- a/src/scheme/DiscreteFunctionP0.hpp +++ b/src/scheme/DiscreteFunctionP0.hpp @@ -3,7 +3,6 @@ #include <scheme/IDiscreteFunction.hpp> -#include <language/utils/InterpolateItemValue.hpp> #include <mesh/Connectivity.hpp> #include <mesh/Mesh.hpp> #include <mesh/MeshData.hpp> @@ -19,6 +18,9 @@ class DiscreteFunctionP0 : public IDiscreteFunction static constexpr HandledItemDataType handled_data_type = HandledItemDataType::value; + friend class DiscreteFunctionP0<Dimension, std::add_const_t<DataType>>; + friend class DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>>; + private: std::shared_ptr<const MeshType> m_mesh; CellValue<DataType> m_cell_values; @@ -26,24 +28,28 @@ class DiscreteFunctionP0 : public IDiscreteFunction DiscreteFunctionDescriptorP0 m_discrete_function_descriptor; public: + PUGS_INLINE ASTNodeDataType dataType() const final { return ast_node_data_type_from<DataType>; } + PUGS_INLINE const CellValue<DataType>& cellValues() const { return m_cell_values; } + PUGS_INLINE std::shared_ptr<const IMesh> mesh() const { return m_mesh; } + PUGS_INLINE const IDiscreteFunctionDescriptor& descriptor() const final { @@ -51,86 +57,470 @@ class DiscreteFunctionP0 : public IDiscreteFunction } PUGS_FORCEINLINE - DataType& + operator DiscreteFunctionP0<Dimension, const DataType>() const + { + return DiscreteFunctionP0<Dimension, const DataType>(m_mesh, m_cell_values); + } + + PUGS_INLINE + void + fill(const DataType& data) const noexcept + { + static_assert(not std::is_const_v<DataType>, "Cannot modify ItemValue of const"); + m_cell_values.fill(data); + } + + PUGS_INLINE DiscreteFunctionP0 + operator=(const DiscreteFunctionP0& f) + { + Assert(m_mesh == f.m_mesh); + m_cell_values = f.m_cell_values; + return *this; + } + + friend PUGS_INLINE DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> + copy(const DiscreteFunctionP0& source) + { + return DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>>{source.m_mesh, copy(source.cellValues())}; + } + + friend PUGS_INLINE void + copy_to(const DiscreteFunctionP0<Dimension, DataType>& source, + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>>& destination) + { + Assert(source.m_mesh == destination.m_mesh); + copy_to(source.m_cell_values, destination.m_cell_values); + } + + PUGS_FORCEINLINE DataType& operator[](const CellId cell_id) const noexcept(NO_ASSERT) { return m_cell_values[cell_id]; } - friend DiscreteFunctionP0 - operator+(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) + PUGS_INLINE DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> + operator-() const + { + Assert(m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> opposite = copy(*this); + parallel_for( + m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { opposite[cell_id] = -opposite[cell_id]; }); + + return opposite; + } + + template <typename DataType2T> + PUGS_INLINE DiscreteFunctionP0<Dimension, decltype(DataType{} + DataType2T{})> + operator+(const DiscreteFunctionP0<Dimension, DataType2T>& g) const { - Assert(f.mesh() == g.mesh(), "functions are nor defined on the same mesh"); - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0 sum(mesh); + const DiscreteFunctionP0& f = *this; + Assert(f.m_cell_values.isBuilt() and g.m_cell_values.isBuilt()); + Assert(f.mesh() == g.mesh(), "functions are not defined on the same mesh"); + DiscreteFunctionP0<Dimension, decltype(DataType{} + DataType2T{})> sum(f.m_mesh); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum[cell_id] = f[cell_id] + g[cell_id]; }); + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum[cell_id] = f[cell_id] + g[cell_id]; }); return sum; } - friend DiscreteFunctionP0 - operator-(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) + template <typename LHSDataType> + PUGS_INLINE friend DiscreteFunctionP0<Dimension, decltype(LHSDataType{} + DataType{})> + operator+(const LHSDataType& a, const DiscreteFunctionP0& g) { - Assert(f.mesh() == g.mesh(), "functions are nor defined on the same mesh"); - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0 difference(mesh); + using SumDataType = decltype(LHSDataType{} + DataType{}); + Assert(g.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, SumDataType> sum(g.m_mesh); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference[cell_id] = f[cell_id] - g[cell_id]; }); + g.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum[cell_id] = a + g[cell_id]; }); + return sum; + } + + template <typename RHSDataType> + PUGS_INLINE friend DiscreteFunctionP0<Dimension, decltype(DataType{} + RHSDataType{})> + operator+(const DiscreteFunctionP0& f, const RHSDataType& b) + { + using SumDataType = decltype(DataType{} + RHSDataType{}); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, SumDataType> sum(f.m_mesh); + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum[cell_id] = f[cell_id] + b; }); + return sum; + } + + template <typename DataType2T> + PUGS_INLINE DiscreteFunctionP0<Dimension, decltype(DataType{} - DataType2T{})> + operator-(const DiscreteFunctionP0<Dimension, DataType2T>& g) const + { + const DiscreteFunctionP0& f = *this; + Assert(f.m_cell_values.isBuilt() and g.m_cell_values.isBuilt()); + Assert(f.mesh() == g.mesh(), "functions are not defined on the same mesh"); + DiscreteFunctionP0<Dimension, decltype(DataType{} - DataType2T{})> difference(f.m_mesh); + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference[cell_id] = f[cell_id] - g[cell_id]; }); return difference; } - friend DiscreteFunctionP0 - operator*(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) + template <typename LHSDataType> + PUGS_INLINE friend DiscreteFunctionP0<Dimension, decltype(LHSDataType{} - DataType{})> + operator-(const LHSDataType& a, const DiscreteFunctionP0& g) { - Assert(f.mesh() == g.mesh(), "functions are nor defined on the same mesh"); - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0 product(mesh); + using DifferenceDataType = decltype(LHSDataType{} - DataType{}); + Assert(g.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, DifferenceDataType> difference(g.m_mesh); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = f[cell_id] * g[cell_id]; }); - return product; + g.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference[cell_id] = a - g[cell_id]; }); + return difference; + } + + template <typename RHSDataType> + PUGS_INLINE friend DiscreteFunctionP0<Dimension, decltype(DataType{} - RHSDataType{})> + operator-(const DiscreteFunctionP0& f, const RHSDataType& b) + { + using DifferenceDataType = decltype(DataType{} - RHSDataType{}); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, DifferenceDataType> difference(f.m_mesh); + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference[cell_id] = f[cell_id] - b; }); + return difference; } template <typename DataType2T> - friend DiscreteFunctionP0<Dimension, decltype(DataType2T{} * DataType{})> - operator*(const DiscreteFunctionP0<Dimension, DataType2T>& f, const DiscreteFunctionP0& g) + PUGS_INLINE DiscreteFunctionP0<Dimension, decltype(DataType{} * DataType2T{})> + operator*(const DiscreteFunctionP0<Dimension, DataType2T>& g) const { - Assert(f.mesh() == g.mesh(), "functions are nor defined on the same mesh"); - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0<Dimension, decltype(DataType2T{} * DataType{})> product(mesh); + const DiscreteFunctionP0& f = *this; + Assert(f.m_cell_values.isBuilt()); + Assert(f.mesh() == g.mesh(), "functions are not defined on the same mesh"); + DiscreteFunctionP0<Dimension, decltype(DataType{} * DataType2T{})> product(f.m_mesh); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = f[cell_id] * g[cell_id]; }); + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = f[cell_id] * g[cell_id]; }); return product; } - friend DiscreteFunctionP0 - operator*(const double& a, const DiscreteFunctionP0& f) + template <typename LHSDataType> + PUGS_INLINE friend DiscreteFunctionP0<Dimension, decltype(LHSDataType{} * DataType{})> + operator*(const LHSDataType& a, const DiscreteFunctionP0& f) { - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0 product(mesh); + using ProductDataType = decltype(LHSDataType{} * DataType{}); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, ProductDataType> product(f.m_mesh); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = a * f[cell_id]; }); + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = a * f[cell_id]; }); return product; } - friend DiscreteFunctionP0 - operator/(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) + template <typename RHSDataType> + PUGS_INLINE friend DiscreteFunctionP0<Dimension, decltype(DataType{} * RHSDataType{})> + operator*(const DiscreteFunctionP0& f, const RHSDataType& b) { - Assert(f.mesh() == g.mesh(), "functions are nor defined on the same mesh"); - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0 ratio(mesh); + using ProductDataType = decltype(DataType{} * RHSDataType{}); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, ProductDataType> product(f.m_mesh); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio[cell_id] = f[cell_id] / g[cell_id]; }); + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = f[cell_id] * b; }); + return product; + } + + template <typename DataType2T> + PUGS_INLINE DiscreteFunctionP0<Dimension, decltype(DataType{} / DataType2T{})> + operator/(const DiscreteFunctionP0<Dimension, DataType2T>& g) const + { + const DiscreteFunctionP0& f = *this; + Assert(f.m_cell_values.isBuilt() and g.m_cell_values.isBuilt()); + Assert(f.mesh() == g.mesh(), "functions are not defined on the same mesh"); + DiscreteFunctionP0<Dimension, decltype(DataType{} / DataType2T{})> ratio(f.m_mesh); + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio[cell_id] = f[cell_id] / g[cell_id]; }); return ratio; } - DiscreteFunctionP0(const std::shared_ptr<const MeshType>& mesh, const FunctionSymbolId& function_id) : m_mesh(mesh) + template <typename LHSDataType> + PUGS_INLINE friend DiscreteFunctionP0<Dimension, decltype(LHSDataType{} / DataType{})> + operator/(const LHSDataType& a, const DiscreteFunctionP0& f) + { + using RatioDataType = decltype(LHSDataType{} / DataType{}); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, RatioDataType> ratio(f.m_mesh); + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio[cell_id] = a / f[cell_id]; }); + return ratio; + } + + template <typename RHSDataType> + PUGS_INLINE friend DiscreteFunctionP0<Dimension, decltype(DataType{} / RHSDataType{})> + operator/(const DiscreteFunctionP0& f, const RHSDataType& b) + { + using RatioDataType = decltype(DataType{} / RHSDataType{}); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, RatioDataType> ratio(f.m_mesh); + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio[cell_id] = f[cell_id] / b; }); + return ratio; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + sqrt(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::sqrt(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + abs(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::abs(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + sin(const DiscreteFunctionP0& f) { - using MeshDataType = MeshData<Dimension>; - MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*mesh); + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::sin(f[cell_id]); }); - m_cell_values = - InterpolateItemValue<DataType(TinyVector<Dimension>)>::template interpolate<ItemType::cell>(function_id, - mesh_data.xj()); + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + cos(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::cos(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + tan(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::tan(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + asin(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::asin(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + acos(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::acos(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + atan(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::atan(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + sinh(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::sinh(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + cosh(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::cosh(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + tanh(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::tanh(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + asinh(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::asinh(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + acosh(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::acosh(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + atanh(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::atanh(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + exp(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::exp(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> + log(const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::log(f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0 + atan2(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt() and g.m_cell_values.isBuilt()); + Assert(f.m_mesh == g.m_mesh); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::atan2(f[cell_id], g[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0 + atan2(const double a, const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::atan2(a, f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0 + atan2(const DiscreteFunctionP0& f, const double a) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::atan2(f[cell_id], a); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0 + pow(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt() and g.m_cell_values.isBuilt()); + Assert(f.m_mesh == g.m_mesh); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::pow(f[cell_id], g[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0 + pow(const double a, const DiscreteFunctionP0& f) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::pow(a, f[cell_id]); }); + + return result; + } + + PUGS_INLINE friend DiscreteFunctionP0 + pow(const DiscreteFunctionP0& f, const double a) + { + static_assert(std::is_arithmetic_v<DataType>); + Assert(f.m_cell_values.isBuilt()); + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{f.m_mesh}; + parallel_for( + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = std::pow(f[cell_id], a); }); + + return result; } DiscreteFunctionP0(const std::shared_ptr<const MeshType>& mesh) : m_mesh{mesh}, m_cell_values{mesh->connectivity()} {} @@ -138,73 +528,15 @@ class DiscreteFunctionP0 : public IDiscreteFunction DiscreteFunctionP0(const std::shared_ptr<const MeshType>& mesh, const CellValue<DataType>& cell_value) : m_mesh{mesh}, m_cell_values{cell_value} { - Assert(mesh->connectivity().shared_ptr() == cell_value.connectivity_ptr()); + Assert(mesh->shared_connectivity() == cell_value.connectivity_ptr()); } + DiscreteFunctionP0() noexcept = delete; + DiscreteFunctionP0(const DiscreteFunctionP0&) noexcept = default; DiscreteFunctionP0(DiscreteFunctionP0&&) noexcept = default; ~DiscreteFunctionP0() = default; }; -template <size_t Dimension, size_t ValueDimension> -DiscreteFunctionP0<Dimension, TinyVector<ValueDimension>> -operator*(const TinyMatrix<ValueDimension>& A, const DiscreteFunctionP0<Dimension, TinyVector<ValueDimension>>& f) -{ - using MeshType = typename DiscreteFunctionP0<Dimension, TinyVector<ValueDimension>>::MeshType; - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0<Dimension, TinyVector<ValueDimension>> product(mesh); - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = A * f[cell_id]; }); - return product; -} - -template <size_t Dimension, size_t ValueDimension> -DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>> -operator*(const TinyMatrix<ValueDimension>& A, const DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>>& f) -{ - using MeshType = typename DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>>::MeshType; - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>> product(mesh); - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = A * f[cell_id]; }); - return product; -} - -template <size_t Dimension, size_t ValueDimension> -DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>> -operator*(const DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>>& f, const TinyMatrix<ValueDimension>& A) -{ - using MeshType = typename DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>>::MeshType; - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>> product(mesh); - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = f[cell_id] * A; }); - return product; -} - -template <size_t Dimension, size_t ValueDimension> -DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>> -operator*(const DiscreteFunctionP0<Dimension, double>& f, const TinyMatrix<ValueDimension>& A) -{ - using MeshType = typename DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>>::MeshType; - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0<Dimension, TinyMatrix<ValueDimension>> product(mesh); - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = f[cell_id] * A; }); - return product; -} - -template <size_t Dimension, size_t ValueDimension> -DiscreteFunctionP0<Dimension, TinyVector<ValueDimension>> -operator*(const DiscreteFunctionP0<Dimension, double>& f, const TinyVector<ValueDimension>& A) -{ - using MeshType = typename DiscreteFunctionP0<Dimension, TinyVector<ValueDimension>>::MeshType; - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0<Dimension, TinyVector<ValueDimension>> product(mesh); - parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product[cell_id] = f[cell_id] * A; }); - return product; -} - #endif // DISCRETE_FUNCTION_P0_HPP diff --git a/src/scheme/DiscreteFunctionP0Vector.hpp b/src/scheme/DiscreteFunctionP0Vector.hpp index 77ddf70f1d7f14a1c4dcab4cb352d4c6280d1715..103718b125e123692241715e697ab89869d078eb 100644 --- a/src/scheme/DiscreteFunctionP0Vector.hpp +++ b/src/scheme/DiscreteFunctionP0Vector.hpp @@ -3,7 +3,6 @@ #include <scheme/IDiscreteFunction.hpp> -#include <language/utils/InterpolateItemArray.hpp> #include <mesh/Connectivity.hpp> #include <mesh/ItemArray.hpp> #include <mesh/Mesh.hpp> @@ -22,6 +21,9 @@ class DiscreteFunctionP0Vector : public IDiscreteFunction static constexpr HandledItemDataType handled_data_type = HandledItemDataType::vector; + friend class DiscreteFunctionP0Vector<Dimension, std::add_const_t<DataType>>; + friend class DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>>; + static_assert(std::is_arithmetic_v<DataType>, "DiscreteFunctionP0Vector are only defined for arithmetic data type"); private: @@ -31,6 +33,7 @@ class DiscreteFunctionP0Vector : public IDiscreteFunction DiscreteFunctionDescriptorP0Vector m_discrete_function_descriptor; public: + PUGS_INLINE ASTNodeDataType dataType() const final { @@ -44,18 +47,21 @@ class DiscreteFunctionP0Vector : public IDiscreteFunction return m_cell_arrays.sizeOfArrays(); } + PUGS_INLINE const CellArray<DataType>& cellArrays() const { return m_cell_arrays; } + PUGS_INLINE std::shared_ptr<const IMesh> mesh() const { return m_mesh; } + PUGS_INLINE const IDiscreteFunctionDescriptor& descriptor() const final { @@ -63,21 +69,75 @@ class DiscreteFunctionP0Vector : public IDiscreteFunction } PUGS_FORCEINLINE - Array<double> + operator DiscreteFunctionP0Vector<Dimension, const DataType>() const + { + return DiscreteFunctionP0Vector<Dimension, const DataType>(m_mesh, m_cell_arrays); + } + + PUGS_INLINE + void + fill(const DataType& data) const noexcept + { + static_assert(not std::is_const_v<DataType>, "Cannot modify ItemValue of const"); + m_cell_arrays.fill(data); + } + + PUGS_INLINE DiscreteFunctionP0Vector + operator=(const DiscreteFunctionP0Vector& f) + { + Assert(m_mesh == f.m_mesh); + Assert(this->size() == f.size()); + m_cell_arrays = f.m_cell_arrays; + return *this; + } + + friend PUGS_INLINE DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> + copy(const DiscreteFunctionP0Vector& source) + { + return DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>>{source.m_mesh, copy(source.cellArrays())}; + } + + friend PUGS_INLINE void + copy_to(const DiscreteFunctionP0Vector<Dimension, DataType>& source, + DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>>& destination) + { + Assert(source.m_mesh == destination.m_mesh); + copy_to(source.m_cell_arrays, destination.m_cell_arrays); + } + + PUGS_FORCEINLINE + Array<DataType> operator[](const CellId cell_id) const noexcept(NO_ASSERT) { return m_cell_arrays[cell_id]; } - friend DiscreteFunctionP0Vector + PUGS_INLINE DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> + operator-() const + { + Assert(m_cell_arrays.isBuilt()); + DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> opposite = copy(*this); + + const size_t size_of_arrays = this->size(); + parallel_for( + m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + auto array = opposite[cell_id]; + for (size_t i = 0; i < size_of_arrays; ++i) { + array[i] = -array[i]; + } + }); + + return opposite; + } + + friend DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> operator+(const DiscreteFunctionP0Vector& f, const DiscreteFunctionP0Vector& g) { - Assert(f.mesh() == g.mesh(), "functions are nor defined on the same mesh"); + Assert(f.m_mesh == g.m_mesh, "functions are nor defined on the same mesh"); Assert(f.size() == g.size(), "P0 vectors have different sizes"); - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0Vector sum(mesh, f.size()); + DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> sum(f.m_mesh, f.size()); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { for (size_t i = 0; i < f.size(); ++i) { sum[cell_id][i] = f[cell_id][i] + g[cell_id][i]; } @@ -85,15 +145,14 @@ class DiscreteFunctionP0Vector : public IDiscreteFunction return sum; } - friend DiscreteFunctionP0Vector + friend DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> operator-(const DiscreteFunctionP0Vector& f, const DiscreteFunctionP0Vector& g) { Assert(f.mesh() == g.mesh(), "functions are nor defined on the same mesh"); Assert(f.size() == g.size(), "P0 vectors have different sizes"); - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0Vector difference(mesh, f.size()); + DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> difference(f.m_mesh, f.size()); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { for (size_t i = 0; i < f.size(); ++i) { difference[cell_id][i] = f[cell_id][i] - g[cell_id][i]; } @@ -102,63 +161,47 @@ class DiscreteFunctionP0Vector : public IDiscreteFunction } template <typename DataType2> - friend DiscreteFunctionP0Vector + friend DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> operator*(const DiscreteFunctionP0<Dimension, DataType2>& f, const DiscreteFunctionP0Vector& g) { static_assert(std::is_arithmetic_v<DataType2>, "left operand must be arithmetic"); Assert(f.mesh() == g.mesh(), "functions are nor defined on the same mesh"); - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0Vector product(mesh, g.size()); + DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> product(g.m_mesh, g.size()); + const size_t size_of_arrays = g.size(); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - const double f_value = f[cell_id]; - for (size_t i = 0; i < g.size(); ++i) { + g.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const DataType2& f_value = f[cell_id]; + for (size_t i = 0; i < size_of_arrays; ++i) { product[cell_id][i] = f_value * g[cell_id][i]; } }); return product; } - friend DiscreteFunctionP0Vector - operator*(double a, const DiscreteFunctionP0Vector& f) + template <typename DataType2> + friend DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> + operator*(const DataType2& a, const DiscreteFunctionP0Vector& f) { - std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); - DiscreteFunctionP0Vector product(mesh, f.size()); + DiscreteFunctionP0Vector<Dimension, std::remove_const_t<DataType>> product(f.m_mesh, f.size()); + const size_t size_of_arrays = f.size(); parallel_for( - mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { - for (size_t i = 0; i < f.size(); ++i) { + f.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size_of_arrays; ++i) { product[cell_id][i] = a * f[cell_id][i]; } }); return product; } - DiscreteFunctionP0Vector(const std::shared_ptr<const MeshType>& mesh, - const std::vector<FunctionSymbolId>& function_symbol_id_list) - : m_mesh(mesh) - { - using MeshDataType = MeshData<Dimension>; - MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*mesh); - - m_cell_arrays = InterpolateItemArray<DataType( - TinyVector<Dimension>)>::template interpolate<ItemType::cell>(function_symbol_id_list, mesh_data.xj()); - } - DiscreteFunctionP0Vector(const std::shared_ptr<const MeshType>& mesh, size_t size) : m_mesh{mesh}, m_cell_arrays{mesh->connectivity(), size} {} - template <typename DataType2> - DiscreteFunctionP0Vector(const std::shared_ptr<const MeshType>& mesh, const CellArray<DataType2>& cell_arrays) - : m_mesh{mesh} + DiscreteFunctionP0Vector(const std::shared_ptr<const MeshType>& mesh, const CellArray<DataType>& cell_arrays) + : m_mesh{mesh}, m_cell_arrays{cell_arrays} { - static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>); - static_assert(std::is_const_v<DataType> or not std::is_const_v<DataType2>); - - Assert(mesh->connectivity_ptr() == cell_arrays.connectivity_ptr()); - - m_cell_arrays = cell_arrays; + Assert(mesh->shared_connectivity() == cell_arrays.connectivity_ptr()); } DiscreteFunctionP0Vector(const DiscreteFunctionP0Vector&) noexcept = default; diff --git a/src/scheme/DiscreteFunctionType.hpp b/src/scheme/DiscreteFunctionType.hpp index 8532a25e9111d40a8fcfbd4d0fe8cb6805d525c9..6dd002be688133cbc96a5780d7933fad51bf86cb 100644 --- a/src/scheme/DiscreteFunctionType.hpp +++ b/src/scheme/DiscreteFunctionType.hpp @@ -21,7 +21,9 @@ name(DiscreteFunctionType type) case DiscreteFunctionType::P0Vector: return "P0Vector"; } + // LCOV_EXCL_START return {}; + // LCOV_EXCL_STOP } #endif // DISCRETE_FUNCTION_TYPE_HPP diff --git a/src/scheme/DiscreteFunctionVectorInterpoler.cpp b/src/scheme/DiscreteFunctionVectorInterpoler.cpp index 1a5077377dd1858f5f3c2fa495621598784e8360..4827345a5864ccae5425f6463e00163d455a4aa8 100644 --- a/src/scheme/DiscreteFunctionVectorInterpoler.cpp +++ b/src/scheme/DiscreteFunctionVectorInterpoler.cpp @@ -1,5 +1,6 @@ #include <scheme/DiscreteFunctionVectorInterpoler.hpp> +#include <language/utils/InterpolateItemArray.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> #include <utils/Exceptions.hpp> @@ -8,7 +9,14 @@ std::shared_ptr<IDiscreteFunction> DiscreteFunctionVectorInterpoler::_interpolate() const { std::shared_ptr mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(m_mesh); - return std::make_shared<DiscreteFunctionP0Vector<Dimension, DataType>>(mesh, m_function_id_list); + + using MeshDataType = MeshData<Dimension>; + MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*mesh); + + return std::make_shared< + DiscreteFunctionP0Vector<Dimension, DataType>>(mesh, InterpolateItemArray<DataType(TinyVector<Dimension>)>:: + template interpolate<ItemType::cell>(m_function_id_list, + mesh_data.xj())); } template <size_t Dimension> @@ -41,6 +49,10 @@ DiscreteFunctionVectorInterpoler::_interpolate() const std::shared_ptr<IDiscreteFunction> DiscreteFunctionVectorInterpoler::interpolate() const { + if (m_discrete_function_descriptor->type() != DiscreteFunctionType::P0Vector) { + throw NormalError("invalid discrete function type for vector interpolation"); + } + std::shared_ptr<IDiscreteFunction> discrete_function; switch (m_mesh->dimension()) { case 1: { @@ -56,5 +68,4 @@ DiscreteFunctionVectorInterpoler::interpolate() const throw UnexpectedError("invalid dimension"); } } - return nullptr; } diff --git a/src/utils/Array.hpp b/src/utils/Array.hpp index 1fe0aacaac25b7541acab4dc532ab93e7f65070e..5eb834b85fb8f0679636531e740863286e912c3d 100644 --- a/src/utils/Array.hpp +++ b/src/utils/Array.hpp @@ -36,6 +36,13 @@ class [[nodiscard]] Array return image; } + friend PUGS_INLINE void copy_to(const Array<DataType>& source, + const Array<std::remove_const_t<DataType>>& destination) + { + Assert(source.size() == destination.size()); + Kokkos::deep_copy(destination.m_values, source.m_values); + } + template <typename DataType2, typename... RT> friend PUGS_INLINE Array<DataType2> encapsulate(const Kokkos::View<DataType2*, RT...>& values); diff --git a/src/utils/SubArray.hpp b/src/utils/SubArray.hpp deleted file mode 100644 index a5019dec9521039e420aeeef48c0439930a7840c..0000000000000000000000000000000000000000 --- a/src/utils/SubArray.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef SUB_ARRAY_HPP -#define SUB_ARRAY_HPP - -#include <utils/Array.hpp> -#include <utils/PugsAssert.hpp> -#include <utils/PugsMacros.hpp> -#include <utils/PugsUtils.hpp> - -#include <algorithm> - -template <typename DataType> -class [[nodiscard]] SubArray -{ - public: - using data_type = DataType; - using index_type = size_t; - - private: - PUGS_RESTRICT DataType* const m_sub_values; - const size_t m_size; - - // Allows const version to access our data - friend SubArray<std::add_const_t<DataType>>; - - public: - PUGS_INLINE size_t size() const noexcept - { - return m_size; - } - - PUGS_INLINE DataType& operator[](index_type i) const noexcept(NO_ASSERT) - { - Assert(i < m_size); - return m_sub_values[i]; - } - - PUGS_INLINE - void fill(const DataType& data) const - { - static_assert(not std::is_const<DataType>(), "Cannot modify SubArray of const"); - - // could consider to use std::fill - parallel_for( - this->size(), PUGS_LAMBDA(index_type i) { m_sub_values[i] = data; }); - } - - PUGS_INLINE - SubArray& operator=(const SubArray&) = delete; - - PUGS_INLINE - SubArray& operator=(SubArray&&) = delete; - - PUGS_INLINE - explicit SubArray(const Array<DataType>& array, size_t begin, size_t size) - : m_sub_values{&array[0] + begin}, m_size{size} - { - Assert(begin + size <= array.size(), "SubView is not contained in the source Array"); - } - - PUGS_INLINE - explicit SubArray(DataType* const raw_array, size_t begin, size_t size) - : m_sub_values{raw_array + begin}, m_size{size} - {} - - PUGS_INLINE - SubArray() = delete; - - PUGS_INLINE - SubArray(const SubArray&) = delete; - - PUGS_INLINE - SubArray(SubArray &&) = delete; - - PUGS_INLINE - ~SubArray() = default; -}; - -#endif // SUB_ARRAY_HPP diff --git a/src/utils/Table.hpp b/src/utils/Table.hpp index 67f544b997f32086131a549237de091e75ba60c1..eedc5e7d72c4c2f935f0ecafe0d24747c3b2d00e 100644 --- a/src/utils/Table.hpp +++ b/src/utils/Table.hpp @@ -46,6 +46,14 @@ class [[nodiscard]] Table return image; } + friend PUGS_INLINE void copy_to(const Table<DataType>& source, + const Table<std::remove_const_t<DataType>>& destination) + { + Assert(source.nbRows() == destination.nbRows()); + Assert(source.nbColumns() == destination.nbColumns()); + Kokkos::deep_copy(destination.m_values, source.m_values); + } + template <typename DataType2, typename... RT> friend PUGS_INLINE Table<DataType2> encapsulate(const Kokkos::View<DataType2**, RT...>& values); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c36830918d3d769870250d212ea6d04e5d8316fc..4bb227aac16a433471caa45bdfb8b8bc48f4f2bb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -58,6 +58,9 @@ add_executable (unit_tests test_CRSMatrix.cpp test_DataVariant.cpp test_Demangle.cpp + test_DiscreteFunctionDescriptorP0.cpp + test_DiscreteFunctionDescriptorP0Vector.cpp + test_DiscreteFunctionType.cpp test_DoWhileProcessor.cpp test_EmbeddedData.cpp test_EscapedString.cpp @@ -98,12 +101,16 @@ add_executable (unit_tests add_executable (mpi_unit_tests mpi_test_main.cpp - test_Messenger.cpp - test_Partitioner.cpp + test_DiscreteFunctionP0.cpp + test_DiscreteFunctionP0Vector.cpp + test_InterpolateItemArray.cpp + test_InterpolateItemValue.cpp test_ItemArray.cpp test_ItemArrayUtils.cpp test_ItemValue.cpp test_ItemValueUtils.cpp + test_Messenger.cpp + test_Partitioner.cpp test_SubItemValuePerItem.cpp test_SubItemArrayPerItem.cpp ) diff --git a/tests/MeshDataBaseForTests.cpp b/tests/MeshDataBaseForTests.cpp index 8debe252a86fac67463ffc74ab17e1f9ccf141ea..95399d4564f38313f443f144cf214298577f315a 100644 --- a/tests/MeshDataBaseForTests.cpp +++ b/tests/MeshDataBaseForTests.cpp @@ -7,13 +7,14 @@ const MeshDataBaseForTests* MeshDataBaseForTests::m_instance = nullptr; MeshDataBaseForTests::MeshDataBaseForTests() { - m_cartesian_1d_mesh = CartesianMeshBuilder{TinyVector<1>{-1}, TinyVector<1>{3}, TinyVector<1, size_t>{23}}.mesh(); + m_cartesian_1d_mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>( + CartesianMeshBuilder{TinyVector<1>{-1}, TinyVector<1>{3}, TinyVector<1, size_t>{23}}.mesh()); - m_cartesian_2d_mesh = - CartesianMeshBuilder{TinyVector<2>{0, -1}, TinyVector<2>{3, 2}, TinyVector<2, size_t>{6, 7}}.mesh(); + m_cartesian_2d_mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>( + CartesianMeshBuilder{TinyVector<2>{0, -1}, TinyVector<2>{3, 2}, TinyVector<2, size_t>{6, 7}}.mesh()); - m_cartesian_3d_mesh = - CartesianMeshBuilder{TinyVector<3>{0, 1, 0}, TinyVector<3>{2, -1, 3}, TinyVector<3, size_t>{6, 7, 4}}.mesh(); + m_cartesian_3d_mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<3>>>( + CartesianMeshBuilder{TinyVector<3>{0, 1, 0}, TinyVector<3>{2, -1, 3}, TinyVector<3, size_t>{6, 7, 4}}.mesh()); } const MeshDataBaseForTests& @@ -37,19 +38,20 @@ MeshDataBaseForTests::destroy() m_instance = nullptr; } -template <size_t Dimension> -const Mesh<Connectivity<Dimension>>& -MeshDataBaseForTests::cartesianMesh() const +std::shared_ptr<const Mesh<Connectivity<1>>> +MeshDataBaseForTests::cartesianMesh1D() const { - if constexpr (Dimension == 1) { - return dynamic_cast<const Mesh<Connectivity<Dimension>>&>(*m_cartesian_1d_mesh); - } else if constexpr (Dimension == 2) { - return dynamic_cast<const Mesh<Connectivity<Dimension>>&>(*m_cartesian_2d_mesh); - } else if constexpr (Dimension == 3) { - return dynamic_cast<const Mesh<Connectivity<Dimension>>&>(*m_cartesian_3d_mesh); - } + return m_cartesian_1d_mesh; } -template const Mesh<Connectivity<1>>& MeshDataBaseForTests::cartesianMesh<1>() const; -template const Mesh<Connectivity<2>>& MeshDataBaseForTests::cartesianMesh<2>() const; -template const Mesh<Connectivity<3>>& MeshDataBaseForTests::cartesianMesh<3>() const; +std::shared_ptr<const Mesh<Connectivity<2>>> +MeshDataBaseForTests::cartesianMesh2D() const +{ + return m_cartesian_2d_mesh; +} + +std::shared_ptr<const Mesh<Connectivity<3>>> +MeshDataBaseForTests::cartesianMesh3D() const +{ + return m_cartesian_3d_mesh; +} diff --git a/tests/MeshDataBaseForTests.hpp b/tests/MeshDataBaseForTests.hpp index 2a1b1c06c864f37981fd275067e0994a589afaac..589ec9b82f9be6451afd496aab3399c13bb3d718 100644 --- a/tests/MeshDataBaseForTests.hpp +++ b/tests/MeshDataBaseForTests.hpp @@ -18,13 +18,14 @@ class MeshDataBaseForTests static const MeshDataBaseForTests* m_instance; - std::shared_ptr<const IMesh> m_cartesian_1d_mesh; - std::shared_ptr<const IMesh> m_cartesian_2d_mesh; - std::shared_ptr<const IMesh> m_cartesian_3d_mesh; + std::shared_ptr<const Mesh<Connectivity<1>>> m_cartesian_1d_mesh; + std::shared_ptr<const Mesh<Connectivity<2>>> m_cartesian_2d_mesh; + std::shared_ptr<const Mesh<Connectivity<3>>> m_cartesian_3d_mesh; public: - template <size_t Dimension> - const Mesh<Connectivity<Dimension>>& cartesianMesh() const; + std::shared_ptr<const Mesh<Connectivity<1>>> cartesianMesh1D() const; + std::shared_ptr<const Mesh<Connectivity<2>>> cartesianMesh2D() const; + std::shared_ptr<const Mesh<Connectivity<3>>> cartesianMesh3D() const; static const MeshDataBaseForTests& get(); static void create(); diff --git a/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp b/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp index d9b5d245624eaba1ebb14e1e7869ac89e58b28b9..b99aa045958dc356cb03f2b548e8c632d58b124d 100644 --- a/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp +++ b/tests/test_ASTNodeBinaryOperatorExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeBinaryOperatorExpressionBuilder.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> @@ -22,6 +23,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 79e01aef9a34ab2324c0c731e1a2079d3e985d99..346807df3b58e189a7e1283850fbdda54264abbb 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -2,7 +2,9 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> +#include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> #include <language/utils/ASTNodeDataTypeTraits.hpp> #include <language/utils/ASTPrinter.hpp> @@ -20,6 +22,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -78,7 +83,16 @@ import a_module_name; `-(language::module_name:string) )"; - CHECK_AST(data, result); + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + std::stringstream ast_output; + ast_output << '\n' << ASTPrinter{*ast, ASTPrinter::Format::raw, {ASTPrinter::Info::data_type}}; + + REQUIRE(ast_output.str() == result); } SECTION("integer") @@ -392,7 +406,7 @@ let (x,y) : R; SECTION("invalid R-list -> R^d") { std::string_view data = R"( -let square : R -> R^3, x -> (x, x*x); +let square : R -> R^3, x -> (x, 2); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; @@ -999,7 +1013,8 @@ let f : R*Z -> B, x -> 3; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "number of product spaces (2) R*Z differs from number of variables (1) x"); } SECTION("wrong parameter number 2") @@ -1011,7 +1026,8 @@ let f : R -> B, (x,y) -> 3; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "number of product spaces (1) R differs from number of variables (2) (x,y) "); } SECTION("wrong image size") @@ -1034,6 +1050,10 @@ let f : R -> R*R, x -> x*x*x; )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTSymbolTableBuilder{*ast}; REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, @@ -1047,11 +1067,67 @@ let f : R -> R^2x2, x -> (x, 2*x, 2); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTSymbolTableBuilder{*ast}; REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "expecting 4 scalar expressions or an R^2x2, found 3 scalar expressions"); } + + SECTION("undefined type identifier") + { + std::string_view data = R"( +let x:X; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "undefined type identifier"); + } + + SECTION("undefined type identifier") + { + std::string_view data = R"( +let X:R, X = 3; +let x:X; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "invalid type identifier, 'X' was previously defined as a 'R'"); + } + + SECTION("undefined image type identifier") + { + std::string_view data = R"( +let f: R -> X, x -> x; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "undefined type identifier"); + } + + SECTION("invalid image type identifier") + { + std::string_view data = R"( +let X: R, X = 3; +let f: R -> X, x -> x; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "invalid type identifier, 'X' was previously defined as a 'R'"); + } } } @@ -1277,7 +1353,8 @@ not_a_function(2,3); auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "invalid function call\n" + "note: 'not_a_function' (type: R) is not a function!"); } } } @@ -1732,7 +1809,7 @@ if ("string"); TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "invalid implicit conversion: string -> B"); } } @@ -1818,7 +1895,7 @@ while ("string"); TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "invalid implicit conversion: string -> B"); } } @@ -1904,7 +1981,7 @@ do 1; while ("string"); TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "invalid implicit conversion: string -> B"); } } @@ -2223,7 +2300,8 @@ true xor false; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "undefined binary operator\n" + "note: incompatible operand types Z and string"); } } } diff --git a/tests/test_ASTNodeDataTypeChecker.cpp b/tests/test_ASTNodeDataTypeChecker.cpp index 4c8dc8cf03e475b97bd91a1422e55a909dede2b7..5c0fc6d8fd38054e4343470ef8f6196d7e34ac60 100644 --- a/tests/test_ASTNodeDataTypeChecker.cpp +++ b/tests/test_ASTNodeDataTypeChecker.cpp @@ -2,8 +2,10 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDataTypeChecker.hpp> +#include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> #include <language/utils/ParseError.hpp> @@ -25,6 +27,9 @@ for(let i:Z, i=0; i<10; ++i) { TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; @@ -43,6 +48,9 @@ for(let i:Z, i=0; i<10; ++i) { TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; diff --git a/tests/test_ASTNodeDataTypeFlattener.cpp b/tests/test_ASTNodeDataTypeFlattener.cpp index c49613ca827ed265e3e338a5639a7edfa862823c..d4b4bbe6c65e7bc0a110d70b406b24f678f82576 100644 --- a/tests/test_ASTNodeDataTypeFlattener.cpp +++ b/tests/test_ASTNodeDataTypeFlattener.cpp @@ -2,12 +2,15 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDataTypeFlattener.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> +#include <test_BuiltinFunctionRegister.hpp> + #include <pegtl/string_input.hpp> // clazy:excludeall=non-pod-global-static @@ -26,6 +29,9 @@ b; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); + ASTModulesImporter{*root_node}; + ASTNodeTypeCleaner<language::import_instruction>{*root_node}; + ASTSymbolTableBuilder{*root_node}; ASTNodeDataTypeBuilder{*root_node}; @@ -49,6 +55,9 @@ n; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); + ASTModulesImporter{*root_node}; + ASTNodeTypeCleaner<language::import_instruction>{*root_node}; + ASTSymbolTableBuilder{*root_node}; ASTNodeDataTypeBuilder{*root_node}; @@ -75,6 +84,9 @@ f(2); TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); + ASTModulesImporter{*root_node}; + ASTNodeTypeCleaner<language::import_instruction>{*root_node}; + ASTSymbolTableBuilder{*root_node}; ASTNodeDataTypeBuilder{*root_node}; @@ -104,6 +116,9 @@ f(2); TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); + ASTModulesImporter{*root_node}; + ASTNodeTypeCleaner<language::import_instruction>{*root_node}; + ASTSymbolTableBuilder{*root_node}; ASTNodeDataTypeBuilder{*root_node}; @@ -136,6 +151,9 @@ f(2); TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto root_node = ASTBuilder::build(input); + ASTModulesImporter{*root_node}; + ASTNodeTypeCleaner<language::import_instruction>{*root_node}; + ASTSymbolTableBuilder{*root_node}; ASTNodeDataTypeBuilder{*root_node}; @@ -155,5 +173,39 @@ f(2); REQUIRE(flattened_datatype_list[1].m_data_type == ASTNodeDataType::vector_t); REQUIRE(flattened_datatype_list[1].m_data_type.dimension() == 3); } + + SECTION("builtin_function -> R*R") + { + std::string_view data = R"( +sum_vector(2,3); +)"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto root_node = ASTBuilder::build(input); + + ASTModulesImporter{*root_node}; + ASTNodeTypeCleaner<language::import_instruction>{*root_node}; + + test_only::test_BuiltinFunctionRegister{*root_node}; + + ASTSymbolTableBuilder{*root_node}; + ASTNodeDataTypeBuilder{*root_node}; + + // optimizations + ASTNodeDeclarationToAffectationConverter{*root_node}; + + ASTNodeTypeCleaner<language::var_declaration>{*root_node}; + ASTNodeTypeCleaner<language::fct_declaration>{*root_node}; + + REQUIRE(root_node->children[0]->is_type<language::function_evaluation>()); + + ASTNodeDataTypeFlattener::FlattenedDataTypeList flattened_datatype_list; + ASTNodeDataTypeFlattener{*root_node->children[0], flattened_datatype_list}; + + REQUIRE(flattened_datatype_list.size() == 2); + REQUIRE(flattened_datatype_list[0].m_data_type == ASTNodeDataType::double_t); + REQUIRE(flattened_datatype_list[1].m_data_type == ASTNodeDataType::vector_t); + REQUIRE(flattened_datatype_list[1].m_data_type.dimension() == 2); + } } } diff --git a/tests/test_ASTNodeDeclarationToAffectationConverter.cpp b/tests/test_ASTNodeDeclarationToAffectationConverter.cpp index c102d5f6599f40a390bdb7b67004f3786624540f..f38b7aaf7c57d60d7fb7a6a44b1241b3d71aa6c0 100644 --- a/tests/test_ASTNodeDeclarationToAffectationConverter.cpp +++ b/tests/test_ASTNodeDeclarationToAffectationConverter.cpp @@ -2,8 +2,10 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> +#include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> #include <language/utils/ASTPrinter.hpp> @@ -17,6 +19,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_ASTNodeEmptyBlockCleaner.cpp b/tests/test_ASTNodeEmptyBlockCleaner.cpp index e9a7c4a5e9b786f9c9e4ba6fe34504f320bb5472..baf6978c6a6d04d8a4e68a75e5e61fad635f8b55 100644 --- a/tests/test_ASTNodeEmptyBlockCleaner.cpp +++ b/tests/test_ASTNodeEmptyBlockCleaner.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeEmptyBlockCleaner.hpp> @@ -22,6 +23,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_ASTNodeExpressionBuilder.cpp b/tests/test_ASTNodeExpressionBuilder.cpp index 11eb9f16177612f0c150a9b9f363fc219578c9cf..cb6fdbfef85884a013e112a978207729ba965835 100644 --- a/tests/test_ASTNodeExpressionBuilder.cpp +++ b/tests/test_ASTNodeExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -21,6 +22,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -39,6 +43,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ \ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ @@ -896,6 +903,10 @@ continue; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; diff --git a/tests/test_ASTNodeIncDecExpressionBuilder.cpp b/tests/test_ASTNodeIncDecExpressionBuilder.cpp index 88d1518fcad3511bba5cb6d426f752f72dd5c912..78391f1ee8e41f9b0d53cbddc2cea7aefe5e54ec 100644 --- a/tests/test_ASTNodeIncDecExpressionBuilder.cpp +++ b/tests/test_ASTNodeIncDecExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -23,6 +24,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -46,6 +50,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp index bcb8942e785f3ad9f5320a4ab321986736ae6b97..8ae86fa804a704c10e32c3fe3e5b986987e22de0 100644 --- a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp +++ b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -22,6 +23,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -45,6 +49,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_ASTNodeTypeCleaner.cpp b/tests/test_ASTNodeTypeCleaner.cpp index e2ae69b4695d785745dce55a5dc1bf617b980773..e1abf88d600d45ba9ae77d3c25b4904adf6992d4 100644 --- a/tests/test_ASTNodeTypeCleaner.cpp +++ b/tests/test_ASTNodeTypeCleaner.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> @@ -15,6 +16,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp b/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp index ae51cf9a0d77b642f7e3b9f6cdcd1c00d59c492a..d320aee0257de0e2cabf852ee9426885c755e7e4 100644 --- a/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp +++ b/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -22,6 +23,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -41,6 +45,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ \ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ diff --git a/tests/test_ASTSymbolTableBuilder.cpp b/tests/test_ASTSymbolTableBuilder.cpp index 581bd1fae668aef70e17544393f7632fe564e1fc..e336d7841a3fbc54903a16584d0eb224252b464d 100644 --- a/tests/test_ASTSymbolTableBuilder.cpp +++ b/tests/test_ASTSymbolTableBuilder.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> #include <language/utils/ParseError.hpp> @@ -78,7 +79,7 @@ let n:N, n = a; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTSymbolTableBuilder{*ast}, "undefined symbol 'a'"); } SECTION("Re-declared symbol") @@ -91,7 +92,7 @@ let n:N, n = 1; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTSymbolTableBuilder{*ast}, "symbol 'n' was already defined!"); } SECTION("Re-declared symbol (function)") @@ -104,7 +105,36 @@ let f : R -> R, x -> 1; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTSymbolTableBuilder{*ast}, "symbol 'f' was already defined!"); + } + + SECTION("Re-declared symbol (builtin function)") + { + std::string_view data = R"( +import math; +let cos:N; +)"; + + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTModulesImporter{*ast}; + + REQUIRE_THROWS_WITH(ASTSymbolTableBuilder{*ast}, "symbol 'cos' already denotes a builtin function!"); + } + + SECTION("Re-declared symbol (builtin function) 2") + { + std::string_view data = R"( +import math; +let cos: R -> R, x->2*x; +)"; + + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTModulesImporter{*ast}; + + // REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTSymbolTableBuilder{*ast}, "symbol 'cos' already denotes a builtin function!"); } SECTION("Re-declared parameter (function)") @@ -116,7 +146,7 @@ let f : R*R*N -> R, (x,y,x) -> 1; string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); - REQUIRE_THROWS_AS(ASTSymbolTableBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTSymbolTableBuilder{*ast}, "symbol 'x' was already defined!"); } } } diff --git a/tests/test_AffectationProcessor.cpp b/tests/test_AffectationProcessor.cpp index ec130a135320bf1ceba5ee1ff532b57437296d2e..b6f73afdb4ec60f6b754eea3eafcbe2bf0ce0759 100644 --- a/tests/test_AffectationProcessor.cpp +++ b/tests/test_AffectationProcessor.cpp @@ -482,6 +482,13 @@ TEST_CASE("AffectationProcessor", "[language]") CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 3.2;", "undefined affectation type: R^2 = R"); CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 2.3;", "undefined affectation type: R^3 = R"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^1; let y : R^1x1, y = 1; x = y;", + "undefined affectation type: R^1 = R^1x1"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2; let y : R^2x2, y = (1,2,4,4); x = y;", + "undefined affectation type: R^2 = R^2x2"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3; let y : R^3x3, y = (1,2,3,4,5,6,7,8,9); x = y;", + "undefined affectation type: R^3 = R^3x3"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 4;", "invalid integral value (0 is the solely valid value)"); CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 3;", "invalid integral value (0 is the solely valid value)"); @@ -499,6 +506,65 @@ TEST_CASE("AffectationProcessor", "[language]") "undefined affectation type: R^1 = R^3"); CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 0; let y : R^2, y = x;", "undefined affectation type: R^2 = R^3"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^1, x = (1,2);", "undefined affectation type: R^1 = list"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = (1,2,3);", + "incompatible dimensions in affectation: expecting 2, but provided 3"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = (1,2);", + "incompatible dimensions in affectation: expecting 3, but provided 2"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = (1,2,3,4);", + "incompatible dimensions in affectation: expecting 3, but provided 4"); + } + + SECTION("-> R^nxn") + { + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2, x = \"foobar\";", "undefined affectation type: R^2x2 = string"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3, x = \"foobar\";", "undefined affectation type: R^3x3 = string"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2, x = 3.2;", "undefined affectation type: R^2x2 = R"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3, x = 2.3;", "undefined affectation type: R^3x3 = R"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^1x1; let y : R^1, y = 1; x = y;", + "undefined affectation type: R^1x1 = R^1"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2; let y : R^2, y = (1,2); x = y;", + "undefined affectation type: R^2x2 = R^2"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3; let y : R^3, y = (1,2,3); x = y;", + "undefined affectation type: R^3x3 = R^3"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2; x = 3.2;", "undefined affectation type: R^2x2 = R"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3; x = 2.3;", "undefined affectation type: R^3x3 = R"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2, x = 4;", "invalid integral value (0 is the solely valid value)"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3, x = 3;", "invalid integral value (0 is the solely valid value)"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^1x1, x = 0; let y : R^2x2, y = x;", + "undefined affectation type: R^2x2 = R^1x1"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^1x1, x = 0; let y : R^3x3, y = x;", + "undefined affectation type: R^3x3 = R^1x1"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2, x = 0; let y : R^1x1, y = x;", + "undefined affectation type: R^1x1 = R^2x2"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2, x = 0; let y : R^3x3, y = x;", + "undefined affectation type: R^3x3 = R^2x2"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3, x = 0; let y : R^1x1, y = x;", + "undefined affectation type: R^1x1 = R^3x3"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3, x = 0; let y : R^2x2, y = x;", + "undefined affectation type: R^2x2 = R^3x3"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^1x1, x = (1,2);", "undefined affectation type: R^1x1 = list"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2, x = (1,2,3);", + "incompatible dimensions in affectation: expecting 4, but provided 3"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2, x = (1,2,3,4,5);", + "incompatible dimensions in affectation: expecting 4, but provided 5"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3, x = (1,2,3,4,5,6,7,8);", + "incompatible dimensions in affectation: expecting 9, but provided 8"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3, x = (1,2,3,4,5,6,7,8,9,10);", + "incompatible dimensions in affectation: expecting 9, but provided 10"); } } } diff --git a/tests/test_AffectationToStringProcessor.cpp b/tests/test_AffectationToStringProcessor.cpp index a793a5cd82a6bd53d7e45369e5e9ebae9044745c..01c7ba7b938945dc9f929f602a3fe071b052379c 100644 --- a/tests/test_AffectationToStringProcessor.cpp +++ b/tests/test_AffectationToStringProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> @@ -20,6 +21,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_AffectationToTupleProcessor.cpp b/tests/test_AffectationToTupleProcessor.cpp index df2de1d07c100154a9728a1c68197121fd18f4dd..650e60ca61bb6bc1d8b2e239c9e4c67713c3212a 100644 --- a/tests/test_AffectationToTupleProcessor.cpp +++ b/tests/test_AffectationToTupleProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> @@ -20,6 +21,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_Array.cpp b/tests/test_Array.cpp index ac61be590dbfafe8bee60a216eb3ba01819b6279..23d63a4a2dd769c679811ddc00265ba4aa615dac 100644 --- a/tests/test_Array.cpp +++ b/tests/test_Array.cpp @@ -105,6 +105,23 @@ TEST_CASE("Array", "[utils]") REQUIRE(((c[0] == 2) and (c[1] == 2) and (c[2] == 2) and (c[3] == 2) and (c[4] == 2) and (c[5] == 2) and (c[6] == 2) and (c[7] == 2) and (c[8] == 2) and (c[9] == 2))); + + Array<int> d{a.size()}; + copy_to(a, d); + + REQUIRE(((d[0] == 0) and (d[1] == 2) and (d[2] == 4) and (d[3] == 6) and (d[4] == 8) and (d[5] == 10) and + (d[6] == 12) and (d[7] == 14) and (d[8] == 16) and (d[9] == 18))); + + REQUIRE(((c[0] == 2) and (c[1] == 2) and (c[2] == 2) and (c[3] == 2) and (c[4] == 2) and (c[5] == 2) and + (c[6] == 2) and (c[7] == 2) and (c[8] == 2) and (c[9] == 2))); + + copy_to(c, d); + + REQUIRE(((a[0] == 0) and (a[1] == 2) and (a[2] == 4) and (a[3] == 6) and (a[4] == 8) and (a[5] == 10) and + (a[6] == 12) and (a[7] == 14) and (a[8] == 16) and (a[9] == 18))); + + REQUIRE(((d[0] == 2) and (d[1] == 2) and (d[2] == 2) and (d[3] == 2) and (d[4] == 2) and (d[5] == 2) and + (d[6] == 2) and (d[7] == 2) and (d[8] == 2) and (d[9] == 2))); } SECTION("checking for std container conversion") @@ -220,5 +237,11 @@ TEST_CASE("Array", "[utils]") { REQUIRE_THROWS_AS(a[10], AssertError); } + + SECTION("invalid copy_to") + { + Array<int> b{2 * a.size()}; + REQUIRE_THROWS_AS(copy_to(a, b), AssertError); + } #endif // NDEBUG } diff --git a/tests/test_BinaryExpressionProcessor_utils.hpp b/tests/test_BinaryExpressionProcessor_utils.hpp index 7b32bff86087bf871eb70decafe952f273991b65..c8e3440cfd75b1320c146d5eb342a2a5d343a20f 100644 --- a/tests/test_BinaryExpressionProcessor_utils.hpp +++ b/tests/test_BinaryExpressionProcessor_utils.hpp @@ -2,6 +2,7 @@ #define TEST_BINARY_EXPRESSION_PROCESSOR_UTILS_HPP #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -18,6 +19,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -46,6 +50,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ \ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ diff --git a/tests/test_BuiltinFunctionRegister.hpp b/tests/test_BuiltinFunctionRegister.hpp index e062fcd92222796da9071243bda7c3e5dd253e32..7c361c9df4a6e4c3071ccef00c070313dba2bb5b 100644 --- a/tests/test_BuiltinFunctionRegister.hpp +++ b/tests/test_BuiltinFunctionRegister.hpp @@ -7,6 +7,8 @@ #include <language/utils/TypeDescriptor.hpp> #include <utils/Exceptions.hpp> +#include <unordered_map> + template <> inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t"); @@ -66,7 +68,7 @@ class test_BuiltinFunctionRegister [](const TinyVector<3>& x) -> double { return x[0] + x[1] + x[2]; }))); m_name_builtin_function_map.insert( - std::make_pair("R3R2toR:R^3,R^2", + std::make_pair("R3R2toR:R^3*R^2", std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<3>, TinyVector<2>)>>( [](TinyVector<3> x, TinyVector<2> y) -> double { return x[0] * y[1] + (y[0] - x[2]) * x[1]; }))); @@ -159,6 +161,14 @@ class test_BuiltinFunctionRegister std::make_pair("tuple_R33ToR:(R^3x3...)", std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyMatrix<3>>)>>( [](const std::vector<TinyMatrix<3>>&) -> double { return 0; }))); + + m_name_builtin_function_map.insert( + std::make_pair("sum_vector:R*R^2", + std::make_shared< + BuiltinFunctionEmbedder<std::tuple<double, TinyVector<2>>(const double, const double)>>( + [](const double& x, const double& y) -> std::tuple<double, TinyVector<2>> { + return std::make_tuple(x + y, TinyVector<2>{x, y}); + }))); } void diff --git a/tests/test_ConcatExpressionProcessor.cpp b/tests/test_ConcatExpressionProcessor.cpp index eaa0f76f245ae0f14394396a6593f9118a2e879d..4c5e202b71a1b9630683145aa4ffb30863ce9a27 100644 --- a/tests/test_ConcatExpressionProcessor.cpp +++ b/tests/test_ConcatExpressionProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> @@ -20,6 +21,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_DiscreteFunctionDescriptorP0.cpp b/tests/test_DiscreteFunctionDescriptorP0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f80bd84e36ee1a5d18b1682ec2f2cbe35203d90 --- /dev/null +++ b/tests/test_DiscreteFunctionDescriptorP0.cpp @@ -0,0 +1,26 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <scheme/DiscreteFunctionDescriptorP0.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("DiscreteFunctionDescriptorP0", "[scheme]") +{ + SECTION("type") + { + DiscreteFunctionDescriptorP0 descriptor; + REQUIRE(descriptor.type() == DiscreteFunctionType::P0); + + { + auto copy = [](const DiscreteFunctionDescriptorP0& d) -> DiscreteFunctionDescriptorP0 { return d; }; + + DiscreteFunctionDescriptorP0 descriptor_copy{copy(descriptor)}; + REQUIRE(descriptor_copy.type() == DiscreteFunctionType::P0); + } + + DiscreteFunctionDescriptorP0 temp; + DiscreteFunctionDescriptorP0 descriptor_move{std::move(temp)}; + REQUIRE(descriptor_move.type() == DiscreteFunctionType::P0); + } +} diff --git a/tests/test_DiscreteFunctionDescriptorP0Vector.cpp b/tests/test_DiscreteFunctionDescriptorP0Vector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5caa63b236c3414aef6ee46668c73b0b0c3f6e3f --- /dev/null +++ b/tests/test_DiscreteFunctionDescriptorP0Vector.cpp @@ -0,0 +1,26 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <scheme/DiscreteFunctionDescriptorP0Vector.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("DiscreteFunctionDescriptorP0Vector", "[scheme]") +{ + SECTION("type") + { + DiscreteFunctionDescriptorP0Vector descriptor; + REQUIRE(descriptor.type() == DiscreteFunctionType::P0Vector); + + { + auto copy = [](const DiscreteFunctionDescriptorP0Vector& d) -> DiscreteFunctionDescriptorP0Vector { return d; }; + + DiscreteFunctionDescriptorP0Vector descriptor_copy{copy(descriptor)}; + REQUIRE(descriptor_copy.type() == DiscreteFunctionType::P0Vector); + } + + DiscreteFunctionDescriptorP0Vector temp; + DiscreteFunctionDescriptorP0Vector descriptor_move{std::move(temp)}; + REQUIRE(descriptor_move.type() == DiscreteFunctionType::P0Vector); + } +} diff --git a/tests/test_DiscreteFunctionP0.cpp b/tests/test_DiscreteFunctionP0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1fefcdc6ea1e50e4c48fdff2be95d737a118de5a --- /dev/null +++ b/tests/test_DiscreteFunctionP0.cpp @@ -0,0 +1,2376 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <scheme/DiscreteFunctionP0.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("DiscreteFunctionP0", "[scheme]") +{ + auto same_values = [](const auto& f, const auto& g) { + size_t number_of_cells = f.cellValues().numberOfItems(); + for (CellId cell_id = 0; cell_id < number_of_cells; ++cell_id) { + if (f[cell_id] != g[cell_id]) { + return false; + } + } + return true; + }; + + SECTION("constructors") + { + SECTION("1D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + + constexpr size_t Dimension = 1; + + DiscreteFunctionP0<Dimension, double> f{mesh}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0); + + REQUIRE(f.mesh().get() == mesh.get()); + + DiscreteFunctionP0 g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0); + + CellValue<TinyVector<Dimension>> h_values{mesh->connectivity()}; + h_values.fill(ZeroType{}); + + DiscreteFunctionP0 zero{mesh, [&] { + CellValue<TinyVector<Dimension>> cell_value{mesh->connectivity()}; + cell_value.fill(ZeroType{}); + return cell_value; + }()}; + + DiscreteFunctionP0 h{mesh, h_values}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_values)); + + DiscreteFunctionP0<Dimension, TinyVector<Dimension>> shallow_h{mesh}; + shallow_h = h; + + copy_to(MeshDataManager::instance().getMeshData(*mesh).xj(), h_values); + + REQUIRE(same_values(shallow_h, h_values)); + REQUIRE(same_values(h, h_values)); + REQUIRE(not same_values(h, zero)); + + DiscreteFunctionP0 moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_values)); + } + + SECTION("2D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh2D(); + + constexpr size_t Dimension = 2; + + DiscreteFunctionP0<Dimension, double> f{mesh}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0); + + REQUIRE(f.mesh().get() == mesh.get()); + + DiscreteFunctionP0 g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0); + + CellValue<TinyVector<Dimension>> h_values{mesh->connectivity()}; + h_values.fill(ZeroType{}); + + DiscreteFunctionP0 zero{mesh, [&] { + CellValue<TinyVector<Dimension>> cell_value{mesh->connectivity()}; + cell_value.fill(ZeroType{}); + return cell_value; + }()}; + + DiscreteFunctionP0 h{mesh, h_values}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_values)); + + DiscreteFunctionP0<Dimension, TinyVector<Dimension>> shallow_h{mesh}; + shallow_h = h; + + copy_to(MeshDataManager::instance().getMeshData(*mesh).xj(), h_values); + + REQUIRE(same_values(shallow_h, h_values)); + REQUIRE(same_values(h, h_values)); + REQUIRE(not same_values(h, zero)); + + DiscreteFunctionP0 moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_values)); + } + + SECTION("3D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh3D(); + + constexpr size_t Dimension = 3; + + DiscreteFunctionP0<Dimension, double> f{mesh}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0); + + REQUIRE(f.mesh().get() == mesh.get()); + + DiscreteFunctionP0 g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0); + + CellValue<TinyVector<Dimension>> h_values{mesh->connectivity()}; + h_values.fill(ZeroType{}); + + DiscreteFunctionP0 zero{mesh, [&] { + CellValue<TinyVector<Dimension>> cell_value{mesh->connectivity()}; + cell_value.fill(ZeroType{}); + return cell_value; + }()}; + + DiscreteFunctionP0 h{mesh, h_values}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_values)); + + DiscreteFunctionP0<Dimension, TinyVector<Dimension>> shallow_h{mesh}; + shallow_h = h; + + copy_to(MeshDataManager::instance().getMeshData(*mesh).xj(), h_values); + + REQUIRE(same_values(shallow_h, h_values)); + REQUIRE(same_values(h, h_values)); + REQUIRE(not same_values(h, zero)); + + DiscreteFunctionP0 moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_values)); + } + } + + SECTION("fill") + { + auto all_values_equal = [](const auto& f, const auto& g) { + size_t number_of_cells = f.cellValues().numberOfItems(); + for (CellId cell_id = 0; cell_id < number_of_cells; ++cell_id) { + if (f[cell_id] != g) { + return false; + } + } + return true; + }; + + SECTION("1D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + constexpr size_t Dimension = 1; + + DiscreteFunctionP0<Dimension, double> f{mesh}; + f.fill(3); + + REQUIRE(all_values_equal(f, 3)); + + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + v.fill(TinyVector<3>{1, 2, 3}); + + REQUIRE(all_values_equal(v, TinyVector<3>{1, 2, 3})); + + DiscreteFunctionP0<Dimension, TinyMatrix<3>> A{mesh}; + A.fill(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9}); + + REQUIRE(all_values_equal(A, TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); + } + + SECTION("2D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh2D(); + constexpr size_t Dimension = 2; + + DiscreteFunctionP0<Dimension, double> f{mesh}; + f.fill(3); + + REQUIRE(all_values_equal(f, 3)); + + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + v.fill(TinyVector<3>{1, 2, 3}); + + REQUIRE(all_values_equal(v, TinyVector<3>{1, 2, 3})); + + DiscreteFunctionP0<Dimension, TinyMatrix<3>> A{mesh}; + A.fill(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9}); + + REQUIRE(all_values_equal(A, TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); + } + + SECTION("3D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh3D(); + constexpr size_t Dimension = 3; + + DiscreteFunctionP0<Dimension, double> f{mesh}; + f.fill(3); + + REQUIRE(all_values_equal(f, 3)); + + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + v.fill(TinyVector<3>{1, 2, 3}); + + REQUIRE(all_values_equal(v, TinyVector<3>{1, 2, 3})); + + DiscreteFunctionP0<Dimension, TinyMatrix<3>> A{mesh}; + A.fill(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9}); + + REQUIRE(all_values_equal(A, TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); + } + } + + SECTION("copies") + { + auto all_values_equal = [](const auto& f, const auto& g) { + size_t number_of_cells = f.cellValues().numberOfItems(); + for (CellId cell_id = 0; cell_id < number_of_cells; ++cell_id) { + if (f[cell_id] != g) { + return false; + } + } + return true; + }; + + SECTION("1D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + + constexpr size_t Dimension = 1; + + SECTION("scalar") + { + const size_t value = parallel::rank() + 1; + const size_t zero = 0; + + DiscreteFunctionP0<Dimension, size_t> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0 g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0<Dimension, const size_t> h = copy(f); + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + } + + SECTION("vector") + { + const TinyVector<2, size_t> value{parallel::rank() + 1, 3}; + const TinyVector<2, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyVector<2, size_t>> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0 g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0<Dimension, const TinyVector<2, size_t>> h = copy(f); + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + } + + SECTION("matrix") + { + const TinyMatrix<3, size_t> value{1, 2, 3, 4, 5, 6, 7, 8, 9}; + const TinyMatrix<3, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyMatrix<3, size_t>> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0 g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0<Dimension, const TinyMatrix<3, size_t>> h = copy(f); + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + } + } + + SECTION("2D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh2D(); + + constexpr size_t Dimension = 2; + + SECTION("scalar") + { + const size_t value = parallel::rank() + 1; + const size_t zero = 0; + + DiscreteFunctionP0<Dimension, size_t> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0 g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0<Dimension, const size_t> h = copy(f); + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + } + + SECTION("vector") + { + const TinyVector<2, size_t> value{parallel::rank() + 1, 3}; + const TinyVector<2, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyVector<2, size_t>> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0 g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0<Dimension, const TinyVector<2, size_t>> h = copy(f); + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + } + + SECTION("matrix") + { + const TinyMatrix<3, size_t> value{1, 2, 3, 4, 5, 6, 7, 8, 9}; + const TinyMatrix<3, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyMatrix<3, size_t>> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0 g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0<Dimension, const TinyMatrix<3, size_t>> h = copy(f); + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + } + } + + SECTION("3D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh3D(); + + constexpr size_t Dimension = 3; + + SECTION("scalar") + { + const size_t value = parallel::rank() + 1; + const size_t zero = 0; + + DiscreteFunctionP0<Dimension, size_t> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0 g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0<Dimension, const size_t> h = copy(f); + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + } + + SECTION("vector") + { + const TinyVector<2, size_t> value{parallel::rank() + 1, 3}; + const TinyVector<2, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyVector<2, size_t>> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0 g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0<Dimension, const TinyVector<2, size_t>> h = copy(f); + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + } + + SECTION("matrix") + { + const TinyMatrix<3, size_t> value{1, 2, 3, 4, 5, 6, 7, 8, 9}; + const TinyMatrix<3, size_t> zero{ZeroType{}}; + DiscreteFunctionP0<Dimension, TinyMatrix<3, size_t>> f{mesh}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0 g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0<Dimension, const TinyMatrix<3, size_t>> h = copy(f); + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + } + } + } + + SECTION("unary operators") + { + SECTION("1D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + + constexpr size_t Dimension = 1; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("unary minus") + { + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + f[cell_id] = 2 * x + 1; + }); + + DiscreteFunctionP0<Dimension, const double> const_f = f; + + Array<double> minus_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { minus_values[cell_id] = -f[cell_id]; }); + + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); + + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + + Array<TinyVector<VectorDimension>> minus_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { minus_values[cell_id] = -f[cell_id]; }); + + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; + f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; + }); + + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + + Array<TinyMatrix<MatrixDimension>> minus_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { minus_values[cell_id] = -f[cell_id]; }); + + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); + } + } + } + } + + SECTION("binary operators") + { + SECTION("1D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + + constexpr size_t Dimension = 1; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("inner operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + f[cell_id] = 2 * x + 1; + }); + + DiscreteFunctionP0<Dimension, double> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + g[cell_id] = std::abs((x + 1) * (x - 2)) + 1; + }); + + DiscreteFunctionP0<Dimension, const double> const_f = f; + DiscreteFunctionP0<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + + SECTION("ratio") + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / g[cell_id]; }); + + REQUIRE(same_values(f / g, ratio_values)); + REQUIRE(same_values(const_f / g, ratio_values)); + REQUIRE(same_values(f / const_g, ratio_values)); + REQUIRE(same_values(const_f / const_g, ratio_values)); + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{3 * x + 1, 2 + x}; + g[cell_id] = X; + }); + + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_g{g}; + + SECTION("sum") + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; + f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; + }); + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{3 * x + 1, 2 + x, 1 - 2 * x, 2 * x * x}; + g[cell_id] = A; + }); + + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_g{g}; + + SECTION("sum") + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + } + } + + SECTION("external operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + f[cell_id] = std::abs(2 * x) + 1; + }); + + const double a = 3; + + DiscreteFunctionP0<Dimension, const double> const_f = f; + + SECTION("sum") + { + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = a + f[cell_id]; }); + + REQUIRE(same_values(a + f, sum_values)); + REQUIRE(same_values(a + const_f, sum_values)); + } + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + a; }); + + REQUIRE(same_values(f + a, sum_values)); + REQUIRE(same_values(const_f + a, sum_values)); + } + } + + SECTION("difference") + { + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = a - f[cell_id]; }); + REQUIRE(same_values(a - f, difference_values)); + REQUIRE(same_values(a - const_f, difference_values)); + } + + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - a; }); + REQUIRE(same_values(f - a, difference_values)); + REQUIRE(same_values(const_f - a, difference_values)); + } + } + + SECTION("product") + { + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * a; }); + + REQUIRE(same_values(f * a, product_values)); + REQUIRE(same_values(const_f * a, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + const TinyVector<3> v{1, 2, 3}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + v[cell_id] = TinyVector<3>{x, 2 * x, 1 - x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v[cell_id]; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + const TinyMatrix<2> A{1, 2, 3, 4}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<2>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * M[cell_id]; }); + + REQUIRE(same_values(f * M, product_values)); + REQUIRE(same_values(const_f * M, product_values)); + } + } + + SECTION("ratio") + { + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = a / f[cell_id]; }); + + REQUIRE(same_values(a / f, ratio_values)); + REQUIRE(same_values(a / const_f, ratio_values)); + } + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / a; }); + + REQUIRE(same_values(f / a, ratio_values)); + REQUIRE(same_values(const_f / a, ratio_values)); + } + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); + + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + + SECTION("sum") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = v + f[cell_id]; }); + + REQUIRE(same_values(v + f, sum_values)); + REQUIRE(same_values(v + const_f, sum_values)); + } + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + v; }); + + REQUIRE(same_values(f + v, sum_values)); + REQUIRE(same_values(const_f + v, sum_values)); + } + } + + SECTION("difference") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = v - f[cell_id]; }); + + REQUIRE(same_values(v - f, difference_values)); + REQUIRE(same_values(v - const_f, difference_values)); + } + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - v; }); + + REQUIRE(same_values(f - v, difference_values)); + REQUIRE(same_values(const_f - v, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<VectorDimension> A{1, 2, 3, 4}; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<VectorDimension>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = M[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(M * f, product_values)); + REQUIRE(same_values(M * const_f, product_values)); + } + } + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> X{x, 2 - x, x * x, x * 3}; + f[cell_id] = 2 * X + TinyMatrix<2>{1, 2, 3, 4}; + }); + + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + + SECTION("sum") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = A + f[cell_id]; }); + + REQUIRE(same_values(A + f, sum_values)); + REQUIRE(same_values(A + const_f, sum_values)); + } + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + A; }); + + REQUIRE(same_values(f + A, sum_values)); + REQUIRE(same_values(const_f + A, sum_values)); + } + } + + SECTION("difference") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = A - f[cell_id]; }); + + REQUIRE(same_values(A - f, difference_values)); + REQUIRE(same_values(A - const_f, difference_values)); + } + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - A; }); + + REQUIRE(same_values(f - A, difference_values)); + REQUIRE(same_values(const_f - A, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + } + } + } + } + + SECTION("2D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh2D(); + + constexpr size_t Dimension = 2; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("inner operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + f[cell_id] = 2 * x + y + 1; + }); + + DiscreteFunctionP0<Dimension, double> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + g[cell_id] = std::abs((x + 1) * (x - 2) + y * (1 + y)) + 1; + }); + + DiscreteFunctionP0<Dimension, const double> const_f = f; + DiscreteFunctionP0<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + + SECTION("ratio") + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / g[cell_id]; }); + + REQUIRE(same_values(f / g, ratio_values)); + REQUIRE(same_values(const_f / g, ratio_values)); + REQUIRE(same_values(f / const_g, ratio_values)); + REQUIRE(same_values(const_f / const_g, ratio_values)); + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{3 * x + 1, 2 + x}; + g[cell_id] = X; + }); + + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_g{g}; + + SECTION("sum") + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; + f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; + }); + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{3 * x + 1, 2 + x, 1 - 2 * x, 2 * x * x}; + g[cell_id] = A; + }); + + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_g{g}; + + SECTION("sum") + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + } + } + + SECTION("external operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + f[cell_id] = std::abs(2 * x + y) + 1; + }); + + const double a = 3; + + DiscreteFunctionP0<Dimension, const double> const_f = f; + + SECTION("sum") + { + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = a + f[cell_id]; }); + + REQUIRE(same_values(a + f, sum_values)); + REQUIRE(same_values(a + const_f, sum_values)); + } + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + a; }); + + REQUIRE(same_values(f + a, sum_values)); + REQUIRE(same_values(const_f + a, sum_values)); + } + } + + SECTION("difference") + { + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = a - f[cell_id]; }); + REQUIRE(same_values(a - f, difference_values)); + REQUIRE(same_values(a - const_f, difference_values)); + } + + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - a; }); + REQUIRE(same_values(f - a, difference_values)); + REQUIRE(same_values(const_f - a, difference_values)); + } + } + + SECTION("product") + { + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * a; }); + + REQUIRE(same_values(f * a, product_values)); + REQUIRE(same_values(const_f * a, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + const TinyVector<3> v{1, 2, 3}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + v[cell_id] = TinyVector<3>{x, 2 * x, 1 - x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v[cell_id]; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + const TinyMatrix<2> A{1, 2, 3, 4}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<2>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * M[cell_id]; }); + + REQUIRE(same_values(f * M, product_values)); + REQUIRE(same_values(const_f * M, product_values)); + } + } + + SECTION("ratio") + { + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = a / f[cell_id]; }); + + REQUIRE(same_values(a / f, ratio_values)); + REQUIRE(same_values(a / const_f, ratio_values)); + } + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / a; }); + + REQUIRE(same_values(f / a, ratio_values)); + REQUIRE(same_values(const_f / a, ratio_values)); + } + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const TinyVector<VectorDimension> X{x + y, 2 - x * y}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); + + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + + SECTION("sum") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = v + f[cell_id]; }); + + REQUIRE(same_values(v + f, sum_values)); + REQUIRE(same_values(v + const_f, sum_values)); + } + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + v; }); + + REQUIRE(same_values(f + v, sum_values)); + REQUIRE(same_values(const_f + v, sum_values)); + } + } + + SECTION("difference") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = v - f[cell_id]; }); + + REQUIRE(same_values(v - f, difference_values)); + REQUIRE(same_values(v - const_f, difference_values)); + } + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - v; }); + + REQUIRE(same_values(f - v, difference_values)); + REQUIRE(same_values(const_f - v, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<VectorDimension> A{1, 2, 3, 4}; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<VectorDimension>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = M[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(M * f, product_values)); + REQUIRE(same_values(M * const_f, product_values)); + } + } + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const TinyMatrix<MatrixDimension> X{x, 2 - y, x * y, y * 3}; + f[cell_id] = 2 * X + TinyMatrix<2>{1, 2, 3, 4}; + }); + + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + + SECTION("sum") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = A + f[cell_id]; }); + + REQUIRE(same_values(A + f, sum_values)); + REQUIRE(same_values(A + const_f, sum_values)); + } + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + A; }); + + REQUIRE(same_values(f + A, sum_values)); + REQUIRE(same_values(const_f + A, sum_values)); + } + } + + SECTION("difference") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = A - f[cell_id]; }); + + REQUIRE(same_values(A - f, difference_values)); + REQUIRE(same_values(A - const_f, difference_values)); + } + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - A; }); + + REQUIRE(same_values(f - A, difference_values)); + REQUIRE(same_values(const_f - A, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + } + } + } + } + + SECTION("3D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh3D(); + + constexpr size_t Dimension = 3; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("inner operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + f[cell_id] = 2 * x + y - z; + }); + + DiscreteFunctionP0<Dimension, double> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + g[cell_id] = std::abs((x + 1) * (x - 2) + y * (1 + y) + 2 * z) + 1; + }); + + DiscreteFunctionP0<Dimension, const double> const_f = f; + DiscreteFunctionP0<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + + SECTION("ratio") + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / g[cell_id]; }); + + REQUIRE(same_values(f / g, ratio_values)); + REQUIRE(same_values(const_f / g, ratio_values)); + REQUIRE(same_values(f / const_g, ratio_values)); + REQUIRE(same_values(const_f / const_g, ratio_values)); + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{x, 2 - x}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyVector<VectorDimension> X{3 * x + 1, 2 + x}; + g[cell_id] = X; + }); + + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_g{g}; + + SECTION("sum") + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{x, 2 - x, 2 * x, x * x - 3}; + f[cell_id] = 2 * A + TinyMatrix<2>{1, 2, 3, 4}; + }); + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> g{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const TinyMatrix<MatrixDimension> A{3 * x + 1, 2 + x, 1 - 2 * x, 2 * x * x}; + g[cell_id] = A; + }); + + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_g{g}; + + SECTION("sum") + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + g[cell_id]; }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - g[cell_id]; }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + + SECTION("product") + { + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * g[cell_id]; }); + + REQUIRE(same_values(f * g, product_values)); + REQUIRE(same_values(const_f * g, product_values)); + REQUIRE(same_values(f * const_g, product_values)); + REQUIRE(same_values(const_f * const_g, product_values)); + } + } + } + + SECTION("external operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0<Dimension, double> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + f[cell_id] = std::abs(2 * x + y * z) + 1; + }); + + const double a = 3; + + DiscreteFunctionP0<Dimension, const double> const_f = f; + + SECTION("sum") + { + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = a + f[cell_id]; }); + + REQUIRE(same_values(a + f, sum_values)); + REQUIRE(same_values(a + const_f, sum_values)); + } + { + Array<double> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + a; }); + + REQUIRE(same_values(f + a, sum_values)); + REQUIRE(same_values(const_f + a, sum_values)); + } + } + + SECTION("difference") + { + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = a - f[cell_id]; }); + REQUIRE(same_values(a - f, difference_values)); + REQUIRE(same_values(a - const_f, difference_values)); + } + + { + Array<double> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - a; }); + REQUIRE(same_values(f - a, difference_values)); + REQUIRE(same_values(const_f - a, difference_values)); + } + } + + SECTION("product") + { + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + { + Array<double> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * a; }); + + REQUIRE(same_values(f * a, product_values)); + REQUIRE(same_values(const_f * a, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + const TinyVector<3> v{1, 2, 3}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyVector<3>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyVector<3>> v{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + v[cell_id] = TinyVector<3>{x, 2 * x, 1 - x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * v[cell_id]; }); + + REQUIRE(same_values(f * v, product_values)); + REQUIRE(same_values(const_f * v, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + const TinyMatrix<2> A{1, 2, 3, 4}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + + { + Array<TinyMatrix<2>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<2>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * M[cell_id]; }); + + REQUIRE(same_values(f * M, product_values)); + REQUIRE(same_values(const_f * M, product_values)); + } + } + + SECTION("ratio") + { + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = a / f[cell_id]; }); + + REQUIRE(same_values(a / f, ratio_values)); + REQUIRE(same_values(a / const_f, ratio_values)); + } + { + Array<double> ratio_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { ratio_values[cell_id] = f[cell_id] / a; }); + + REQUIRE(same_values(f / a, ratio_values)); + REQUIRE(same_values(const_f / a, ratio_values)); + } + } + } + + SECTION("vector functions") + { + constexpr std::uint64_t VectorDimension = 2; + + DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + const TinyVector<VectorDimension> X{x + y - z, 2 - x * y}; + f[cell_id] = 2 * X + TinyVector<2>{1, 2}; + }); + + DiscreteFunctionP0<Dimension, const TinyVector<VectorDimension>> const_f = f; + + SECTION("sum") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = v + f[cell_id]; }); + + REQUIRE(same_values(v + f, sum_values)); + REQUIRE(same_values(v + const_f, sum_values)); + } + { + Array<TinyVector<VectorDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + v; }); + + REQUIRE(same_values(f + v, sum_values)); + REQUIRE(same_values(const_f + v, sum_values)); + } + } + + SECTION("difference") + { + const TinyVector<VectorDimension> v{1, 2}; + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = v - f[cell_id]; }); + + REQUIRE(same_values(v - f, difference_values)); + REQUIRE(same_values(v - const_f, difference_values)); + } + { + Array<TinyVector<VectorDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - v; }); + + REQUIRE(same_values(f - v, difference_values)); + REQUIRE(same_values(const_f - v, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<VectorDimension> A{1, 2, 3, 4}; + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + Array<TinyVector<VectorDimension>> product_values{mesh->numberOfCells()}; + DiscreteFunctionP0<Dimension, TinyMatrix<VectorDimension>> M{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + M[cell_id] = TinyMatrix<2>{x, 2 * x, 1 - x, 2 - x * x}; + }); + + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = M[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(M * f, product_values)); + REQUIRE(same_values(M * const_f, product_values)); + } + } + } + + SECTION("matrix functions") + { + constexpr std::uint64_t MatrixDimension = 2; + + DiscreteFunctionP0<Dimension, TinyMatrix<MatrixDimension>> f{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + const TinyMatrix<MatrixDimension> X{x, 2 - y, x * y, y * z + 3}; + f[cell_id] = 2 * X + TinyMatrix<2>{1, 2, 3, 4}; + }); + + DiscreteFunctionP0<Dimension, const TinyMatrix<MatrixDimension>> const_f = f; + + SECTION("sum") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = A + f[cell_id]; }); + + REQUIRE(same_values(A + f, sum_values)); + REQUIRE(same_values(A + const_f, sum_values)); + } + { + Array<TinyMatrix<MatrixDimension>> sum_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { sum_values[cell_id] = f[cell_id] + A; }); + + REQUIRE(same_values(f + A, sum_values)); + REQUIRE(same_values(const_f + A, sum_values)); + } + } + + SECTION("difference") + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = A - f[cell_id]; }); + + REQUIRE(same_values(A - f, difference_values)); + REQUIRE(same_values(A - const_f, difference_values)); + } + { + Array<TinyMatrix<MatrixDimension>> difference_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { difference_values[cell_id] = f[cell_id] - A; }); + + REQUIRE(same_values(f - A, difference_values)); + REQUIRE(same_values(const_f - A, difference_values)); + } + } + + SECTION("product") + { + { + const double a = 2.3; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x * x - 1; + }); + + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), + PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = a[cell_id] * f[cell_id]; }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = A * f[cell_id]; }); + + REQUIRE(same_values(A * f, product_values)); + REQUIRE(same_values(A * const_f, product_values)); + } + + { + const TinyMatrix<MatrixDimension> A{1, 2, 3, 4}; + Array<TinyMatrix<MatrixDimension>> product_values{mesh->numberOfCells()}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { product_values[cell_id] = f[cell_id] * A; }); + + REQUIRE(same_values(f * A, product_values)); + REQUIRE(same_values(const_f * A, product_values)); + } + } + } + } + } + } + +#ifndef NDEBUG + SECTION("error") + { + SECTION("different meshes") + { + SECTION("1D") + { + constexpr size_t Dimension = 1; + + std::shared_ptr mesh_1 = MeshDataBaseForTests::get().cartesianMesh1D(); + std::shared_ptr mesh_2 = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh_1->shared_connectivity(), mesh_1->xr()); + + DiscreteFunctionP0<Dimension, double> f1{mesh_1}; + DiscreteFunctionP0<Dimension, double> f2{mesh_2}; + + REQUIRE_THROWS_AS(f1 = f2, AssertError); + REQUIRE_THROWS_AS(copy_to(f1, f2), AssertError); + REQUIRE_THROWS_AS(f1 + f2, AssertError); + REQUIRE_THROWS_AS(f1 - f2, AssertError); + REQUIRE_THROWS_AS(f1 * f2, AssertError); + REQUIRE_THROWS_AS(f1 / f2, AssertError); + } + + SECTION("2D") + { + constexpr size_t Dimension = 2; + + std::shared_ptr mesh_1 = MeshDataBaseForTests::get().cartesianMesh2D(); + std::shared_ptr mesh_2 = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh_1->shared_connectivity(), mesh_1->xr()); + + DiscreteFunctionP0<Dimension, double> f1{mesh_1}; + DiscreteFunctionP0<Dimension, double> f2{mesh_2}; + + REQUIRE_THROWS_AS(f1 = f2, AssertError); + REQUIRE_THROWS_AS(copy_to(f1, f2), AssertError); + REQUIRE_THROWS_AS(f1 + f2, AssertError); + REQUIRE_THROWS_AS(f1 - f2, AssertError); + REQUIRE_THROWS_AS(f1 * f2, AssertError); + REQUIRE_THROWS_AS(f1 / f2, AssertError); + } + + SECTION("3D") + { + constexpr size_t Dimension = 3; + + std::shared_ptr mesh_1 = MeshDataBaseForTests::get().cartesianMesh3D(); + std::shared_ptr mesh_2 = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh_1->shared_connectivity(), mesh_1->xr()); + + DiscreteFunctionP0<Dimension, double> f1{mesh_1}; + DiscreteFunctionP0<Dimension, double> f2{mesh_2}; + + REQUIRE_THROWS_AS(f1 = f2, AssertError); + REQUIRE_THROWS_AS(copy_to(f1, f2), AssertError); + REQUIRE_THROWS_AS(f1 + f2, AssertError); + REQUIRE_THROWS_AS(f1 - f2, AssertError); + REQUIRE_THROWS_AS(f1 * f2, AssertError); + REQUIRE_THROWS_AS(f1 / f2, AssertError); + } + } + } +#endif // NDEBUG +} diff --git a/tests/test_DiscreteFunctionP0Vector.cpp b/tests/test_DiscreteFunctionP0Vector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c004ba5732c41dce1af56d3074b9c038b3a1bf8c --- /dev/null +++ b/tests/test_DiscreteFunctionP0Vector.cpp @@ -0,0 +1,845 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <scheme/DiscreteFunctionP0Vector.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("DiscreteFunctionP0Vector", "[scheme]") +{ + auto same_values = [](const auto& f, const auto& g) { + const size_t number_of_cells = f.cellArrays().numberOfItems(); + const size_t size_of_arrays = f.cellArrays().sizeOfArrays(); + for (CellId cell_id = 0; cell_id < number_of_cells; ++cell_id) { + for (size_t i = 0; i < size_of_arrays; ++i) { + if (f[cell_id][i] != g[cell_id][i]) { + return false; + } + } + } + return true; + }; + + SECTION("constructors") + { + SECTION("1D") + { + const size_t size = 3; + + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + constexpr size_t Dimension = 1; + + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(f.size() == size); + + REQUIRE(f.mesh().get() == mesh.get()); + + DiscreteFunctionP0Vector g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(g.size() == size); + + CellArray<double> h_arrays{mesh->connectivity(), size}; + h_arrays.fill(0); + + DiscreteFunctionP0Vector zero{mesh, [&] { + CellArray<double> cell_array{mesh->connectivity(), size}; + cell_array.fill(0); + return cell_array; + }()}; + + DiscreteFunctionP0Vector h{mesh, h_arrays}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_arrays)); + + h_arrays.fill(1); + + REQUIRE(same_values(h, h_arrays)); + REQUIRE(not same_values(h, zero)); + + DiscreteFunctionP0Vector moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_arrays)); + } + + SECTION("2D") + { + const size_t size = 3; + + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh2D(); + constexpr size_t Dimension = 2; + + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(f.size() == size); + + REQUIRE(f.mesh().get() == mesh.get()); + + DiscreteFunctionP0Vector g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(g.size() == size); + + CellArray<double> h_arrays{mesh->connectivity(), size}; + h_arrays.fill(0); + + DiscreteFunctionP0Vector zero{mesh, [&] { + CellArray<double> cell_array{mesh->connectivity(), size}; + cell_array.fill(0); + return cell_array; + }()}; + + DiscreteFunctionP0Vector h{mesh, h_arrays}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_arrays)); + + h_arrays.fill(1); + + REQUIRE(same_values(h, h_arrays)); + REQUIRE(not same_values(h, zero)); + + DiscreteFunctionP0Vector moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_arrays)); + } + + SECTION("3D") + { + const size_t size = 2; + + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh3D(); + constexpr size_t Dimension = 3; + + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + REQUIRE(f.dataType() == ASTNodeDataType::double_t); + REQUIRE(f.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(f.size() == size); + + REQUIRE(f.mesh().get() == mesh.get()); + + DiscreteFunctionP0Vector g{f}; + REQUIRE(g.dataType() == ASTNodeDataType::double_t); + REQUIRE(g.descriptor().type() == DiscreteFunctionType::P0Vector); + REQUIRE(g.size() == size); + + CellArray<double> h_arrays{mesh->connectivity(), size}; + h_arrays.fill(0); + + DiscreteFunctionP0Vector zero{mesh, [&] { + CellArray<double> cell_array{mesh->connectivity(), size}; + cell_array.fill(0); + return cell_array; + }()}; + + DiscreteFunctionP0Vector h{mesh, h_arrays}; + REQUIRE(same_values(h, zero)); + REQUIRE(same_values(h, h_arrays)); + + h_arrays.fill(1); + + REQUIRE(same_values(h, h_arrays)); + REQUIRE(not same_values(h, zero)); + + DiscreteFunctionP0Vector moved_h{std::move(h)}; + REQUIRE(same_values(moved_h, h_arrays)); + } + } + + SECTION("fill") + { + auto all_values_equal = [](const auto& f, const auto& g) { + const size_t number_of_cells = f.cellArrays().numberOfItems(); + size_t size_of_arrays = f.cellArrays().sizeOfArrays(); + for (CellId cell_id = 0; cell_id < number_of_cells; ++cell_id) { + for (size_t i = 0; i < size_of_arrays; ++i) { + if (f[cell_id][i] != g) { + return false; + } + } + } + return true; + }; + + SECTION("1D") + { + const size_t size = 3; + + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + constexpr size_t Dimension = 1; + + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + f.fill(3); + + REQUIRE(all_values_equal(f, 3)); + } + + SECTION("2D") + { + const size_t size = 3; + + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh2D(); + constexpr size_t Dimension = 2; + + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + f.fill(2.3); + + REQUIRE(all_values_equal(f, 2.3)); + } + + SECTION("3D") + { + const size_t size = 2; + + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh3D(); + constexpr size_t Dimension = 3; + + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + f.fill(3.2); + + REQUIRE(all_values_equal(f, 3.2)); + } + } + + SECTION("copies") + { + auto all_values_equal = [](const auto& f, const auto& g) { + const size_t number_of_cells = f.cellArrays().numberOfItems(); + const size_t size_of_arrays = f.cellArrays().sizeOfArrays(); + + for (CellId cell_id = 0; cell_id < number_of_cells; ++cell_id) { + for (size_t i = 0; i < size_of_arrays; ++i) { + if (f[cell_id][i] != g) { + return false; + } + } + } + return true; + }; + + SECTION("1D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + + constexpr size_t Dimension = 1; + + const size_t size = 3; + const size_t value = parallel::rank() + 1; + const size_t zero = 0; + + DiscreteFunctionP0Vector<Dimension, size_t> f{mesh, size}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0Vector g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0Vector<Dimension, const size_t> h = copy(f); + + DiscreteFunctionP0Vector<Dimension, size_t> shallow_g{mesh, size}; + shallow_g = g; + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(shallow_g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(shallow_g, value)); + } + + SECTION("2D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh2D(); + + constexpr size_t Dimension = 2; + + const size_t size = 3; + const size_t value = parallel::rank() + 1; + const size_t zero = 0; + + DiscreteFunctionP0Vector<Dimension, size_t> f{mesh, size}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0Vector g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0Vector<Dimension, const size_t> h = copy(f); + + DiscreteFunctionP0Vector<Dimension, size_t> shallow_g{mesh, size}; + shallow_g = g; + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(shallow_g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(shallow_g, value)); + } + + SECTION("3D") + { + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh3D(); + + constexpr size_t Dimension = 3; + + const size_t size = 3; + const size_t value = parallel::rank() + 1; + const size_t zero = 0; + + DiscreteFunctionP0Vector<Dimension, size_t> f{mesh, size}; + f.fill(value); + + REQUIRE(all_values_equal(f, value)); + + DiscreteFunctionP0Vector g = copy(f); + f.fill(zero); + + REQUIRE(all_values_equal(f, zero)); + REQUIRE(all_values_equal(g, value)); + + copy_to(g, f); + g.fill(zero); + + DiscreteFunctionP0Vector<Dimension, const size_t> h = copy(f); + + DiscreteFunctionP0Vector<Dimension, size_t> shallow_g{mesh, size}; + shallow_g = g; + + REQUIRE(all_values_equal(f, value)); + REQUIRE(all_values_equal(g, zero)); + REQUIRE(all_values_equal(h, value)); + + copy_to(h, g); + + REQUIRE(all_values_equal(g, value)); + REQUIRE(all_values_equal(shallow_g, value)); + } + } + + SECTION("unary operators") + { + SECTION("1D") + { + const size_t size = 3; + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + + constexpr size_t Dimension = 1; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("unary minus") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + for (size_t i = 0; i < size; ++i) { + f[cell_id][i] = 2 * x + i; + } + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + + Table<double> minus_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + minus_values[cell_id][i] = -f[cell_id][i]; + } + }); + + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); + } + } + + SECTION("2D") + { + const size_t size = 3; + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh2D(); + + constexpr size_t Dimension = 2; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("unary minus") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + for (size_t i = 0; i < size; ++i) { + f[cell_id][i] = 2 * x + i * y; + } + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + + Table<double> minus_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + minus_values[cell_id][i] = -f[cell_id][i]; + } + }); + + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); + } + } + + SECTION("3D") + { + const size_t size = 2; + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh3D(); + + constexpr size_t Dimension = 3; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("unary minus") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + for (size_t i = 0; i < size; ++i) { + f[cell_id][i] = 2 * x + i * y - z; + } + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + + Table<double> minus_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + minus_values[cell_id][i] = -f[cell_id][i]; + } + }); + + REQUIRE(same_values(-f, minus_values)); + REQUIRE(same_values(-const_f, minus_values)); + } + } + } + + SECTION("binary operators") + { + SECTION("1D") + { + const size_t size = 3; + + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh1D(); + + constexpr size_t Dimension = 1; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("inner operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + f[cell_id][0] = 2 * x + 1; + f[cell_id][1] = x * x - 1; + f[cell_id][2] = 2 + x; + }); + + DiscreteFunctionP0Vector<Dimension, double> g{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + g[cell_id][0] = (x + 1) * (x - 2) + 1; + g[cell_id][1] = 3 * (x + 2) - 1; + g[cell_id][2] = (x + 3) * 5; + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + DiscreteFunctionP0Vector<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Table<double> sum_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + sum_values[cell_id][i] = f[cell_id][i] + g[cell_id][i]; + } + }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Table<double> difference_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + difference_values[cell_id][i] = f[cell_id][i] - g[cell_id][i]; + } + }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } + } + + SECTION("external operators") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + for (size_t i = 0; i < size; ++i) { + f[cell_id][i] = std::abs(2 * x) + i; + } + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + + SECTION("product") + { + SECTION("scalar lhs") + { + const double a = 3.2; + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + SECTION("DiscreteFunctionP0 lhs") + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + a[cell_id] = 2 * x + 1; + }); + + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a[cell_id] * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + + DiscreteFunctionP0<Dimension, const double> const_a = a; + REQUIRE(same_values(const_a * f, product_values)); + REQUIRE(same_values(const_a * const_f, product_values)); + } + } + } + } + + SECTION("2D") + { + const size_t size = 3; + + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh2D(); + + constexpr size_t Dimension = 2; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("inner operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + f[cell_id][0] = 2 * x + 1; + f[cell_id][1] = x * x - y; + f[cell_id][2] = 2 + x * y; + }); + + DiscreteFunctionP0Vector<Dimension, double> g{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + g[cell_id][0] = (x + 1) * (y - 2) + 1; + g[cell_id][1] = 3 * (x + 2) - y; + g[cell_id][2] = (x + 3) + 5 * y; + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + DiscreteFunctionP0Vector<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Table<double> sum_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + sum_values[cell_id][i] = f[cell_id][i] + g[cell_id][i]; + } + }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Table<double> difference_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + difference_values[cell_id][i] = f[cell_id][i] - g[cell_id][i]; + } + }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } + } + + SECTION("external operators") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + for (size_t i = 0; i < size; ++i) { + f[cell_id][i] = std::abs(2 * x) + i * y; + } + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + + SECTION("product") + { + SECTION("scalar lhs") + { + const double a = 3.2; + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + SECTION("DiscreteFunctionP0 lhs") + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + a[cell_id] = 2 * x + 1 - y; + }); + + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a[cell_id] * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + + DiscreteFunctionP0<Dimension, const double> const_a = a; + REQUIRE(same_values(const_a * f, product_values)); + REQUIRE(same_values(const_a * const_f, product_values)); + } + } + } + } + + SECTION("3D") + { + const size_t size = 2; + + std::shared_ptr mesh = MeshDataBaseForTests::get().cartesianMesh3D(); + + constexpr size_t Dimension = 3; + + auto xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + SECTION("inner operators") + { + SECTION("scalar functions") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + f[cell_id][0] = 2 * x * z + 1; + f[cell_id][1] = x * z - y; + }); + + DiscreteFunctionP0Vector<Dimension, double> g{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + g[cell_id][0] = (x + 1) * (y - 2) + 1 - z; + g[cell_id][1] = 3 * (x + 2) - y * z; + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + DiscreteFunctionP0Vector<Dimension, const double> const_g{g}; + + SECTION("sum") + { + Table<double> sum_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + sum_values[cell_id][i] = f[cell_id][i] + g[cell_id][i]; + } + }); + + REQUIRE(same_values(f + g, sum_values)); + REQUIRE(same_values(const_f + g, sum_values)); + REQUIRE(same_values(f + const_g, sum_values)); + REQUIRE(same_values(const_f + const_g, sum_values)); + } + + SECTION("difference") + { + Table<double> difference_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + difference_values[cell_id][i] = f[cell_id][i] - g[cell_id][i]; + } + }); + + REQUIRE(same_values(f - g, difference_values)); + REQUIRE(same_values(const_f - g, difference_values)); + REQUIRE(same_values(f - const_g, difference_values)); + REQUIRE(same_values(const_f - const_g, difference_values)); + } + } + } + + SECTION("external operators") + { + DiscreteFunctionP0Vector<Dimension, double> f{mesh, size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + for (size_t i = 0; i < size; ++i) { + f[cell_id][i] = std::abs(2 * x) + i * y + z; + } + }); + + DiscreteFunctionP0Vector<Dimension, const double> const_f = f; + + SECTION("product") + { + SECTION("scalar lhs") + { + const double a = 3.2; + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + } + + SECTION("DiscreteFunctionP0 lhs") + { + DiscreteFunctionP0<Dimension, double> a{mesh}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + const double x = xj[cell_id][0]; + const double y = xj[cell_id][1]; + const double z = xj[cell_id][2]; + a[cell_id] = 2 * x + 1 - y * z; + }); + + Table<double> product_values{mesh->numberOfCells(), size}; + parallel_for( + mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { + for (size_t i = 0; i < size; ++i) { + product_values[cell_id][i] = a[cell_id] * f[cell_id][i]; + } + }); + + REQUIRE(same_values(a * f, product_values)); + REQUIRE(same_values(a * const_f, product_values)); + + DiscreteFunctionP0<Dimension, const double> const_a = a; + REQUIRE(same_values(const_a * f, product_values)); + REQUIRE(same_values(const_a * const_f, product_values)); + } + } + } + } + } +} diff --git a/tests/test_DiscreteFunctionType.cpp b/tests/test_DiscreteFunctionType.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5e00470e267cef8614281a03801ae4395975c45 --- /dev/null +++ b/tests/test_DiscreteFunctionType.cpp @@ -0,0 +1,15 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <scheme/DiscreteFunctionType.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("DiscreteFunctionType", "[scheme]") +{ + SECTION("name") + { + REQUIRE(name(DiscreteFunctionType::P0) == "P0"); + REQUIRE(name(DiscreteFunctionType::P0Vector) == "P0Vector"); + } +} diff --git a/tests/test_DoWhileProcessor.cpp b/tests/test_DoWhileProcessor.cpp index ccb056399c665a683c1f71cf1e4a224962fb4876..8e4f7a2c95b5cc435ba4365129aa8d207ef0adcf 100644 --- a/tests/test_DoWhileProcessor.cpp +++ b/tests/test_DoWhileProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> @@ -20,6 +21,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -48,6 +52,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ \ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ diff --git a/tests/test_ForProcessor.cpp b/tests/test_ForProcessor.cpp index e3d8a634e29d80f6a1be0534660065b02a0a3f6f..a83482550be288ed2104c6f28ed348955aee2914 100644 --- a/tests/test_ForProcessor.cpp +++ b/tests/test_ForProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> @@ -20,6 +21,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -48,6 +52,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ \ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ diff --git a/tests/test_IfProcessor.cpp b/tests/test_IfProcessor.cpp index 9b9da7d4026b2e136279ef0d482384ddbfa34418..461f3a98f8279a55e098e22fc5b63cec8276cc35 100644 --- a/tests/test_IfProcessor.cpp +++ b/tests/test_IfProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -18,6 +19,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -46,6 +50,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ \ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ diff --git a/tests/test_IncDecExpressionProcessor.cpp b/tests/test_IncDecExpressionProcessor.cpp index 62e3d531facb5fe956f775b6dcad000ced5c625a..5075ee900bdedb76acc9e7301b06732b7266753d 100644 --- a/tests/test_IncDecExpressionProcessor.cpp +++ b/tests/test_IncDecExpressionProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -18,6 +19,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ @@ -46,6 +50,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ \ REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); \ diff --git a/tests/test_InterpolateItemArray.cpp b/tests/test_InterpolateItemArray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf65afdf42c803b15900be7fc96fdad23e9c230f --- /dev/null +++ b/tests/test_InterpolateItemArray.cpp @@ -0,0 +1,467 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> +#include <language/ast/ASTNodeDataTypeBuilder.hpp> +#include <language/ast/ASTNodeExpressionBuilder.hpp> +#include <language/ast/ASTNodeFunctionEvaluationExpressionBuilder.hpp> +#include <language/ast/ASTNodeFunctionExpressionBuilder.hpp> +#include <language/ast/ASTNodeTypeCleaner.hpp> +#include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/PugsFunctionAdapter.hpp> +#include <language/utils/SymbolTable.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <mesh/Connectivity.hpp> +#include <mesh/Mesh.hpp> +#include <mesh/MeshData.hpp> +#include <mesh/MeshDataManager.hpp> + +#include <language/utils/InterpolateItemArray.hpp> + +#include <pegtl/string_input.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("InterpolateItemArray", "[language]") +{ + SECTION("interpolate on all items") + { + auto same_cell_array = [](auto f, auto g) -> bool { + using ItemIdType = typename decltype(f)::index_type; + + for (ItemIdType item_id = 0; item_id < f.numberOfItems(); ++item_id) { + for (size_t i = 0; i < f.sizeOfArrays(); ++i) { + if (f[item_id][i] != g[item_id][i]) { + return false; + } + } + } + + return true; + }; + + SECTION("1D") + { + constexpr size_t Dimension = 1; + + const auto& mesh_1d = MeshDataBaseForTests::get().cartesianMesh1D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + + std::string_view data = R"( +import math; +let scalar_affine_1d: R^1 -> R, x -> 2*x[0] + 2; +let scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + std::vector<FunctionSymbolId> function_symbol_id_list; + + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + CellArray<double> cell_array{mesh_1d->connectivity(), 2}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = 2 * x[0] + 2; + cell_array[cell_id][1] = 2 * exp(x[0]) + 3; + }); + + CellArray<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj); + + REQUIRE(same_cell_array(cell_array, interpolate_array)); + } + + SECTION("2D") + { + constexpr size_t Dimension = 2; + + const auto& mesh_2d = MeshDataBaseForTests::get().cartesianMesh2D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + + std::string_view data = R"( +import math; +let scalar_affine_2d: R^2 -> R, x -> 2*x[0] + 3*x[1] + 2; +let scalar_non_linear_2d: R^2 -> R, x -> 2*exp(x[0])*sin(x[1])+3; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + std::vector<FunctionSymbolId> function_symbol_id_list; + + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + CellArray<double> cell_array{mesh_2d->connectivity(), 2}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = 2 * x[0] + 3 * x[1] + 2; + cell_array[cell_id][1] = 2 * exp(x[0]) * sin(x[1]) + 3; + }); + + CellArray<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj); + + REQUIRE(same_cell_array(cell_array, interpolate_array)); + } + + SECTION("3D") + { + constexpr size_t Dimension = 3; + + const auto& mesh_3d = MeshDataBaseForTests::get().cartesianMesh3D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + + std::string_view data = R"( +import math; +let scalar_affine_3d: R^3 -> R, x -> 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; +let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + std::vector<FunctionSymbolId> function_symbol_id_list; + + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + CellArray<double> cell_array{mesh_3d->connectivity(), 2}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; + cell_array[cell_id][1] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; + }); + + CellArray<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj); + + REQUIRE(same_cell_array(cell_array, interpolate_array)); + } + } + + SECTION("interpolate on items list") + { + auto same_cell_value = [](auto interpolated, auto reference) -> bool { + for (size_t i = 0; i < interpolated.nbRows(); ++i) { + for (size_t j = 0; j < interpolated.nbColumns(); ++j) { + if (interpolated[i][j] != reference[i][j]) { + return false; + } + } + } + return true; + }; + + SECTION("1D") + { + constexpr size_t Dimension = 1; + + const auto& mesh_1d = MeshDataBaseForTests::get().cartesianMesh1D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + + Array<const CellId> cell_id_list = [&] { + Array<CellId> cell_ids{mesh_1d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_ids.size(); ++i_cell) { + cell_ids[i_cell] = static_cast<CellId>(2 * i_cell); + } + return cell_ids; + }(); + + std::string_view data = R"( + import math; + let scalar_affine_1d: R^1 -> R, x -> 2*x[0] + 2; + let scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; + )"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + std::vector<FunctionSymbolId> function_symbol_id_list; + + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + Table<double> cell_array{cell_id_list.size(), 2}; + parallel_for( + cell_id_list.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_array[i][0] = 2 * x[0] + 2; + cell_array[i][1] = 2 * exp(x[0]) + 3; + }); + + Table<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_array, interpolate_array)); + } + + SECTION("2D") + { + constexpr size_t Dimension = 2; + + const auto& mesh_2d = MeshDataBaseForTests::get().cartesianMesh2D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + + Array<CellId> cell_id_list{mesh_2d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { + cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); + } + + std::string_view data = R"( +import math; +let scalar_affine_2d: R^2 -> R, x -> 2*x[0] + 3*x[1] + 2; +let scalar_non_linear_2d: R^2 -> R, x -> 2*exp(x[0])*sin(x[1])+3; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + std::vector<FunctionSymbolId> function_symbol_id_list; + + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + Table<double> cell_array{cell_id_list.size(), 2}; + parallel_for( + cell_id_list.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_array[i][0] = 2 * x[0] + 3 * x[1] + 2; + cell_array[i][1] = 2 * exp(x[0]) * sin(x[1]) + 3; + }); + + Table<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_array, interpolate_array)); + } + + SECTION("3D") + { + constexpr size_t Dimension = 3; + + const auto& mesh_3d = MeshDataBaseForTests::get().cartesianMesh3D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + + Array<CellId> cell_id_list{mesh_3d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { + cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); + } + + std::string_view data = R"( +import math; +let scalar_affine_3d: R^3 -> R, x -> 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; +let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + std::vector<FunctionSymbolId> function_symbol_id_list; + + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + function_symbol_id_list.push_back( + FunctionSymbolId(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table)); + } + + Table<double> cell_array{cell_id_list.size(), 2}; + parallel_for( + cell_id_list.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_array[i][0] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; + cell_array[i][1] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; + }); + + Table<const double> interpolate_array = + InterpolateItemArray<double(TinyVector<Dimension>)>::interpolate(function_symbol_id_list, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_array, interpolate_array)); + } + } +} diff --git a/tests/test_InterpolateItemValue.cpp b/tests/test_InterpolateItemValue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fa786632c10660c9197842196440ae383a489edd --- /dev/null +++ b/tests/test_InterpolateItemValue.cpp @@ -0,0 +1,1026 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> +#include <language/ast/ASTNodeDataTypeBuilder.hpp> +#include <language/ast/ASTNodeExpressionBuilder.hpp> +#include <language/ast/ASTNodeFunctionEvaluationExpressionBuilder.hpp> +#include <language/ast/ASTNodeFunctionExpressionBuilder.hpp> +#include <language/ast/ASTNodeTypeCleaner.hpp> +#include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/PugsFunctionAdapter.hpp> +#include <language/utils/SymbolTable.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <mesh/Connectivity.hpp> +#include <mesh/Mesh.hpp> +#include <mesh/MeshData.hpp> +#include <mesh/MeshDataManager.hpp> + +#include <language/utils/InterpolateItemValue.hpp> + +#include <pegtl/string_input.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("InterpolateItemValue", "[language]") +{ + SECTION("interpolate on all items") + { + auto same_cell_value = [](auto f, auto g) -> bool { + using ItemIdType = typename decltype(f)::index_type; + for (ItemIdType item_id = 0; item_id < f.numberOfItems(); ++item_id) { + if (f[item_id] != g[item_id]) { + return false; + } + } + + return true; + }; + + SECTION("1D") + { + constexpr size_t Dimension = 1; + + const auto& mesh_1d = MeshDataBaseForTests::get().cartesianMesh1D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + + std::string_view data = R"( +import math; +let scalar_affine_1d: R^1 -> R, x -> 2*x[0] + 2; +let scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; +let R3_affine_1d: R^1 -> R^3, x -> (2 * x[0] + 2, 3 * x[0], 2); +let R3_non_linear_1d: R^1 -> R^3, x -> (2 * exp(x[0]) + 3, x[0] - 2, 3); +let R2x2_affine_1d: R^1 -> R^2x2, x -> (2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2); +let R2x2_non_linear_1d: R^1 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]); +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * x[0] + 2; + }); + + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * exp(x[0]) + 3; + }); + + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * x[0] + 2, 3 * x[0], 2}; + }); + + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * exp(x[0]) + 3, x[0] - 2, 3}; + }); + + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyMatrix<2>{2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2}; + }); + + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_1d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]}; + }); + + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } + + SECTION("2D") + { + constexpr size_t Dimension = 2; + + const auto& mesh_2d = MeshDataBaseForTests::get().cartesianMesh2D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + + std::string_view data = R"( +import math; +let scalar_affine_2d: R^2 -> R, x -> 2*x[0] + 3*x[1] + 2; +let scalar_non_linear_2d: R^2 -> R, x -> 2*exp(x[0])*sin(x[1])+3; +let R3_affine_2d: R^2 -> R^3, x -> (2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[1]); +let R3_non_linear_2d: R^2 -> R^3, x -> (2*exp(x[0])*sin(x[1])+3, x[0]-2*x[1], 3); +let R2x2_affine_2d: R^2 -> R^2x2, x -> (2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2); +let R2x2_non_linear_2d: R^2 -> R^2x2, x -> (2*exp(x[0])*sin(x[1])+3, sin(x[0]-2*x[1]), 3, x[0]*x[1]); +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * x[0] + 3 * x[1] + 2; + }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * exp(x[0]) * sin(x[1]) + 3; + }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[1]}; + }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + 3, x[0] - 2 * x[1], 3}; + }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2}; + }); + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_2d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3, sin(x[0] - 2 * x[1]), 3, x[0] * x[1]}; + }); + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } + + SECTION("3D") + { + constexpr size_t Dimension = 3; + + const auto& mesh_3d = MeshDataBaseForTests::get().cartesianMesh3D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + + std::string_view data = R"( +import math; +let scalar_affine_3d: R^3 -> R, x -> 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; +let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; +let R3_affine_3d: R^3 -> R^3, x -> (2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1] + 2 * x[2], 2 * x[2]); +let R3_non_linear_3d: R^3 -> R^3, x -> (2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[0] * x[2] - 2 * x[1], 3); +let R2x2_affine_3d: R^3 -> R^2x2, x -> (2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], 2 * x[0] + x[1] + x[2], 2); +let R2x2_non_linear_3d: R^3 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), sin(x[0] - 2 * x[1] * x[2]), 3, x[0] * x[1] * x[2]); +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; + }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<double> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; + }); + CellValue<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1] + 2 * x[2], 2 * x[2]}; + }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyVector<3>> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[0] * x[2] - 2 * x[1], 3}; + }); + CellValue<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = + TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], 2 * x[0] + x[1] + x[2], 2}; + }); + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellValue<TinyMatrix<2>> cell_value{mesh_3d->connectivity()}; + parallel_for( + cell_value.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_value[cell_id] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), sin(x[0] - 2 * x[1] * x[2]), + 3, x[0] * x[1] * x[2]}; + }); + CellValue<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } + } + + SECTION("interpolate on items list") + { + auto same_cell_value = [](auto interpolated, auto reference) -> bool { + for (size_t i = 0; i < interpolated.size(); ++i) { + if (interpolated[i] != reference[i]) { + return false; + } + } + + return true; + }; + + SECTION("1D") + { + constexpr size_t Dimension = 1; + + const auto& mesh_1d = MeshDataBaseForTests::get().cartesianMesh1D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + + Array<const CellId> cell_id_list = [&] { + Array<CellId> cell_ids{mesh_1d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_ids.size(); ++i_cell) { + cell_ids[i_cell] = static_cast<CellId>(2 * i_cell); + } + return cell_ids; + }(); + + std::string_view data = R"( +import math; +let scalar_affine_1d: R^1 -> R, x -> 2*x[0] + 2; +let scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; +let R3_affine_1d: R^1 -> R^3, x -> (2 * x[0] + 2, 3 * x[0], 2); +let R3_non_linear_1d: R^1 -> R^3, x -> (2 * exp(x[0]) + 3, x[0] - 2, 3); +let R2x2_affine_1d: R^1 -> R^2x2, x -> (2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2); +let R2x2_non_linear_1d: R^1 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]); +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * x[0] + 2; + }); + + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * exp(x[0]) + 3; + }); + + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * x[0] + 2, 3 * x[0], 2}; + }); + + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * exp(x[0]) + 3, x[0] - 2, 3}; + }); + + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_1d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * x[0] + 3 + 2, 3 * x[0], 2 * x[0], 2}; + }); + + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_1d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3, x[0] * x[0]}; + }); + + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } + + SECTION("2D") + { + constexpr size_t Dimension = 2; + + const auto& mesh_2d = MeshDataBaseForTests::get().cartesianMesh2D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_2d).xj(); + + Array<CellId> cell_id_list{mesh_2d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { + cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); + } + + std::string_view data = R"( +import math; +let scalar_affine_2d: R^2 -> R, x -> 2*x[0] + 3*x[1] + 2; +let scalar_non_linear_2d: R^2 -> R, x -> 2*exp(x[0])*sin(x[1])+3; +let R3_affine_2d: R^2 -> R^3, x -> (2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[1]); +let R3_non_linear_2d: R^2 -> R^3, x -> (2*exp(x[0])*sin(x[1])+3, x[0]-2*x[1], 3); +let R2x2_affine_2d: R^2 -> R^2x2, x -> (2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2); +let R2x2_non_linear_2d: R^2 -> R^2x2, x -> (2*exp(x[0])*sin(x[1])+3, sin(x[0]-2*x[1]), 3, x[0]*x[1]); +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * x[0] + 3 * x[1] + 2; + }); + + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * exp(x[0]) * sin(x[1]) + 3; + }); + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[1]}; + }); + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + 3, x[0] - 2 * x[1], 3}; + }); + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_2d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1], 2 * x[0] + x[1], 2}; + }); + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_2d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3, sin(x[0] - 2 * x[1]), 3, x[0] * x[1]}; + }); + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } + + SECTION("3D") + { + constexpr size_t Dimension = 3; + + const auto& mesh_3d = MeshDataBaseForTests::get().cartesianMesh3D(); + auto xj = MeshDataManager::instance().getMeshData(*mesh_3d).xj(); + + Array<CellId> cell_id_list{mesh_3d->numberOfCells() / 2}; + for (size_t i_cell = 0; i_cell < cell_id_list.size(); ++i_cell) { + cell_id_list[i_cell] = static_cast<CellId>(2 * i_cell); + } + + std::string_view data = R"( +import math; +let scalar_affine_3d: R^3 -> R, x -> 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; +let scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; +let R3_affine_3d: R^3 -> R^3, x -> (2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1] + 2 * x[2], 2 * x[2]); +let R3_non_linear_3d: R^3 -> R^3, x -> (2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[0] * x[2] - 2 * x[1], 3); +let R2x2_affine_3d: R^3 -> R^2x2, x -> (2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], 2 * x[0] + x[1] + x[2], 2); +let R2x2_non_linear_3d: R^3 -> R^2x2, x -> (2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), sin(x[0] - 2 * x[1] * x[2]), 3, x[0] * x[1] * x[2]); +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("scalar_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("scalar_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * x[0] + 3 * x[1] + 2 * x[2] - 1; + }); + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("scalar_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("scalar_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<double> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = 2 * exp(x[0]) * sin(x[1]) * x[2] + 3; + }); + Array<const double> interpolate_value = + InterpolateItemValue<double(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("R3_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * x[0] + 3 * x[1] + 2, 3 * x[0] + x[1] + 2 * x[2], 2 * x[2]}; + }); + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R3_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("R3_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyVector<3>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyVector<3>{2 * exp(x[0]) * sin(x[1]) + x[2] + 3, x[0] * x[2] - 2 * x[1], 3}; + }); + Array<const TinyVector<3>> interpolate_value = + InterpolateItemValue<TinyVector<3>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_affine_3d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_affine_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = + TinyMatrix<2>{2 * x[0] + 3 * x[1] + 2 * x[2] + 1, 3 * x[0] + x[1] + 2 * x[2], 2 * x[0] + x[1] + x[2], 2}; + }); + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + + SECTION("R2x2_non_linear_3d") + { + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + Array<TinyMatrix<2>> cell_value{cell_id_list.size()}; + parallel_for( + cell_value.size(), PUGS_LAMBDA(const size_t i) { + const TinyVector<Dimension>& x = xj[cell_id_list[i]]; + cell_value[i] = TinyMatrix<2>{2 * exp(x[0]) * sin(x[1]) + 3 * cos(x[2]), sin(x[0] - 2 * x[1] * x[2]), 3, + x[0] * x[1] * x[2]}; + }); + Array<const TinyMatrix<2>> interpolate_value = + InterpolateItemValue<TinyMatrix<2>(TinyVector<Dimension>)>::interpolate(function_symbol_id, xj, cell_id_list); + + REQUIRE(same_cell_value(cell_value, interpolate_value)); + } + } + } +} diff --git a/tests/test_ItemArray.cpp b/tests/test_ItemArray.cpp index 8cf05df5df90f3886771905f9a4fe2b727698150..2a76275324c4922ed0bad182ebcfa106c3d9b462 100644 --- a/tests/test_ItemArray.cpp +++ b/tests/test_ItemArray.cpp @@ -28,7 +28,7 @@ TEST_CASE("ItemArray", "[mesh]") SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); REQUIRE_NOTHROW(NodeArray<int>{connectivity, 3}); @@ -58,7 +58,7 @@ TEST_CASE("ItemArray", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); REQUIRE_NOTHROW(NodeArray<int>{connectivity, 2}); @@ -86,7 +86,7 @@ TEST_CASE("ItemArray", "[mesh]") SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); REQUIRE_NOTHROW(NodeArray<int>{connectivity, 3}); @@ -112,7 +112,7 @@ TEST_CASE("ItemArray", "[mesh]") SECTION("set values from array") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellArray<size_t> cell_array{connectivity, 3}; @@ -155,7 +155,7 @@ TEST_CASE("ItemArray", "[mesh]") return is_same; }; - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellArray<int> cell_array{connectivity, 4}; @@ -169,16 +169,20 @@ TEST_CASE("ItemArray", "[mesh]") CellArray<const int> const_cell_array; const_cell_array = copy(cell_array); + CellArray<int> duplicated_cell_array{connectivity, cell_array.sizeOfArrays()}; + copy_to(const_cell_array, duplicated_cell_array); + cell_array.fill(0); REQUIRE(is_same(cell_array, 0)); REQUIRE(is_same(cell_array_const_view, 0)); REQUIRE(is_same(const_cell_array, static_cast<std::int64_t>(parallel::rank()))); + REQUIRE(is_same(duplicated_cell_array, static_cast<std::int64_t>(parallel::rank()))); } SECTION("WeakItemArray") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); WeakFaceArray<int> weak_face_array{connectivity, 5}; @@ -210,7 +214,7 @@ TEST_CASE("ItemArray", "[mesh]") SECTION("checking for bounds violation") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellArray<int> cell_array{connectivity, 1}; @@ -232,7 +236,7 @@ TEST_CASE("ItemArray", "[mesh]") SECTION("set values from invalid array size") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellArray<size_t> cell_array{connectivity, 2}; diff --git a/tests/test_ItemArrayUtils.cpp b/tests/test_ItemArrayUtils.cpp index a8c4b7fbf50eb3c4bb4f9af89926eedcd66c5992..6eb6894d41aa3700fdc86e6c0d7c9d83acda328e 100644 --- a/tests/test_ItemArrayUtils.cpp +++ b/tests/test_ItemArrayUtils.cpp @@ -19,7 +19,7 @@ TEST_CASE("ItemArrayUtils", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); SECTION("node") @@ -269,7 +269,7 @@ TEST_CASE("ItemArrayUtils", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); SECTION("node") @@ -519,7 +519,7 @@ TEST_CASE("ItemArrayUtils", "[mesh]") SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); SECTION("node") diff --git a/tests/test_ItemValue.cpp b/tests/test_ItemValue.cpp index 942b4f57bafd0528ed31e82709213207c2dea619..1c4ab49faf757cc0b2e871f9bf4e0ba33061ece7 100644 --- a/tests/test_ItemValue.cpp +++ b/tests/test_ItemValue.cpp @@ -26,7 +26,7 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); REQUIRE_NOTHROW(NodeValue<int>{connectivity}); @@ -51,7 +51,7 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); REQUIRE_NOTHROW(NodeValue<int>{connectivity}); @@ -72,7 +72,7 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); REQUIRE_NOTHROW(NodeValue<int>{connectivity}); @@ -88,7 +88,7 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("set values from array") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellValue<size_t> cell_value{connectivity}; @@ -107,7 +107,7 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("copy") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellValue<int> cell_value{connectivity}; @@ -129,7 +129,7 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("WeakItemValue") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); WeakFaceValue<int> weak_face_value{connectivity}; @@ -161,7 +161,7 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("checking for bounds violation") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellValue<int> cell_value{connectivity}; @@ -183,7 +183,7 @@ TEST_CASE("ItemValue", "[mesh]") SECTION("set values from invalid array size") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellValue<size_t> cell_value{connectivity}; @@ -191,6 +191,19 @@ TEST_CASE("ItemValue", "[mesh]") Array<size_t> values{3 + cell_value.numberOfItems()}; REQUIRE_THROWS_AS(cell_value = values, AssertError); } + + SECTION("invalid copy_to") + { + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); + const Connectivity<2>& connectivity_2d = mesh_2d.connectivity(); + + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); + const Connectivity<3>& connectivity_3d = mesh_3d.connectivity(); + + CellValue<int> cell_2d_value{connectivity_2d}; + CellValue<int> cell_3d_value{connectivity_3d}; + REQUIRE_THROWS_AS(copy_to(cell_2d_value, cell_3d_value), AssertError); + } } #endif // NDEBUG } diff --git a/tests/test_ItemValueUtils.cpp b/tests/test_ItemValueUtils.cpp index f54362188d6e9519d28abb47e69385ba11ccfdb8..b77dfecd58fe2aa2ee2addcc483f631f3e3ec62f 100644 --- a/tests/test_ItemValueUtils.cpp +++ b/tests/test_ItemValueUtils.cpp @@ -17,7 +17,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") { SECTION("Synchronize") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); WeakFaceValue<int> weak_face_value{connectivity}; @@ -57,7 +57,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); CellValue<int> cell_value{connectivity}; @@ -76,7 +76,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); CellValue<int> cell_value{connectivity}; @@ -95,7 +95,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellValue<int> cell_value{connectivity}; @@ -117,7 +117,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); CellValue<size_t> cell_value{connectivity}; @@ -136,7 +136,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); CellValue<size_t> cell_value{connectivity}; @@ -155,7 +155,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellValue<size_t> cell_value{connectivity}; @@ -177,7 +177,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); CellValue<size_t> cell_value{connectivity}; @@ -198,7 +198,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); FaceValue<size_t> face_value{connectivity}; @@ -219,7 +219,7 @@ TEST_CASE("ItemValueUtils", "[mesh]") SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); NodeValue<size_t> node_value{connectivity}; diff --git a/tests/test_ListAffectationProcessor.cpp b/tests/test_ListAffectationProcessor.cpp index f809884c3e660f16cc88f58c709040c58c96fe70..94dc1845cddcd898a3b3b0f2f08c80e164898660 100644 --- a/tests/test_ListAffectationProcessor.cpp +++ b/tests/test_ListAffectationProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -18,6 +19,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_NameProcessor.cpp b/tests/test_NameProcessor.cpp index ac6b8174d6345e4be81fe5515bca14233fa8f1f4..30e20339aac2096b61f4a12b3131959531061475 100644 --- a/tests/test_NameProcessor.cpp +++ b/tests/test_NameProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -27,6 +28,9 @@ n = 2; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + ASTSymbolTableBuilder{*ast}; ASTNodeDataTypeBuilder{*ast}; diff --git a/tests/test_PugsFunctionAdapter.cpp b/tests/test_PugsFunctionAdapter.cpp index 7d048738e6a20484dfe5f0431d7dab9bf3f3c5f2..76f3a06aa3f96c208e6c02c16f8006e22160a8f6 100644 --- a/tests/test_PugsFunctionAdapter.cpp +++ b/tests/test_PugsFunctionAdapter.cpp @@ -1,10 +1,6 @@ #include <catch2/catch_test_macros.hpp> #include <catch2/matchers/catch_matchers_all.hpp> -#include <language/ast/ASTBuilder.hpp> -#include <language/utils/PugsFunctionAdapter.hpp> -#include <language/utils/SymbolTable.hpp> - #include <language/ast/ASTBuilder.hpp> #include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> @@ -13,8 +9,8 @@ #include <language/ast/ASTNodeFunctionExpressionBuilder.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> -#include <language/utils/ASTPrinter.hpp> -#include <utils/Demangle.hpp> +#include <language/utils/PugsFunctionAdapter.hpp> +#include <language/utils/SymbolTable.hpp> #include <pegtl/string_input.hpp> diff --git a/tests/test_SubArray.cpp b/tests/test_SubArray.cpp deleted file mode 100644 index b0fdec7882d7ee3504cb24bdfb76b796649f8202..0000000000000000000000000000000000000000 --- a/tests/test_SubArray.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include <catch2/catch_test_macros.hpp> -#include <catch2/matchers/catch_matchers_all.hpp> - -#include <utils/PugsAssert.hpp> -#include <utils/SubArray.hpp> -#include <utils/Types.hpp> - -// Instantiate to ensure full coverage is performed -template class SubArray<int>; - -// clazy:excludeall=non-pod-global-static - -TEST_CASE("SubArray", "[utils]") -{ - Array<int> a(10); - REQUIRE(a.size() == 10); - - SECTION("shared values") - { - SubArray sub_a{a, 0, 10}; - for (size_t i = 0; i < sub_a.size(); ++i) { - sub_a[i] = 2 * i; - } - - REQUIRE(((a[0] == 0) and (a[1] == 2) and (a[2] == 4) and (a[3] == 6) and (a[4] == 8) and (a[5] == 10) and - (a[6] == 12) and (a[7] == 14) and (a[8] == 16) and (a[9] == 18))); - - for (size_t i = 0; i < a.size(); ++i) { - a[i] = (i + 1) * (2 * i + 1); - } - - REQUIRE(((sub_a[0] == 1) and (sub_a[1] == 6) and (sub_a[2] == 15) and (sub_a[3] == 28) and (sub_a[4] == 45) and - (sub_a[5] == 66) and (sub_a[6] == 91) and (sub_a[7] == 120) and (sub_a[8] == 153) and (sub_a[9] == 190))); - } - - SECTION("sub array") - { - a.fill(0); - SubArray sub_a{a, 5, 5}; - for (size_t i = 0; i < sub_a.size(); ++i) { - sub_a[i] = i + 1; - } - - REQUIRE(((a[0] == 0) and (a[1] == 0) and (a[2] == 0) and (a[3] == 0) and (a[4] == 0) and (a[5] == 1) and - (a[6] == 2) and (a[7] == 3) and (a[8] == 4) and (a[9] == 5))); - - for (size_t i = 0; i < a.size(); ++i) { - a[i] = (i + 1) * (2 * i + 1); - } - - REQUIRE(((sub_a[0] == 66) and (sub_a[1] == 91) and (sub_a[2] == 120) and (sub_a[3] == 153) and (sub_a[4] == 190))); - } - -#ifndef NDEBUG - SECTION("errors") - { - a.fill(0); - SubArray<int> sub_a{a, 5, 5}; - for (size_t i = 0; i < sub_a.size(); ++i) { - sub_a[i] = i + 1; - } - - REQUIRE_THROWS_AS(sub_a[5], AssertError); - } -#endif // NDEBUG -} diff --git a/tests/test_SubItemArrayPerItem.cpp b/tests/test_SubItemArrayPerItem.cpp index 7636ad420dc87ddf029d21b154ea0067a4eb5684..b03353f0ebbff8fe3d6c5634020d1ea739668f57 100644 --- a/tests/test_SubItemArrayPerItem.cpp +++ b/tests/test_SubItemArrayPerItem.cpp @@ -64,7 +64,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); SECTION("per cell") @@ -178,7 +178,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); SECTION("per cell") @@ -335,7 +335,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") } SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); SECTION("per cell") @@ -524,7 +524,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); EdgeArrayPerCell<size_t> edge_arrays_per_cell{connectivity, 3}; @@ -589,7 +589,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); CellArrayPerFace<size_t> cell_arrays_per_face{connectivity, 3}; @@ -653,7 +653,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); FaceArrayPerNode<size_t> face_arrays_per_node{connectivity, 3}; @@ -717,7 +717,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") SECTION("copy") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); SECTION("classic") @@ -818,7 +818,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") SECTION("WeakSubItemArrayPerItem") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); WeakFaceArrayPerCell<int> weak_face_array_per_cell{connectivity, 3}; @@ -889,7 +889,7 @@ TEST_CASE("SubItemArrayPerItem", "[mesh]") SECTION("checking for bounds violation") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellArrayPerFace<int> cell_array_per_face{connectivity, 3}; diff --git a/tests/test_SubItemValuePerItem.cpp b/tests/test_SubItemValuePerItem.cpp index e7c9434aa7362f7cb27a87ee6b144df27f9c2f26..f9b71010b411c3a53b968703202882f1d4fd0df1 100644 --- a/tests/test_SubItemValuePerItem.cpp +++ b/tests/test_SubItemValuePerItem.cpp @@ -64,7 +64,7 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); SECTION("per cell") @@ -172,7 +172,7 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); SECTION("per cell") @@ -320,7 +320,7 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); SECTION("per cell") @@ -497,7 +497,7 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") { SECTION("1D") { - const Mesh<Connectivity<1>>& mesh_1d = MeshDataBaseForTests::get().cartesianMesh<1>(); + const Mesh<Connectivity<1>>& mesh_1d = *MeshDataBaseForTests::get().cartesianMesh1D(); const Connectivity<1>& connectivity = mesh_1d.connectivity(); EdgeValuePerCell<size_t> edge_values_per_cell{connectivity}; @@ -534,7 +534,7 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("2D") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); CellValuePerFace<size_t> cell_values_per_face{connectivity}; @@ -570,7 +570,7 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("3D") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); FaceValuePerNode<size_t> face_values_per_node{connectivity}; @@ -608,7 +608,7 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("copy") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); SECTION("classic") @@ -698,7 +698,7 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("WeakSubItemValuePerItem") { - const Mesh<Connectivity<2>>& mesh_2d = MeshDataBaseForTests::get().cartesianMesh<2>(); + const Mesh<Connectivity<2>>& mesh_2d = *MeshDataBaseForTests::get().cartesianMesh2D(); const Connectivity<2>& connectivity = mesh_2d.connectivity(); WeakFaceValuePerCell<int> weak_face_value_per_cell{connectivity}; @@ -758,7 +758,7 @@ TEST_CASE("SubItemValuePerItem", "[mesh]") SECTION("checking for bounds violation") { - const Mesh<Connectivity<3>>& mesh_3d = MeshDataBaseForTests::get().cartesianMesh<3>(); + const Mesh<Connectivity<3>>& mesh_3d = *MeshDataBaseForTests::get().cartesianMesh3D(); const Connectivity<3>& connectivity = mesh_3d.connectivity(); CellValuePerFace<int> cell_value_per_face{connectivity}; diff --git a/tests/test_Table.cpp b/tests/test_Table.cpp index 7b736f3d76f87129b45885fed737a361bf73562e..3521476c375dba6a31e57dd2f55ad09430026d8a 100644 --- a/tests/test_Table.cpp +++ b/tests/test_Table.cpp @@ -137,6 +137,23 @@ TEST_CASE("Table", "[utils]") REQUIRE(((c(0, 0) == 2) and (c(1, 0) == 2) and (c(2, 0) == 2) and (c(3, 0) == 2) and // (c(0, 1) == 2) and (c(1, 1) == 2) and (c(2, 1) == 2) and (c(3, 1) == 2) and // (c(0, 2) == 2) and (c(1, 2) == 2) and (c(2, 2) == 2) and (c(3, 2) == 2))); + + Table<int> d{a.nbRows(), a.nbColumns()}; + copy_to(a, d); + + REQUIRE(((a(0, 0) == 0) and (a(1, 0) == 2) and (a(2, 0) == 4) and (a(3, 0) == 6) and // + (a(0, 1) == 1) and (a(1, 1) == 3) and (a(2, 1) == 5) and (a(3, 1) == 7) and // + (a(0, 2) == 2) and (a(1, 2) == 4) and (a(2, 2) == 6) and (a(3, 2) == 8))); + + REQUIRE(((d(0, 0) == 0) and (d(1, 0) == 2) and (d(2, 0) == 4) and (d(3, 0) == 6) and // + (d(0, 1) == 1) and (d(1, 1) == 3) and (d(2, 1) == 5) and (d(3, 1) == 7) and // + (d(0, 2) == 2) and (d(1, 2) == 4) and (d(2, 2) == 6) and (d(3, 2) == 8))); + + copy_to(c, d); + + REQUIRE(((d(0, 0) == 2) and (d(1, 0) == 2) and (d(2, 0) == 2) and (d(3, 0) == 2) and // + (d(0, 1) == 2) and (d(1, 1) == 2) and (d(2, 1) == 2) and (d(3, 1) == 2) and // + (d(0, 2) == 2) and (d(1, 2) == 2) and (d(2, 2) == 2) and (d(3, 2) == 2))); } SECTION("checking for Kokkos::View encaspulation") @@ -167,5 +184,20 @@ TEST_CASE("Table", "[utils]") REQUIRE_THROWS_AS(a(4, 0), AssertError); REQUIRE_THROWS_AS(a(0, 3), AssertError); } + + SECTION("invalid copy_to") + { + SECTION("wrong row number") + { + Table<int> b{2 * a.nbRows(), a.nbColumns()}; + REQUIRE_THROWS_AS(copy_to(a, b), AssertError); + } + + SECTION("wrong column number") + { + Table<int> c{a.nbRows(), 2 * a.nbColumns()}; + REQUIRE_THROWS_AS(copy_to(a, c), AssertError); + } + } #endif // NDEBUG } diff --git a/tests/test_UnaryExpressionProcessor.cpp b/tests/test_UnaryExpressionProcessor.cpp index 84b3bc0c8da06d17dd429f7add7d72d036d17068..f63e45d1fa9912f1d007f83a2759bfc5b7316b42 100644 --- a/tests/test_UnaryExpressionProcessor.cpp +++ b/tests/test_UnaryExpressionProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> @@ -18,6 +19,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \ diff --git a/tests/test_WhileProcessor.cpp b/tests/test_WhileProcessor.cpp index 33f1d9488a3007e8f1a4d2f8c9a733487c496d4b..e886b62137e4d9d67bdabdca4745bb6cf266537d 100644 --- a/tests/test_WhileProcessor.cpp +++ b/tests/test_WhileProcessor.cpp @@ -2,6 +2,7 @@ #include <catch2/matchers/catch_matchers_all.hpp> #include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeAffectationExpressionBuilder.hpp> #include <language/ast/ASTNodeDataTypeBuilder.hpp> #include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp> @@ -19,6 +20,9 @@ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ ASTSymbolTableBuilder{*ast}; \ ASTNodeDataTypeBuilder{*ast}; \ \