diff --git a/doc/userdoc.org b/doc/userdoc.org index c338582d59ef05c6b2241c09b615a515e56b2fe0..ba7cd798a6a7991d6451c405a5b9c81dfa2c0362 100644 --- a/doc/userdoc.org +++ b/doc/userdoc.org @@ -1223,8 +1223,7 @@ are sorted by type of left hand side variable. Observe that for these small matrix types ($\mathbb{R}^{d\times d}$) the construction ~A *= B;~ where ~B~ is a matrix of the same type as ~A~ is not allowed. The main reason for that is that for $d>1$ this operation has -no interest since it requires a temporary. One will see bellow that it -is possible to write ~A = A*B;~ if needed. +no interest since it requires a temporary. One will see below that it #+END_note - ~string~: the ~*=~ operator is not defined for left hand side string variables. diff --git a/src/language/modules/BinaryOperatorRegisterForVh.cpp b/src/language/modules/BinaryOperatorRegisterForVh.cpp index 675d84772cc9764df42be29b8be9a03de77c6858..3eb83537323d91bbf6266cbefebf4d004d74c2be 100644 --- a/src/language/modules/BinaryOperatorRegisterForVh.cpp +++ b/src/language/modules/BinaryOperatorRegisterForVh.cpp @@ -4,9 +4,8 @@ #include <language/utils/BinaryOperatorProcessorBuilder.hpp> #include <language/utils/DataHandler.hpp> #include <language/utils/DataVariant.hpp> -#include <language/utils/EmbeddedIDiscreteFunctionOperators.hpp> +#include <language/utils/EmbeddedDiscreteFunctionOperators.hpp> #include <language/utils/OperatorRepository.hpp> -#include <scheme/IDiscreteFunction.hpp> void BinaryOperatorRegisterForVh::_register_plus() @@ -14,89 +13,89 @@ 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, bool, - std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + bool, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - int64_t, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + int64_t, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - uint64_t, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + uint64_t, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, double, - std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + double, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, bool>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyVector<1>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - TinyVector<2>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyVector<2>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - TinyVector<3>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyVector<3>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<1>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyMatrix<1>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<2>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyMatrix<2>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<3>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyMatrix<3>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::plus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, TinyVector<1>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::plus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, TinyMatrix<3>>>()); } void @@ -105,89 +104,89 @@ 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, bool, - std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + bool, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - int64_t, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + int64_t, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - uint64_t, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + uint64_t, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - double, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + double, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, bool>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyVector<1>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - TinyVector<2>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyVector<2>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - TinyVector<3>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyVector<3>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<1>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyMatrix<1>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<2>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyMatrix<2>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<3>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyMatrix<3>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::minus_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, TinyVector<1>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::minus_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, TinyMatrix<3>>>()); } void @@ -196,77 +195,94 @@ 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder< + language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - bool, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, bool, + std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - int64_t, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, int64_t, + std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - uint64_t, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, uint64_t, + std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - double, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, double, + std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, bool>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyMatrix<1>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<2>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyMatrix<2>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - TinyMatrix<3>, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + TinyMatrix<3>, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::multiply_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, TinyVector<1>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, 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>>>()); + std::make_shared< + BinaryOperatorProcessorBuilder<language::multiply_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, TinyMatrix<3>>>()); } void @@ -275,21 +291,21 @@ 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>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::divide_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const IDiscreteFunction>, - int64_t, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const DiscreteFunctionVariant>, + int64_t, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::divide_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const IDiscreteFunction>, - uint64_t, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const DiscreteFunctionVariant>, + uint64_t, std::shared_ptr<const DiscreteFunctionVariant>>>()); repository.addBinaryOperator<language::divide_op>( - std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const IDiscreteFunction>, - double, std::shared_ptr<const IDiscreteFunction>>>()); + std::make_shared<BinaryOperatorProcessorBuilder<language::divide_op, std::shared_ptr<const DiscreteFunctionVariant>, + double, std::shared_ptr<const DiscreteFunctionVariant>>>()); } BinaryOperatorRegisterForVh::BinaryOperatorRegisterForVh() diff --git a/src/language/modules/MathFunctionRegisterForVh.cpp b/src/language/modules/MathFunctionRegisterForVh.cpp index d0468777f4528873115939a69027dcb6844d936f..38dc08b6e4bec82be8cab2666080563bd7cb9736 100644 --- a/src/language/modules/MathFunctionRegisterForVh.cpp +++ b/src/language/modules/MathFunctionRegisterForVh.cpp @@ -2,361 +2,387 @@ #include <language/modules/SchemeModule.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> -#include <language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp> -#include <scheme/IDiscreteFunction.hpp> -#include <scheme/IDiscreteFunctionDescriptor.hpp> +#include <language/utils/EmbeddedDiscreteFunctionMathFunctions.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module) { scheme_module._addBuiltinFunction("sqrt", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return sqrt(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return sqrt(a); } )); scheme_module._addBuiltinFunction("abs", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return abs(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return abs(a); } )); scheme_module._addBuiltinFunction("sin", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return sin(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return sin(a); } )); scheme_module._addBuiltinFunction("cos", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return cos(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return cos(a); } )); scheme_module._addBuiltinFunction("tan", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return tan(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return tan(a); } )); scheme_module._addBuiltinFunction("asin", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return asin(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return asin(a); } )); scheme_module._addBuiltinFunction("acos", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return acos(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return acos(a); } )); scheme_module._addBuiltinFunction("atan", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return atan(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return atan(a); } )); - scheme_module._addBuiltinFunction("atan2", std::function( - - [](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::function( + scheme_module._addBuiltinFunction("atan2", + std::function( - [](double a, std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, + std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return atan2(a, b); } - )); + )); scheme_module._addBuiltinFunction("atan2", std::function( - [](std::shared_ptr<const IDiscreteFunction> a, - double b) -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); } + [](double a, std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return atan2(a, b); } )); + scheme_module._addBuiltinFunction("atan2", std::function( + + [](std::shared_ptr<const DiscreteFunctionVariant> a, + double b) -> std::shared_ptr<const DiscreteFunctionVariant> { + return atan2(a, b); + } + + )); + scheme_module._addBuiltinFunction("sinh", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return sinh(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return sinh(a); } )); - scheme_module._addBuiltinFunction("std::function", std::function( + scheme_module._addBuiltinFunction("tanh", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return tanh(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return tanh(a); } - )); + )); scheme_module._addBuiltinFunction("asinh", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return asinh(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return asinh(a); } )); scheme_module._addBuiltinFunction("acosh", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return acosh(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return acosh(a); } )); scheme_module._addBuiltinFunction("atanh", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return atanh(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return atanh(a); } )); scheme_module._addBuiltinFunction("exp", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return exp(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return exp(a); } )); scheme_module._addBuiltinFunction("log", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return log(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { return log(a); } )); scheme_module._addBuiltinFunction("pow", std::function( - [](double a, std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); } + [](double a, std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return pow(a, b); } )); - scheme_module._addBuiltinFunction("pow", - std::function( + scheme_module._addBuiltinFunction("pow", std::function( - [](std::shared_ptr<const IDiscreteFunction> a, - double b) -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, double b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return pow(a, b); } - )); + )); scheme_module._addBuiltinFunction("pow", std::function( - [](std::shared_ptr<const IDiscreteFunction> a, - std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, + std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return pow(a, b); } )); scheme_module._addBuiltinFunction("dot", std::function( - [](std::shared_ptr<const IDiscreteFunction> a, - std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, + std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return dot(a, b); } )); scheme_module._addBuiltinFunction("dot", std::function( - [](std::shared_ptr<const IDiscreteFunction> a, const TinyVector<1> b) - -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, const TinyVector<1> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return dot(a, b); } )); scheme_module._addBuiltinFunction("dot", std::function( - [](std::shared_ptr<const IDiscreteFunction> a, const TinyVector<2> b) - -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, const TinyVector<2> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return dot(a, b); } )); - scheme_module._addBuiltinFunction("dot", std::function( + scheme_module._addBuiltinFunction("dot", + std::function( - [](std::shared_ptr<const IDiscreteFunction> a, const TinyVector<3>& b) - -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, const TinyVector<3>& b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return dot(a, b); } - )); + )); scheme_module._addBuiltinFunction("dot", std::function( - [](const TinyVector<1> a, std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); } + [](const TinyVector<1> a, std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return dot(a, b); } )); scheme_module._addBuiltinFunction("dot", std::function( - [](const TinyVector<2> a, std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); } + [](const TinyVector<2> a, std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return dot(a, b); } )); - scheme_module._addBuiltinFunction("dot", std::function( + scheme_module._addBuiltinFunction("dot", + std::function( - [](const TinyVector<3>& a, std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); } + [](const TinyVector<3>& a, std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return dot(a, b); } - )); + )); scheme_module._addBuiltinFunction("det", std::function( - [](std::shared_ptr<const IDiscreteFunction> A) - -> std::shared_ptr<const IDiscreteFunction> { return det(A); } + [](std::shared_ptr<const DiscreteFunctionVariant> A) + -> std::shared_ptr<const DiscreteFunctionVariant> { return det(A); } )); - scheme_module._addBuiltinFunction("inverse", std::function( + scheme_module._addBuiltinFunction("inverse", + std::function( + + [](std::shared_ptr<const DiscreteFunctionVariant> A) + -> std::shared_ptr<const DiscreteFunctionVariant> { return inverse(A); } + + )); + + scheme_module._addBuiltinFunction("trace", std::function( + + [](std::shared_ptr<const DiscreteFunctionVariant> A) + -> std::shared_ptr<const DiscreteFunctionVariant> { return trace(A); } + + )); + scheme_module._addBuiltinFunction("min", + std::function( + + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> double { return min(a); } + + )); + + scheme_module._addBuiltinFunction("transpose", + std::function( - [](std::shared_ptr<const IDiscreteFunction> A) - -> std::shared_ptr<const IDiscreteFunction> { return inverse(A); } + [](std::shared_ptr<const DiscreteFunctionVariant> A) + -> std::shared_ptr<const DiscreteFunctionVariant> { return transpose(A); } - )); + )); scheme_module._addBuiltinFunction("min", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> double { return min(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, + std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return min(a, b); } )); scheme_module._addBuiltinFunction("min", std::function( - [](std::shared_ptr<const IDiscreteFunction> a, - std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return min(a, b); } + [](double a, std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return min(a, b); } )); scheme_module._addBuiltinFunction("min", std::function( - [](double a, std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return min(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, double b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return min(a, b); } )); - scheme_module._addBuiltinFunction("min", + scheme_module._addBuiltinFunction("max", std::function( - [](std::shared_ptr<const IDiscreteFunction> a, - double b) -> std::shared_ptr<const IDiscreteFunction> { return min(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> double { return max(a); } )); scheme_module._addBuiltinFunction("max", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> double { return max(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, + std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return max(a, b); } )); scheme_module._addBuiltinFunction("max", std::function( - [](std::shared_ptr<const IDiscreteFunction> a, - std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); } + [](double a, std::shared_ptr<const DiscreteFunctionVariant> b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return max(a, b); } )); scheme_module._addBuiltinFunction("max", std::function( - [](double a, std::shared_ptr<const IDiscreteFunction> b) - -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); } + [](std::shared_ptr<const DiscreteFunctionVariant> a, double b) + -> std::shared_ptr<const DiscreteFunctionVariant> { return max(a, b); } )); - scheme_module._addBuiltinFunction("max", - std::function( - - [](std::shared_ptr<const IDiscreteFunction> a, - double b) -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); } - - )); - scheme_module._addBuiltinFunction("sum_of_R", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> double { + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> double { return sum_of<double>(a); } )); - scheme_module._addBuiltinFunction("sum_of_R1", std::function( + scheme_module._addBuiltinFunction("sum_of_R1", + std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<1> { - return sum_of<TinyVector<1>>(a); - } + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyVector<1> { + return sum_of<TinyVector<1>>(a); + } - )); + )); - scheme_module._addBuiltinFunction("sum_of_R2", std::function( + scheme_module._addBuiltinFunction("sum_of_R2", + std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<2> { - return sum_of<TinyVector<2>>(a); - } + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyVector<2> { + return sum_of<TinyVector<2>>(a); + } - )); + )); - scheme_module._addBuiltinFunction("sum_of_R3", std::function( + scheme_module._addBuiltinFunction("sum_of_R3", + std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<3> { - return sum_of<TinyVector<3>>(a); - } + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyVector<3> { + return sum_of<TinyVector<3>>(a); + } - )); + )); - scheme_module._addBuiltinFunction("sum_of_R1x1", std::function( + scheme_module._addBuiltinFunction("sum_of_R1x1", + std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<1> { - return sum_of<TinyMatrix<1>>(a); - } + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyMatrix<1> { + return sum_of<TinyMatrix<1>>(a); + } - )); + )); - scheme_module._addBuiltinFunction("sum_of_R2x2", std::function( + scheme_module._addBuiltinFunction("sum_of_R2x2", + std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<2> { - return sum_of<TinyMatrix<2>>(a); - } + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyMatrix<2> { + return sum_of<TinyMatrix<2>>(a); + } - )); + )); - scheme_module._addBuiltinFunction("sum_of_R3x3", std::function( + scheme_module._addBuiltinFunction("sum_of_R3x3", + std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<3> { - return sum_of<TinyMatrix<3>>(a); - } + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyMatrix<3> { + return sum_of<TinyMatrix<3>>(a); + } - )); + )); - scheme_module._addBuiltinFunction("sum_of_Vh", - std::function( + scheme_module._addBuiltinFunction("sum_of_Vh", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) - -> std::shared_ptr<const IDiscreteFunction> { return sum_of_Vh_components(a); } + [](std::shared_ptr<const DiscreteFunctionVariant> a) + -> std::shared_ptr<const DiscreteFunctionVariant> { + return sum_of_Vh_components(a); + } - )); + )); - scheme_module - ._addBuiltinFunction("vectorize", - std::function( + scheme_module._addBuiltinFunction("vectorize", + std::function( - [](const std::vector<std::shared_ptr<const IDiscreteFunction>>& discrete_function_list) - -> std::shared_ptr<const IDiscreteFunction> { return vectorize(discrete_function_list); } + [](const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& + discrete_function_list) -> std::shared_ptr<const DiscreteFunctionVariant> { + return vectorize(discrete_function_list); + } - )); + )); scheme_module._addBuiltinFunction("integral_of_R", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> double { + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> double { return integral_of<double>(a); } @@ -365,7 +391,7 @@ MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module scheme_module._addBuiltinFunction("integral_of_R1", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<1> { + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyVector<1> { return integral_of<TinyVector<1>>(a); } @@ -374,7 +400,7 @@ MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module scheme_module._addBuiltinFunction("integral_of_R2", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<2> { + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyVector<2> { return integral_of<TinyVector<2>>(a); } @@ -383,7 +409,7 @@ MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module scheme_module._addBuiltinFunction("integral_of_R3", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<3> { + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyVector<3> { return integral_of<TinyVector<3>>(a); } @@ -392,7 +418,7 @@ MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module scheme_module._addBuiltinFunction("integral_of_R1x1", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<1> { + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyMatrix<1> { return integral_of<TinyMatrix<1>>(a); } @@ -401,7 +427,7 @@ MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module scheme_module._addBuiltinFunction("integral_of_R2x2", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<2> { + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyMatrix<2> { return integral_of<TinyMatrix<2>>(a); } @@ -410,7 +436,7 @@ MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module scheme_module._addBuiltinFunction("integral_of_R3x3", std::function( - [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<3> { + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> TinyMatrix<3> { return integral_of<TinyMatrix<3>>(a); } diff --git a/src/language/modules/MeshModule.cpp b/src/language/modules/MeshModule.cpp index 9c5cf3aec1e11d16f652357db53f68db54f6ed79..af1fca45e7dec5898a12731430358691728c7a2a 100644 --- a/src/language/modules/MeshModule.cpp +++ b/src/language/modules/MeshModule.cpp @@ -12,6 +12,7 @@ #include <language/utils/TypeDescriptor.hpp> #include <mesh/CartesianMeshBuilder.hpp> #include <mesh/Connectivity.hpp> +#include <mesh/ConnectivityUtils.hpp> #include <mesh/DualMeshManager.hpp> #include <mesh/GmshReader.hpp> #include <mesh/IBoundaryDescriptor.hpp> @@ -143,6 +144,37 @@ MeshModule::MeshModule() )); + this->_addBuiltinFunction("check_connectivity_ordering", + std::function( + + [](const std::shared_ptr<const IMesh>& i_mesh) -> bool { + switch (i_mesh->dimension()) { + case 1: { + using MeshType = Mesh<Connectivity<1>>; + + std::shared_ptr p_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh); + return checkConnectivityOrdering(p_mesh->connectivity()); + } + case 2: { + using MeshType = Mesh<Connectivity<2>>; + + std::shared_ptr p_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh); + return checkConnectivityOrdering(p_mesh->connectivity()); + } + case 3: { + using MeshType = Mesh<Connectivity<3>>; + + std::shared_ptr p_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh); + return checkConnectivityOrdering(p_mesh->connectivity()); + } + default: { + throw UnexpectedError("invalid dimension"); + } + } + } + + )); + this->_addBuiltinFunction("cartesianMesh", std::function( diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp index 4b4bdfaa9df4b98f9d3a343d2b991b61292c3280..1c888821f8d6c9c62e8ddc58ce23cd97c4f05b32 100644 --- a/src/language/modules/SchemeModule.cpp +++ b/src/language/modules/SchemeModule.cpp @@ -25,6 +25,7 @@ #include <scheme/DiscreteFunctionInterpoler.hpp> #include <scheme/DiscreteFunctionP0.hpp> #include <scheme/DiscreteFunctionUtils.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/DiscreteFunctionVectorIntegrator.hpp> #include <scheme/DiscreteFunctionVectorInterpoler.hpp> #include <scheme/ExternalBoundaryConditionDescriptor.hpp> @@ -33,7 +34,6 @@ #include <scheme/FreeBoundaryConditionDescriptor.hpp> #include <scheme/HyperelasticSolver.hpp> #include <scheme/IBoundaryConditionDescriptor.hpp> -#include <scheme/IDiscreteFunction.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> #include <scheme/NeumannBoundaryConditionDescriptor.hpp> #include <scheme/SymmetryBoundaryConditionDescriptor.hpp> @@ -43,7 +43,7 @@ SchemeModule::SchemeModule() { - this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IDiscreteFunction>>); + this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const DiscreteFunctionVariant>>); this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IDiscreteFunctionDescriptor>>); this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IQuadratureDescriptor>>); @@ -97,11 +97,11 @@ SchemeModule::SchemeModule() std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor, std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor, const std::vector<FunctionSymbolId>& function_id_list) - -> std::shared_ptr<const IDiscreteFunction> { - return DiscreteFunctionVectorIntegrator{mesh, integration_zone_list, - quadrature_descriptor, - discrete_function_descriptor, function_id_list} - .integrate(); + -> std::shared_ptr<const DiscreteFunctionVariant> { + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionVectorIntegrator{mesh, integration_zone_list, quadrature_descriptor, + discrete_function_descriptor, function_id_list} + .integrate()); } )); @@ -113,34 +113,40 @@ SchemeModule::SchemeModule() std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor, std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor, const std::vector<FunctionSymbolId>& function_id_list) - -> std::shared_ptr<const IDiscreteFunction> { - return DiscreteFunctionVectorIntegrator{mesh, quadrature_descriptor, - discrete_function_descriptor, function_id_list} - .integrate(); + -> std::shared_ptr<const DiscreteFunctionVariant> { + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionVectorIntegrator{mesh, quadrature_descriptor, + discrete_function_descriptor, function_id_list} + .integrate()); } )); - this->_addBuiltinFunction( - "integrate", - std::function( + this->_addBuiltinFunction("integrate", + std::function( - [](std::shared_ptr<const IMesh> mesh, - const std::vector<std::shared_ptr<const IZoneDescriptor>>& integration_zone_list, - std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor, - const FunctionSymbolId& function_id) -> std::shared_ptr<const IDiscreteFunction> { - return DiscreteFunctionIntegrator{mesh, integration_zone_list, quadrature_descriptor, function_id}.integrate(); - } + [](std::shared_ptr<const IMesh> mesh, + const std::vector<std::shared_ptr<const IZoneDescriptor>>& integration_zone_list, + std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor, + const FunctionSymbolId& function_id) + -> std::shared_ptr<const DiscreteFunctionVariant> { + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionIntegrator{mesh, integration_zone_list, quadrature_descriptor, + function_id} + .integrate()); + } - )); + )); this->_addBuiltinFunction("integrate", std::function( [](std::shared_ptr<const IMesh> mesh, std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor, - const FunctionSymbolId& function_id) -> std::shared_ptr<const IDiscreteFunction> { - return DiscreteFunctionIntegrator{mesh, quadrature_descriptor, function_id}.integrate(); + const FunctionSymbolId& function_id) + -> std::shared_ptr<const DiscreteFunctionVariant> { + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionIntegrator{mesh, quadrature_descriptor, function_id}.integrate()); } )); @@ -152,21 +158,22 @@ SchemeModule::SchemeModule() const std::vector<std::shared_ptr<const IZoneDescriptor>>& interpolation_zone_list, std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor, const std::vector<FunctionSymbolId>& function_id_list) - -> std::shared_ptr<const IDiscreteFunction> { + -> std::shared_ptr<const DiscreteFunctionVariant> { switch (discrete_function_descriptor->type()) { case DiscreteFunctionType::P0: { if (function_id_list.size() != 1) { throw NormalError("invalid function descriptor type"); } - return DiscreteFunctionInterpoler{mesh, interpolation_zone_list, - discrete_function_descriptor, function_id_list[0]} - .interpolate(); + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionInterpoler{mesh, interpolation_zone_list, + discrete_function_descriptor, function_id_list[0]} + .interpolate()); } case DiscreteFunctionType::P0Vector: { - return DiscreteFunctionVectorInterpoler{mesh, interpolation_zone_list, - discrete_function_descriptor, - function_id_list} - .interpolate(); + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionVectorInterpoler{mesh, interpolation_zone_list, + discrete_function_descriptor, function_id_list} + .interpolate()); } default: { throw NormalError("invalid function descriptor type"); @@ -176,30 +183,35 @@ SchemeModule::SchemeModule() )); - this->_addBuiltinFunction( - "interpolate", - std::function( - - [](std::shared_ptr<const IMesh> mesh, - std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor, - const std::vector<FunctionSymbolId>& function_id_list) -> std::shared_ptr<const IDiscreteFunction> { - switch (discrete_function_descriptor->type()) { - case DiscreteFunctionType::P0: { - if (function_id_list.size() != 1) { - throw NormalError("invalid function descriptor type"); - } - return DiscreteFunctionInterpoler{mesh, discrete_function_descriptor, function_id_list[0]}.interpolate(); - } - case DiscreteFunctionType::P0Vector: { - return DiscreteFunctionVectorInterpoler{mesh, discrete_function_descriptor, function_id_list}.interpolate(); - } - default: { - throw NormalError("invalid function descriptor type"); - } - } - } - - )); + this->_addBuiltinFunction("interpolate", + std::function( + + [](std::shared_ptr<const IMesh> mesh, + std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor, + const std::vector<FunctionSymbolId>& function_id_list) + -> std::shared_ptr<const DiscreteFunctionVariant> { + switch (discrete_function_descriptor->type()) { + case DiscreteFunctionType::P0: { + if (function_id_list.size() != 1) { + throw NormalError("invalid function descriptor type"); + } + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionInterpoler{mesh, discrete_function_descriptor, function_id_list[0]} + .interpolate()); + } + case DiscreteFunctionType::P0Vector: { + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionVectorInterpoler{mesh, discrete_function_descriptor, + function_id_list} + .interpolate()); + } + default: { + throw NormalError("invalid function descriptor type"); + } + } + } + + )); this->_addBuiltinFunction("randomizeMesh", std::function( @@ -303,10 +315,10 @@ SchemeModule::SchemeModule() this->_addBuiltinFunction("glace_fluxes", std::function( - [](const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& c, - const std::shared_ptr<const IDiscreteFunction>& p, + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& c, + const std::shared_ptr<const DiscreteFunctionVariant>& p, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) -> std::tuple<std::shared_ptr<const ItemValueVariant>, @@ -322,17 +334,17 @@ SchemeModule::SchemeModule() this->_addBuiltinFunction("glace_solver", std::function( - [](const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& c, - const std::shared_ptr<const IDiscreteFunction>& p, + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& c, + const std::shared_ptr<const DiscreteFunctionVariant>& p, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list, - const double& dt) - -> std::tuple<std::shared_ptr<const IMesh>, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> { + const double& dt) -> std::tuple<std::shared_ptr<const IMesh>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> { return AcousticSolverHandler{getCommonMesh({rho, u, E, c, p})} .solver() .apply(AcousticSolverHandler::SolverType::Glace, dt, rho, u, E, c, p, @@ -344,10 +356,10 @@ SchemeModule::SchemeModule() this->_addBuiltinFunction("eucclhyd_fluxes", std::function( - [](const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& c, - const std::shared_ptr<const IDiscreteFunction>& p, + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& c, + const std::shared_ptr<const DiscreteFunctionVariant>& p, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) -> std::tuple<std::shared_ptr<const ItemValueVariant>, @@ -363,17 +375,17 @@ SchemeModule::SchemeModule() this->_addBuiltinFunction("eucclhyd_solver", std::function( - [](const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& c, - const std::shared_ptr<const IDiscreteFunction>& p, + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& c, + const std::shared_ptr<const DiscreteFunctionVariant>& p, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list, - const double& dt) - -> std::tuple<std::shared_ptr<const IMesh>, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> { + const double& dt) -> std::tuple<std::shared_ptr<const IMesh>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> { return AcousticSolverHandler{getCommonMesh({rho, u, E, c, p})} .solver() .apply(AcousticSolverHandler::SolverType::Eucclhyd, dt, rho, u, E, c, p, @@ -382,23 +394,62 @@ SchemeModule::SchemeModule() )); + this->_addBuiltinFunction("apply_acoustic_fluxes", + std::function( + + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, // + const std::shared_ptr<const DiscreteFunctionVariant>& u, // + const std::shared_ptr<const DiscreteFunctionVariant>& E, // + const std::shared_ptr<const ItemValueVariant>& ur, // + const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr, // + const double& dt) -> std::tuple<std::shared_ptr<const IMesh>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> { + return AcousticSolverHandler{getCommonMesh({rho, u, E})} // + .solver() + .apply_fluxes(dt, rho, u, E, ur, Fjr); + } + + )); + + this->_addBuiltinFunction("hyperelastic_eucclhyd_fluxes", + std::function( + + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& aL, + const std::shared_ptr<const DiscreteFunctionVariant>& aT, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& sigma, + const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& + bc_descriptor_list) + -> std::tuple<std::shared_ptr<const ItemValueVariant>, + std::shared_ptr<const SubItemValuePerItemVariant>> { + return HyperelasticSolverHandler{getCommonMesh({rho, aL, aT, u, sigma})} + .solver() + .compute_fluxes(HyperelasticSolverHandler::SolverType::Eucclhyd, rho, aL, aT, u, + sigma, bc_descriptor_list); + } + + )); + this->_addBuiltinFunction("hyperelastic_eucclhyd_solver", std::function( - [](const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& CG, - const std::shared_ptr<const IDiscreteFunction>& aL, - const std::shared_ptr<const IDiscreteFunction>& aT, - const std::shared_ptr<const IDiscreteFunction>& sigma, + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& CG, + const std::shared_ptr<const DiscreteFunctionVariant>& aL, + const std::shared_ptr<const DiscreteFunctionVariant>& aT, + const std::shared_ptr<const DiscreteFunctionVariant>& sigma, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list, - const double& dt) - -> std::tuple<std::shared_ptr<const IMesh>, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> { + const double& dt) -> std::tuple<std::shared_ptr<const IMesh>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> { return HyperelasticSolverHandler{getCommonMesh({rho, u, E, CG, aL, aT, sigma})} .solver() .apply(HyperelasticSolverHandler::SolverType::Eucclhyd, dt, rho, u, E, CG, aL, aT, @@ -407,23 +458,43 @@ SchemeModule::SchemeModule() )); + this->_addBuiltinFunction("hyperelastic_glace_fluxes", + std::function( + + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& aL, + const std::shared_ptr<const DiscreteFunctionVariant>& aT, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& sigma, + const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& + bc_descriptor_list) + -> std::tuple<std::shared_ptr<const ItemValueVariant>, + std::shared_ptr<const SubItemValuePerItemVariant>> { + return HyperelasticSolverHandler{getCommonMesh({rho, aL, aT, u, sigma})} + .solver() + .compute_fluxes(HyperelasticSolverHandler::SolverType::Glace, // + rho, aL, aT, u, sigma, bc_descriptor_list); + } + + )); + this->_addBuiltinFunction("hyperelastic_glace_solver", std::function( - [](const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& CG, - const std::shared_ptr<const IDiscreteFunction>& aL, - const std::shared_ptr<const IDiscreteFunction>& aT, - const std::shared_ptr<const IDiscreteFunction>& sigma, + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& CG, + const std::shared_ptr<const DiscreteFunctionVariant>& aL, + const std::shared_ptr<const DiscreteFunctionVariant>& aT, + const std::shared_ptr<const DiscreteFunctionVariant>& sigma, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list, - const double& dt) - -> std::tuple<std::shared_ptr<const IMesh>, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> { + const double& dt) -> std::tuple<std::shared_ptr<const IMesh>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> { return HyperelasticSolverHandler{getCommonMesh({rho, u, E, CG, aL, aT, sigma})} .solver() .apply(HyperelasticSolverHandler::SolverType::Glace, dt, rho, u, E, CG, aL, aT, sigma, @@ -432,21 +503,23 @@ SchemeModule::SchemeModule() )); - this->_addBuiltinFunction("apply_acoustic_fluxes", + this->_addBuiltinFunction("apply_hyperelastic_fluxes", std::function( - [](const std::shared_ptr<const IDiscreteFunction>& rho, // - const std::shared_ptr<const IDiscreteFunction>& u, // - const std::shared_ptr<const IDiscreteFunction>& E, // + [](const std::shared_ptr<const DiscreteFunctionVariant>& rho, // + const std::shared_ptr<const DiscreteFunctionVariant>& u, // + const std::shared_ptr<const DiscreteFunctionVariant>& E, // + const std::shared_ptr<const DiscreteFunctionVariant>& CG, // const std::shared_ptr<const ItemValueVariant>& ur, // const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr, // - const double& dt) - -> std::tuple<std::shared_ptr<const IMesh>, std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> { - return AcousticSolverHandler{getCommonMesh({rho, u, E})} // + const double& dt) -> std::tuple<std::shared_ptr<const IMesh>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> { + return HyperelasticSolverHandler{getCommonMesh({rho, u, E, CG})} // .solver() - .apply_fluxes(dt, rho, u, E, ur, Fjr); + .apply_fluxes(dt, rho, u, E, CG, ur, Fjr); } )); @@ -455,67 +528,68 @@ SchemeModule::SchemeModule() std::function( [](const std::shared_ptr<const IMesh>& mesh, - const std::shared_ptr<const IDiscreteFunction>& v) - -> std::shared_ptr<const IDiscreteFunction> { return shallowCopy(mesh, v); } + const std::shared_ptr<const DiscreteFunctionVariant>& v) + -> std::shared_ptr<const DiscreteFunctionVariant> { return shallowCopy(mesh, v); } )); - this->_addBuiltinFunction("acoustic_dt", + this->_addBuiltinFunction("acoustic_dt", std::function( + + [](const std::shared_ptr<const DiscreteFunctionVariant>& c) -> double { + return acoustic_dt(c); + } + + )); + + this->_addBuiltinFunction("cell_volume", std::function( - [](const std::shared_ptr<const IDiscreteFunction>& c) -> double { return acoustic_dt(c); } + [](const std::shared_ptr<const IMesh>& i_mesh) + -> std::shared_ptr<const DiscreteFunctionVariant> { + switch (i_mesh->dimension()) { + case 1: { + constexpr size_t Dimension = 1; + using MeshType = Mesh<Connectivity<Dimension>>; + std::shared_ptr<const MeshType> mesh = + std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(i_mesh); + + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionP0(mesh, MeshDataManager::instance().getMeshData(*mesh).Vj())); + } + case 2: { + constexpr size_t Dimension = 2; + using MeshType = Mesh<Connectivity<Dimension>>; + std::shared_ptr<const MeshType> mesh = + std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(i_mesh); + + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionP0(mesh, MeshDataManager::instance().getMeshData(*mesh).Vj())); + } + case 3: { + constexpr size_t Dimension = 3; + using MeshType = Mesh<Connectivity<Dimension>>; + std::shared_ptr<const MeshType> mesh = + std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(i_mesh); + + return std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionP0(mesh, MeshDataManager::instance().getMeshData(*mesh).Vj())); + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } )); this->_addBuiltinFunction("hyperelastic_dt", std::function( - [](const std::shared_ptr<const IDiscreteFunction>& c) -> double { + [](const std::shared_ptr<const DiscreteFunctionVariant>& c) -> double { return hyperelastic_dt(c); } )); - this - ->_addBuiltinFunction("cell_volume", - std::function( - - [](const std::shared_ptr<const IMesh>& i_mesh) -> std::shared_ptr<const IDiscreteFunction> { - switch (i_mesh->dimension()) { - case 1: { - constexpr size_t Dimension = 1; - using MeshType = Mesh<Connectivity<Dimension>>; - std::shared_ptr<const MeshType> mesh = - std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(i_mesh); - - return std::make_shared<const DiscreteFunctionP0< - Dimension, double>>(mesh, copy(MeshDataManager::instance().getMeshData(*mesh).Vj())); - } - case 2: { - constexpr size_t Dimension = 2; - using MeshType = Mesh<Connectivity<Dimension>>; - std::shared_ptr<const MeshType> mesh = - std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(i_mesh); - - return std::make_shared<const DiscreteFunctionP0< - Dimension, double>>(mesh, copy(MeshDataManager::instance().getMeshData(*mesh).Vj())); - } - case 3: { - constexpr size_t Dimension = 3; - using MeshType = Mesh<Connectivity<Dimension>>; - std::shared_ptr<const MeshType> mesh = - std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(i_mesh); - - return std::make_shared<const DiscreteFunctionP0< - Dimension, double>>(mesh, copy(MeshDataManager::instance().getMeshData(*mesh).Vj())); - } - default: { - throw UnexpectedError("invalid mesh dimension"); - } - } - } - - )); - MathFunctionRegisterForVh{*this}; } diff --git a/src/language/modules/SchemeModule.hpp b/src/language/modules/SchemeModule.hpp index 6c1f0324aa2858437ec8d7f49434c2d8ac718a45..d56a5ec74069bd23d8169f25ff8a829c7c4a53ff 100644 --- a/src/language/modules/SchemeModule.hpp +++ b/src/language/modules/SchemeModule.hpp @@ -10,9 +10,9 @@ template <> inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IBoundaryConditionDescriptor>> = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("boundary_condition"); -class IDiscreteFunction; +class DiscreteFunctionVariant; template <> -inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IDiscreteFunction>> = +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const DiscreteFunctionVariant>> = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("Vh"); class IDiscreteFunctionDescriptor; diff --git a/src/language/modules/UnaryOperatorRegisterForVh.cpp b/src/language/modules/UnaryOperatorRegisterForVh.cpp index b1dc85aa9dd11be2f5a6d159d8f1a70254d68c7b..e2e9c2db9b72a9a687806d24dee836cfd37a22e8 100644 --- a/src/language/modules/UnaryOperatorRegisterForVh.cpp +++ b/src/language/modules/UnaryOperatorRegisterForVh.cpp @@ -3,10 +3,9 @@ #include <language/modules/SchemeModule.hpp> #include <language/utils/DataHandler.hpp> #include <language/utils/DataVariant.hpp> -#include <language/utils/EmbeddedIDiscreteFunctionOperators.hpp> +#include <language/utils/EmbeddedDiscreteFunctionOperators.hpp> #include <language/utils/OperatorRepository.hpp> #include <language/utils/UnaryOperatorProcessorBuilder.hpp> -#include <scheme/IDiscreteFunction.hpp> void UnaryOperatorRegisterForVh::_register_unary_minus() @@ -14,8 +13,9 @@ 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>>>()); + std::make_shared< + UnaryOperatorProcessorBuilder<language::unary_minus, std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>>>()); } UnaryOperatorRegisterForVh::UnaryOperatorRegisterForVh() diff --git a/src/language/modules/WriterModule.cpp b/src/language/modules/WriterModule.cpp index 6523d56a93d4fe0b4f953fb6065cd4a15be7330c..aa479c0eb94005d59000d98dd460d8fedb89ab21 100644 --- a/src/language/modules/WriterModule.cpp +++ b/src/language/modules/WriterModule.cpp @@ -12,9 +12,7 @@ #include <output/NamedDiscreteFunction.hpp> #include <output/NamedItemValueVariant.hpp> #include <output/VTKWriter.hpp> -#include <scheme/DiscreteFunctionP0.hpp> -#include <scheme/IDiscreteFunction.hpp> -#include <scheme/IDiscreteFunctionDescriptor.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> WriterModule::WriterModule() { @@ -75,7 +73,7 @@ WriterModule::WriterModule() this->_addBuiltinFunction("name_output", std::function( - [](std::shared_ptr<const IDiscreteFunction> discrete_function, + [](std::shared_ptr<const DiscreteFunctionVariant> discrete_function, const std::string& name) -> std::shared_ptr<const INamedDiscreteData> { return std::make_shared<const NamedDiscreteFunction>(discrete_function, name); diff --git a/src/language/modules/WriterModule.hpp b/src/language/modules/WriterModule.hpp index f61eafb0e4847c248e9def011bf269b3b9a4022e..97bef5a78ac6f90cff1af303bed901c4c46c665a 100644 --- a/src/language/modules/WriterModule.hpp +++ b/src/language/modules/WriterModule.hpp @@ -7,7 +7,6 @@ class OutputNamedItemValueSet; class INamedDiscreteData; -class IDiscreteFunction; #include <string> diff --git a/src/language/utils/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp index c3f015c5b61fbdfda66ee78bbf928fe3a24f3de0..460ec3e866be479633e5bf9a9a416c1f84fc09e6 100644 --- a/src/language/utils/BuiltinFunctionEmbedder.hpp +++ b/src/language/utils/BuiltinFunctionEmbedder.hpp @@ -40,19 +40,25 @@ template <typename FX, typename... Args> class BuiltinFunctionEmbedderBase<FX(Args...)> : public IBuiltinFunctionEmbedder { protected: - template <size_t I> - PUGS_INLINE void constexpr _check_value() const + template <typename ValueT> + PUGS_INLINE void constexpr _check_value_type() const { - using ValueN_T = std::tuple_element_t<I, FX>; - if constexpr (std::is_lvalue_reference_v<ValueN_T>) { - static_assert(std::is_const_v<std::remove_reference_t<ValueN_T>>, + if constexpr (std::is_lvalue_reference_v<ValueT>) { + static_assert(std::is_const_v<std::remove_reference_t<ValueT>>, "builtin function return values are non mutable use 'const' when passing references"); } - if constexpr (is_std_ptr_v<ValueN_T>) { - static_assert(std::is_const_v<typename ValueN_T::element_type>, + if constexpr (is_std_ptr_v<ValueT>) { + static_assert(std::is_const_v<typename ValueT::element_type>, "builtin function return values are non mutable. For instance use std::shared_ptr<const T>"); } + } + + template <size_t I> + PUGS_INLINE void constexpr _check_value() const + { + using ValueN_T = std::tuple_element_t<I, FX>; + _check_value_type<ValueN_T>(); if (ast_node_data_type_from<std::remove_cv_t<std::remove_reference_t<ValueN_T>>> == ASTNodeDataType::undefined_t) { throw std::invalid_argument(std::string{"cannot bind C++ to language.\nnote: return value number "} + @@ -79,6 +85,7 @@ class BuiltinFunctionEmbedderBase<FX(Args...)> : public IBuiltinFunctionEmbedder std::string{"cannot bind C++ to language.\nnote: return value has no associated language type: "} + demangle<FX>()); } + _check_value_type<FX>(); } } @@ -99,8 +106,7 @@ class BuiltinFunctionEmbedderBase<FX(Args...)> : public IBuiltinFunctionEmbedder } template <size_t... I> - PUGS_INLINE std::vector<std::shared_ptr<const ASTNodeDataType>> - _getCompoundDataTypes(std::index_sequence<I...>) const + PUGS_INLINE std::vector<std::shared_ptr<const ASTNodeDataType>> _getCompoundDataTypes(std::index_sequence<I...>) const { std::vector<std::shared_ptr<const ASTNodeDataType>> compound_type_list; (compound_type_list.push_back(std::make_shared<ASTNodeDataType>(this->_getOneElementDataType<FX, I>())), ...); @@ -266,8 +272,7 @@ class BuiltinFunctionEmbedder<FX(Args...)> : public BuiltinFunctionEmbedderBase< } template <size_t... I> - PUGS_INLINE std::vector<ASTNodeDataType> - _getParameterDataTypes(std::index_sequence<I...>) const + PUGS_INLINE std::vector<ASTNodeDataType> _getParameterDataTypes(std::index_sequence<I...>) const { std::vector<ASTNodeDataType> parameter_type_list; (parameter_type_list.push_back(this->template _getOneElementDataType<ArgsTuple, I>()), ...); diff --git a/src/language/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt index 0fe1c798ba77d98b4453ded4d4c3334c0d2199e5..a81ffa8aecdf7af0085296b181f2b3ec4d63238f 100644 --- a/src/language/utils/CMakeLists.txt +++ b/src/language/utils/CMakeLists.txt @@ -23,9 +23,8 @@ add_library(PugsLanguageUtils BuiltinFunctionEmbedderUtils.cpp DataVariant.cpp EmbeddedData.cpp - EmbeddedIDiscreteFunctionMathFunctions.cpp - EmbeddedIDiscreteFunctionOperators.cpp - EmbeddedIDiscreteFunctionUtils.cpp + EmbeddedDiscreteFunctionMathFunctions.cpp + EmbeddedDiscreteFunctionOperators.cpp FunctionSymbolId.cpp IncDecOperatorRegisterForN.cpp IncDecOperatorRegisterForZ.cpp diff --git a/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.cpp b/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d820c561f623d01967c6a4d947eaa91a531e183 --- /dev/null +++ b/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.cpp @@ -0,0 +1,647 @@ +#include <language/utils/EmbeddedDiscreteFunctionMathFunctions.hpp> + +#include <language/utils/EmbeddedDiscreteFunctionUtils.hpp> +#include <mesh/IMesh.hpp> +#include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionUtils.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> +#include <scheme/IDiscreteFunctionDescriptor.hpp> + +#include <utils/Demangle.hpp> + +#define DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(FUNCTION, ARG) \ + return std::visit( \ + [&](auto&& discrete_function) -> std::shared_ptr<DiscreteFunctionVariant> { \ + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; \ + if constexpr (std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<1, const double>> or \ + std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<2, const double>> or \ + std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<3, const double>>) { \ + return std::make_shared<DiscreteFunctionVariant>(FUNCTION(discrete_function)); \ + } else { \ + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(ARG)); \ + } \ + }, \ + ARG->discreteFunction()); + +#define DISCRETE_VH_TO_R_CALL(FUNCTION, ARG) \ + return std::visit( \ + [&](auto&& discrete_function) -> double { \ + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; \ + if constexpr (std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<1, const double>> or \ + std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<2, const double>> or \ + std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<3, const double>>) { \ + return FUNCTION(discrete_function); \ + } else { \ + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(ARG)); \ + } \ + }, \ + ARG->discreteFunction()); + +#define DISCRETE_VH_VH_TO_VH_REAL_FUNCTION_CALL(FUNCTION, ARG0, ARG1) \ + if (not hasSameMesh({ARG0, ARG1})) { \ + throw NormalError("operands are defined on different meshes"); \ + } \ + return std::visit( \ + [&](auto&& f, auto&& g) -> std::shared_ptr<DiscreteFunctionVariant> { \ + using TypeOfF = std::decay_t<decltype(f)>; \ + using TypeOfG = std::decay_t<decltype(g)>; \ + if constexpr (std::is_same_v<TypeOfF, DiscreteFunctionP0<1, const double>> or \ + std::is_same_v<TypeOfF, DiscreteFunctionP0<2, const double>> or \ + std::is_same_v<TypeOfF, DiscreteFunctionP0<3, const double>>) { \ + if constexpr (std::is_same_v<TypeOfF, TypeOfG>) { \ + return std::make_shared<DiscreteFunctionVariant>(FUNCTION(f, g)); \ + } else { \ + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); \ + } \ + } else { \ + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); \ + } \ + }, \ + ARG0->discreteFunction(), ARG1->discreteFunction()); + +#define DISCRETE_R_VH_TO_VH_REAL_FUNCTION_CALL(FUNCTION, ARG0, ARG1) \ + return std::visit( \ + [&](auto&& discrete_function) -> std::shared_ptr<DiscreteFunctionVariant> { \ + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; \ + if constexpr (std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<1, const double>> or \ + std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<2, const double>> or \ + std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<3, const double>>) { \ + return std::make_shared<DiscreteFunctionVariant>(FUNCTION(ARG0, discrete_function)); \ + } else { \ + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(ARG0, discrete_function)); \ + } \ + }, \ + ARG1->discreteFunction()); + +#define DISCRETE_VH_R_TO_VH_REAL_FUNCTION_CALL(FUNCTION, ARG0, ARG1) \ + return std::visit( \ + [&](auto&& discrete_function) -> std::shared_ptr<DiscreteFunctionVariant> { \ + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; \ + if constexpr (std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<1, const double>> or \ + std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<2, const double>> or \ + std::is_same_v<DiscreteFunctionType, DiscreteFunctionP0<3, const double>>) { \ + return std::make_shared<DiscreteFunctionVariant>(FUNCTION(discrete_function, ARG1)); \ + } else { \ + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(discrete_function, ARG1)); \ + } \ + }, \ + ARG0->discreteFunction()); + +std::shared_ptr<const DiscreteFunctionVariant> +sqrt(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(sqrt, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +abs(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(abs, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +sin(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(sin, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +cos(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(cos, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +tan(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(tan, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +asin(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(asin, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +acos(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(acos, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +atan(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(atan, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +atan2(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + DISCRETE_VH_VH_TO_VH_REAL_FUNCTION_CALL(atan2, f_v, g_v); +} + +std::shared_ptr<const DiscreteFunctionVariant> +atan2(const double a, const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_R_VH_TO_VH_REAL_FUNCTION_CALL(atan2, a, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +atan2(const std::shared_ptr<const DiscreteFunctionVariant>& f, const double a) +{ + DISCRETE_VH_R_TO_VH_REAL_FUNCTION_CALL(atan2, f, a); +} + +std::shared_ptr<const DiscreteFunctionVariant> +sinh(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(sinh, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +cosh(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(cosh, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +tanh(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(tanh, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +asinh(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(asinh, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +acosh(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(acosh, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +atanh(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(atanh, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +exp(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(exp, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +log(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(log, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +pow(const std::shared_ptr<const DiscreteFunctionVariant>& f, const std::shared_ptr<const DiscreteFunctionVariant>& g) +{ + DISCRETE_VH_VH_TO_VH_REAL_FUNCTION_CALL(pow, f, g); +} + +std::shared_ptr<const DiscreteFunctionVariant> +pow(const double a, const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_R_VH_TO_VH_REAL_FUNCTION_CALL(pow, a, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +pow(const std::shared_ptr<const DiscreteFunctionVariant>& f, const double a) +{ + DISCRETE_VH_R_TO_VH_REAL_FUNCTION_CALL(pow, f, a); +} + +std::shared_ptr<const DiscreteFunctionVariant> +dot(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + if (not hasSameMesh({f_v, g_v})) { + throw NormalError("operands are defined on different meshes"); + } + + return std::visit( + [&](auto&& f, auto&& g) -> std::shared_ptr<DiscreteFunctionVariant> { + using TypeOfF = std::decay_t<decltype(f)>; + using TypeOfG = std::decay_t<decltype(g)>; + if constexpr (not std::is_same_v<TypeOfF, TypeOfG>) { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); + } else { + using DataType = std::decay_t<typename TypeOfF::data_type>; + if constexpr (is_discrete_function_P0_v<TypeOfF>) { + if constexpr (is_tiny_vector_v<DataType>) { + return std::make_shared<DiscreteFunctionVariant>(dot(f, g)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + } else if constexpr (is_discrete_function_P0_vector_v<TypeOfF>) { + if (f.size() == g.size()) { + return std::make_shared<DiscreteFunctionVariant>(dot(f, g)); + } else { + throw NormalError("operands have different dimension"); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + } + }, + f_v->discreteFunction(), g_v->discreteFunction()); +} + +template <size_t VectorDimension> +std::shared_ptr<const DiscreteFunctionVariant> +dot(const std::shared_ptr<const DiscreteFunctionVariant>& f, const TinyVector<VectorDimension>& a) +{ + return std::visit( + [&](auto&& discrete_function0) -> std::shared_ptr<DiscreteFunctionVariant> { + using DiscreteFunction0Type = std::decay_t<decltype(discrete_function0)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunction0Type>) { + using DataType = std::decay_t<typename DiscreteFunction0Type::data_type>; + if constexpr (is_tiny_vector_v<DataType>) { + if constexpr (std::is_same_v<DataType, TinyVector<VectorDimension>>) { + return std::make_shared<DiscreteFunctionVariant>(dot(discrete_function0, a)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + }, + f->discreteFunction()); +} + +template <size_t VectorDimension> +std::shared_ptr<const DiscreteFunctionVariant> +dot(const TinyVector<VectorDimension>& a, const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + return std::visit( + [&](auto&& discrete_function0) -> std::shared_ptr<DiscreteFunctionVariant> { + using DiscreteFunction0Type = std::decay_t<decltype(discrete_function0)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunction0Type>) { + using DataType = std::decay_t<typename DiscreteFunction0Type::data_type>; + if constexpr (is_tiny_vector_v<DataType>) { + if constexpr (std::is_same_v<DataType, TinyVector<VectorDimension>>) { + return std::make_shared<DiscreteFunctionVariant>(dot(a, discrete_function0)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + }, + f->discreteFunction()); +} + +template std::shared_ptr<const DiscreteFunctionVariant> dot(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<1>&); + +template std::shared_ptr<const DiscreteFunctionVariant> dot(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<2>&); + +template std::shared_ptr<const DiscreteFunctionVariant> dot(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<3>&); + +template std::shared_ptr<const DiscreteFunctionVariant> dot(const TinyVector<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +template std::shared_ptr<const DiscreteFunctionVariant> dot(const TinyVector<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +template std::shared_ptr<const DiscreteFunctionVariant> dot(const TinyVector<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> +det(const std::shared_ptr<const DiscreteFunctionVariant>& A) +{ + return std::visit( + [&](auto&& discrete_function) -> std::shared_ptr<DiscreteFunctionVariant> { + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunctionType>) { + if constexpr (is_tiny_matrix_v<std::decay_t<typename DiscreteFunctionType::data_type>>) { + if constexpr (DiscreteFunctionType::data_type::NumberOfRows == + DiscreteFunctionType::data_type::NumberOfColumns) { + return std::make_shared<DiscreteFunctionVariant>(det(discrete_function)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + }, + A->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +trace(const std::shared_ptr<const DiscreteFunctionVariant>& A) +{ + return std::visit( + [&](auto&& discrete_function) -> std::shared_ptr<DiscreteFunctionVariant> { + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunctionType>) { + if constexpr (is_tiny_matrix_v<std::decay_t<typename DiscreteFunctionType::data_type>>) { + if constexpr (DiscreteFunctionType::data_type::NumberOfRows == + DiscreteFunctionType::data_type::NumberOfColumns) { + return std::make_shared<DiscreteFunctionVariant>(trace(discrete_function)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + }, + A->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +inverse(const std::shared_ptr<const DiscreteFunctionVariant>& A) +{ + return std::visit( + [&](auto&& discrete_function) -> std::shared_ptr<DiscreteFunctionVariant> { + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunctionType>) { + if constexpr (is_tiny_matrix_v<std::decay_t<typename DiscreteFunctionType::data_type>>) { + if constexpr (DiscreteFunctionType::data_type::NumberOfRows == + DiscreteFunctionType::data_type::NumberOfColumns) { + return std::make_shared<DiscreteFunctionVariant>(inverse(discrete_function)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + }, + A->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +transpose(const std::shared_ptr<const DiscreteFunctionVariant>& A) +{ + return std::visit( + [&](auto&& discrete_function) -> std::shared_ptr<DiscreteFunctionVariant> { + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunctionType>) { + if constexpr (is_tiny_matrix_v<std::decay_t<typename DiscreteFunctionType::data_type>>) { + if constexpr (DiscreteFunctionType::data_type::NumberOfRows == + DiscreteFunctionType::data_type::NumberOfColumns) { + return std::make_shared<DiscreteFunctionVariant>(transpose(discrete_function)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(A)); + } + }, + A->discreteFunction()); +} + +double +min(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_R_CALL(min, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +min(const std::shared_ptr<const DiscreteFunctionVariant>& f, const std::shared_ptr<const DiscreteFunctionVariant>& g) +{ + DISCRETE_VH_VH_TO_VH_REAL_FUNCTION_CALL(min, f, g); +} + +std::shared_ptr<const DiscreteFunctionVariant> +min(const double a, const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_R_VH_TO_VH_REAL_FUNCTION_CALL(min, a, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +min(const std::shared_ptr<const DiscreteFunctionVariant>& f, const double a) +{ + DISCRETE_VH_R_TO_VH_REAL_FUNCTION_CALL(min, f, a); +} + +double +max(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_VH_TO_R_CALL(max, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +max(const std::shared_ptr<const DiscreteFunctionVariant>& f, const std::shared_ptr<const DiscreteFunctionVariant>& g) +{ + DISCRETE_VH_VH_TO_VH_REAL_FUNCTION_CALL(max, f, g); +} + +std::shared_ptr<const DiscreteFunctionVariant> +max(const double a, const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + DISCRETE_R_VH_TO_VH_REAL_FUNCTION_CALL(max, a, f); +} + +std::shared_ptr<const DiscreteFunctionVariant> +max(const std::shared_ptr<const DiscreteFunctionVariant>& f, const double a) +{ + DISCRETE_VH_R_TO_VH_REAL_FUNCTION_CALL(max, f, a); +} + +template <typename ValueT> +ValueT +sum_of(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + ValueT value; + std::visit( + [&](auto&& discrete_function) { + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunctionType>) { + using DataType = std::decay_t<typename DiscreteFunctionType::data_type>; + if constexpr (std::is_same_v<ValueT, DataType>) { + value = sum(discrete_function); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + }, + f->discreteFunction()); + + return value; +} + +std::shared_ptr<const DiscreteFunctionVariant> +sum_of_Vh_components(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + return std::visit( + [&](auto&& discrete_function) -> std::shared_ptr<const DiscreteFunctionVariant> { + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionType>) { + using DataType = std::decay_t<typename DiscreteFunctionType::data_type>; + static_assert(std::is_same_v<DataType, double>); + return std::make_shared<DiscreteFunctionVariant>(sumOfComponents(discrete_function)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + }, + f->discreteFunction()); +} + +template <size_t Dimension> +void +vectorize_to(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_list, + const Mesh<Connectivity<Dimension>>& mesh, + DiscreteFunctionP0Vector<Dimension, double>& discrete_vector_function) +{ + if (hasSameMesh(discrete_function_list)) { + for (size_t i_discrete_function = 0; i_discrete_function < discrete_function_list.size(); ++i_discrete_function) { + std::visit( + [&](auto&& discrete_function) { + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunctionType>) { + using DataType = std::remove_const_t<typename DiscreteFunctionType::data_type>; + if constexpr (std::is_same_v<DataType, double> and + (Dimension == DiscreteFunctionType::MeshType::Dimension)) { + const auto& connectivity = mesh.connectivity(); + parallel_for( + connectivity.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + discrete_vector_function[cell_id][i_discrete_function] = discrete_function[cell_id]; + }); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(discrete_function)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(discrete_function)); + } + }, + discrete_function_list[i_discrete_function]->discreteFunction()); + } + + } else { + throw NormalError("discrete functions are not defined on the same mesh"); + } +} + +std::shared_ptr<const DiscreteFunctionVariant> +vectorize(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_list) +{ + if (hasSameMesh(discrete_function_list)) { + std::shared_ptr p_i_mesh = getCommonMesh(discrete_function_list); + Assert(p_i_mesh.use_count() > 0); + + switch (p_i_mesh->dimension()) { + case 1: { + constexpr size_t Dimension = 1; + using DiscreteFunctionVectorType = DiscreteFunctionP0Vector<Dimension, double>; + std::shared_ptr<const Mesh<Connectivity<Dimension>>> p_mesh = + std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(p_i_mesh); + + DiscreteFunctionVectorType vector_function(p_mesh, discrete_function_list.size()); + vectorize_to(discrete_function_list, *p_mesh, vector_function); + + return std::make_shared<DiscreteFunctionVariant>(vector_function); + } + case 2: { + constexpr size_t Dimension = 2; + using DiscreteFunctionVectorType = DiscreteFunctionP0Vector<Dimension, double>; + std::shared_ptr<const Mesh<Connectivity<Dimension>>> p_mesh = + std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(p_i_mesh); + + DiscreteFunctionVectorType vector_function(p_mesh, discrete_function_list.size()); + vectorize_to(discrete_function_list, *p_mesh, vector_function); + + return std::make_shared<DiscreteFunctionVariant>(vector_function); + } + case 3: { + constexpr size_t Dimension = 3; + using DiscreteFunctionVectorType = DiscreteFunctionP0Vector<Dimension, double>; + std::shared_ptr<const Mesh<Connectivity<Dimension>>> p_mesh = + std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(p_i_mesh); + + DiscreteFunctionVectorType vector_function(p_mesh, discrete_function_list.size()); + vectorize_to(discrete_function_list, *p_mesh, vector_function); + + return std::make_shared<DiscreteFunctionVariant>(vector_function); + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("invalid mesh dimension"); + } + // LCOV_EXCL_STOP + } + } else { + throw NormalError("discrete functions are not defined on the same mesh"); + } +} + +template double sum_of<double>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyVector<1> sum_of<TinyVector<1>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyVector<2> sum_of<TinyVector<2>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyVector<3> sum_of<TinyVector<3>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyMatrix<1> sum_of<TinyMatrix<1>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyMatrix<2> sum_of<TinyMatrix<2>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyMatrix<3> sum_of<TinyMatrix<3>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template <typename ValueT> +ValueT +integral_of(const std::shared_ptr<const DiscreteFunctionVariant>& f) +{ + return std::visit( + [&](auto&& discrete_function) -> ValueT { + using DiscreteFunctionType = std::decay_t<decltype(discrete_function)>; + if constexpr (is_discrete_function_P0_v<DiscreteFunctionType>) { + using DataType = std::decay_t<typename DiscreteFunctionType::data_type>; + if constexpr (std::is_same_v<ValueT, DataType>) { + return integrate(discrete_function); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + } + }, + f->discreteFunction()); +} + +template double integral_of<double>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyVector<1> integral_of<TinyVector<1>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyVector<2> integral_of<TinyVector<2>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyVector<3> integral_of<TinyVector<3>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyMatrix<1> integral_of<TinyMatrix<1>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyMatrix<2> integral_of<TinyMatrix<2>>(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template TinyMatrix<3> integral_of<TinyMatrix<3>>(const std::shared_ptr<const DiscreteFunctionVariant>&); diff --git a/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.hpp b/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.hpp new file mode 100644 index 0000000000000000000000000000000000000000..66b784921da372cc7dfa2d616b94d6fbfe403ee3 --- /dev/null +++ b/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.hpp @@ -0,0 +1,110 @@ +#ifndef EMBEDDED_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP +#define EMBEDDED_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP + +#include <algebra/TinyMatrix.hpp> +#include <algebra/TinyVector.hpp> + +#include <memory> + +class DiscreteFunctionVariant; + +std::shared_ptr<const DiscreteFunctionVariant> sqrt(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> sqrt(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> abs(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> sin(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> cos(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> tan(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> asin(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> acos(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> atan(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> atan2(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> atan2(const double, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> atan2(const std::shared_ptr<const DiscreteFunctionVariant>&, + const double); + +std::shared_ptr<const DiscreteFunctionVariant> sinh(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> cosh(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> tanh(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> asinh(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> acosh(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> atanh(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> exp(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> log(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> pow(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> pow(const double, const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> pow(const std::shared_ptr<const DiscreteFunctionVariant>&, const double); + +std::shared_ptr<const DiscreteFunctionVariant> dot(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +template <size_t VectorDimension> +std::shared_ptr<const DiscreteFunctionVariant> dot(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<VectorDimension>&); + +template <size_t VectorDimension> +std::shared_ptr<const DiscreteFunctionVariant> dot(const TinyVector<VectorDimension>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> det(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> trace(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> inverse(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> transpose(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> sum_of_Vh_components( + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> vectorize( + const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_list); + +double min(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> min(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> min(const double, const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> min(const std::shared_ptr<const DiscreteFunctionVariant>&, const double); + +double max(const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> max(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> max(const double, const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> max(const std::shared_ptr<const DiscreteFunctionVariant>&, const double); + +template <typename ValueT> +ValueT sum_of(const std::shared_ptr<const DiscreteFunctionVariant>&); + +template <typename ValueT> +ValueT integral_of(const std::shared_ptr<const DiscreteFunctionVariant>&); + +#endif // EMBEDDED_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP diff --git a/src/language/utils/EmbeddedDiscreteFunctionOperators.cpp b/src/language/utils/EmbeddedDiscreteFunctionOperators.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b47153cf0660abd807774d477e7fcd8ae712b62 --- /dev/null +++ b/src/language/utils/EmbeddedDiscreteFunctionOperators.cpp @@ -0,0 +1,671 @@ +#include <language/utils/EmbeddedDiscreteFunctionOperators.hpp> + +#include <language/node_processor/BinaryExpressionProcessor.hpp> +#include <language/node_processor/UnaryExpressionProcessor.hpp> +#include <language/utils/EmbeddedDiscreteFunctionUtils.hpp> +#include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionUtils.hpp> +#include <utils/Exceptions.hpp> + +// unary operators + +template <typename UnaryOperatorT, typename DiscreteFunctionT> +std::shared_ptr<const DiscreteFunctionVariant> +applyUnaryOperation(const DiscreteFunctionT& f) +{ + return std::make_shared<DiscreteFunctionVariant>(UnaryOp<UnaryOperatorT>{}.eval(f)); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyUnaryOperation<language::unary_minus>(f); + }, + f_v->discreteFunction()); +} + +// binary operators + +template <typename DiscreteFunctionT, typename BinOperatorT> +std::shared_ptr<const DiscreteFunctionVariant> +innerCompositionLaw(const DiscreteFunctionT& f, const DiscreteFunctionT& g) +{ + using data_type = std::decay_t<typename DiscreteFunctionT::data_type>; + if constexpr ((std::is_same_v<language::multiply_op, BinOperatorT> and is_tiny_vector_v<data_type>) or + (std::is_same_v<language::divide_op, BinOperatorT> and not std::is_arithmetic_v<data_type>)) { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); + } else { + if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionT>) { + if (f.size() != g.size()) { + std::ostringstream error_msg; + error_msg << EmbeddedDiscreteFunctionUtils::getOperandTypeName(f) << " spaces have different sizes"; + throw NormalError(error_msg.str()); + } else { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, g)); + } + } else { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, g)); + } + } +} + +template <typename DiscreteFunctionT1, typename DiscreteFunctionT2, typename BinOperatorT> +std::shared_ptr<const DiscreteFunctionVariant> +applyBinaryOperation(const DiscreteFunctionT1& f, const DiscreteFunctionT2& g) +{ + using f_data_type = std::decay_t<typename DiscreteFunctionT1::data_type>; + using g_data_type = std::decay_t<typename DiscreteFunctionT2::data_type>; + if constexpr (std::is_same_v<language::multiply_op, BinOperatorT>) { + if constexpr (is_discrete_function_P0_v<DiscreteFunctionT1> and + is_discrete_function_P0_vector_v<DiscreteFunctionT2> and std::is_same_v<double, f_data_type>) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, g)); + } else if constexpr (is_discrete_function_P0_v<DiscreteFunctionT1> and + is_discrete_function_P0_v<DiscreteFunctionT2>) { + if constexpr (std::is_same_v<double, f_data_type> and + (is_tiny_vector_v<g_data_type> or is_tiny_matrix_v<g_data_type>)) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, g)); + } else if constexpr (is_tiny_matrix_v<f_data_type> and is_tiny_vector_v<g_data_type>) { + if constexpr (f_data_type::NumberOfColumns == g_data_type::Dimension) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, g)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); + } +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + if (not hasSameMesh({f_v, g_v})) { + throw NormalError("operands are defined on different meshes"); + } + + return std::visit( + [&](auto&& f, auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { + using TypeOfF = std::decay_t<decltype(f)>; + using TypeOfG = std::decay_t<decltype(g)>; + if constexpr (std::is_same_v<TypeOfF, TypeOfG>) { + return innerCompositionLaw<TypeOfF, language::plus_op>(f, g); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f_v, g_v)); + } + }, + f_v->discreteFunction(), g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + if (not hasSameMesh({f_v, g_v})) { + throw NormalError("operands are defined on different meshes"); + } + + return std::visit( + [&](auto&& f, auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { + using TypeOfF = std::decay_t<decltype(f)>; + using TypeOfG = std::decay_t<decltype(g)>; + if constexpr (std::is_same_v<TypeOfF, TypeOfG>) { + return innerCompositionLaw<TypeOfF, language::minus_op>(f, g); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f_v, g_v)); + } + }, + f_v->discreteFunction(), g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + if (not hasSameMesh({f_v, g_v})) { + throw NormalError("operands are defined on different meshes"); + } + + return std::visit( + [&](auto&& f, auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { + using TypeOfF = std::decay_t<decltype(f)>; + using TypeOfG = std::decay_t<decltype(g)>; + if constexpr (std::is_same_v<TypeOfF, TypeOfG> and not is_discrete_function_P0_vector_v<TypeOfF>) { + return innerCompositionLaw<TypeOfF, language::multiply_op>(f, g); + } else { + if constexpr (std::is_same_v<typename TypeOfF::MeshType, typename TypeOfG::MeshType>) { + return applyBinaryOperation<TypeOfF, TypeOfG, language::multiply_op>(f, g); + } else { + // LCOV_EXCL_START + throw UnexpectedError("operands are defined on different meshes"); + // LCOV_EXCL_STOP + } + } + }, + f_v->discreteFunction(), g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator/(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + if (not hasSameMesh({f_v, g_v})) { + throw NormalError("operands are defined on different meshes"); + } + + return std::visit( + [&](auto&& f, auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { + using TypeOfF = std::decay_t<decltype(f)>; + using TypeOfG = std::decay_t<decltype(g)>; + if constexpr (std::is_same_v<TypeOfF, TypeOfG> and not is_discrete_function_P0_vector_v<TypeOfF>) { + return innerCompositionLaw<TypeOfF, language::divide_op>(f, g); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f_v, g_v)); + } + }, + f_v->discreteFunction(), g_v->discreteFunction()); +} + +template <typename BinOperatorT, typename DataType, typename DiscreteFunctionT> +std::shared_ptr<const DiscreteFunctionVariant> +applyBinaryOperationWithLeftConstant(const DataType& a, const DiscreteFunctionT& f) +{ + if constexpr (is_discrete_function_P0_v<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<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(a, f)); + } else if constexpr (is_tiny_matrix_v<lhs_data_type> and std::is_same_v<lhs_data_type, rhs_data_type>) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(a, f)); + } else if constexpr (is_tiny_matrix_v<lhs_data_type> and is_tiny_vector_v<rhs_data_type>) { + if constexpr (lhs_data_type::NumberOfColumns == rhs_data_type::Dimension) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(a, f)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(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_same_v<rhs_data_type, double>) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(a, f)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(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<rhs_data_type, lhs_data_type>) or + (std::is_arithmetic_v<rhs_data_type> and std::is_arithmetic_v<lhs_data_type>)) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(a, f)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); + } + } else if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionT> and + std::is_same_v<language::multiply_op, BinOperatorT>) { + using lhs_data_type = std::decay_t<DataType>; + if constexpr (std::is_same_v<lhs_data_type, double>) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(a, f)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); + } +} + +template <typename BinOperatorT, typename DataType, typename DiscreteFunctionT> +std::shared_ptr<const DiscreteFunctionVariant> +applyBinaryOperationWithRightConstant(const DiscreteFunctionT& f, const DataType& a) +{ + if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) { + using lhs_data_type = std::decay_t<typename DiscreteFunctionT::data_type>; + using rhs_data_type = std::decay_t<DataType>; + + if constexpr (std::is_same_v<language::multiply_op, BinOperatorT>) { + if constexpr (is_tiny_matrix_v<lhs_data_type> and is_tiny_matrix_v<rhs_data_type>) { + if constexpr (lhs_data_type::NumberOfColumns == rhs_data_type::NumberOfRows) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, a)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); + } + } else if constexpr (is_tiny_matrix_v<lhs_data_type> and is_tiny_vector_v<rhs_data_type>) { + if constexpr (lhs_data_type::NumberOfColumns == rhs_data_type::Dimension) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, a)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(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> or + std::is_arithmetic_v<rhs_data_type>)) { + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, a)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(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<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, a)); + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); + } + } else { + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); + } +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const double& f, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyVector<1>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(v, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyVector<2>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(v, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyVector<3>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(v, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyMatrix<1>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(A, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyMatrix<2>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(A, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyMatrix<3>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(A, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const double& g) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<1>& v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, v); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<2>& v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, v); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<3>& v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, v); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<1>& A) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, A); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<2>& A) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, A); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<3>& A) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, A); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const double& f, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyVector<1>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(v, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyVector<2>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(v, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyVector<3>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(v, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyMatrix<1>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(A, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyMatrix<2>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(A, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyMatrix<3>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(A, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const double& g) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<1>& v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, v); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<2>& v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, v); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<3>& v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, v); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<1>& A) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, A); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<2>& A) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, A); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<3>& A) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, A); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const double& f, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::multiply_op>(f, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const TinyMatrix<1>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const TinyMatrix<2>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const TinyMatrix<3>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) +{ + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, g); + }, + g_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const double& g) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, g); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<1>& v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, v); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<2>& v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, v); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<3>& v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, v); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<1>& A) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, A); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<2>& A) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, A); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<3>& A) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, A); + }, + f_v->discreteFunction()); +} + +std::shared_ptr<const DiscreteFunctionVariant> +operator/(const double& a, const std::shared_ptr<const DiscreteFunctionVariant>& f_v) +{ + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::divide_op>(a, f); + }, + f_v->discreteFunction()); +} diff --git a/src/language/utils/EmbeddedDiscreteFunctionOperators.hpp b/src/language/utils/EmbeddedDiscreteFunctionOperators.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a23ea91a0929a10148d703dd4ec13d703f48e2bf --- /dev/null +++ b/src/language/utils/EmbeddedDiscreteFunctionOperators.hpp @@ -0,0 +1,150 @@ +#ifndef EMBEDDED_DISCRETE_FUNCTION_OPERATORS_HPP +#define EMBEDDED_DISCRETE_FUNCTION_OPERATORS_HPP + +#include <algebra/TinyMatrix.hpp> +#include <algebra/TinyVector.hpp> + +#include <memory> + +class DiscreteFunctionVariant; + +// unary minus +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&); + +// sum +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const double&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const double&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyVector<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyVector<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyVector<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyMatrix<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyMatrix<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyMatrix<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<1>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<2>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<3>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<1>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<2>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<3>&); + +// difference +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const double&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const double&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyVector<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyVector<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyVector<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyMatrix<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyMatrix<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyMatrix<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<1>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<2>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<3>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<1>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<2>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<3>&); + +// product +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const double&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const double&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const TinyMatrix<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const TinyMatrix<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const TinyMatrix<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<1>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<2>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<3>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<1>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<2>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<3>&); + +// ratio +std::shared_ptr<const DiscreteFunctionVariant> operator/(const double&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +std::shared_ptr<const DiscreteFunctionVariant> operator/(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); + +#endif // EMBEDDED_DISCRETE_FUNCTION_OPERATORS_HPP diff --git a/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp b/src/language/utils/EmbeddedDiscreteFunctionUtils.hpp similarity index 53% rename from src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp rename to src/language/utils/EmbeddedDiscreteFunctionUtils.hpp index 1e61f917dfa448add18b562dd403a70101dbec3b..bca3b6772b7913be46ebee9a7731aa26fb7f7a6d 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp +++ b/src/language/utils/EmbeddedDiscreteFunctionUtils.hpp @@ -1,13 +1,15 @@ -#ifndef EMBEDDED_I_DISCRETE_FUNCTION_UTILS_HPP -#define EMBEDDED_I_DISCRETE_FUNCTION_UTILS_HPP +#ifndef EMBEDDED_DISCRETE_FUNCTION_UTILS_HPP +#define EMBEDDED_DISCRETE_FUNCTION_UTILS_HPP #include <language/utils/ASTNodeDataType.hpp> -#include <scheme/IDiscreteFunction.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> +#include <utils/Demangle.hpp> + #include <string> -struct EmbeddedIDiscreteFunctionUtils +struct EmbeddedDiscreteFunctionUtils { template <typename T> static PUGS_INLINE std::string @@ -16,22 +18,16 @@ struct EmbeddedIDiscreteFunctionUtils if constexpr (is_shared_ptr_v<T>) { Assert(t.use_count() > 0, "dangling shared_ptr"); return getOperandTypeName(*t); - } else if constexpr (std::is_base_of_v<IDiscreteFunction, std::decay_t<T>>) { - return "Vh(" + name(t.descriptor().type()) + ':' + dataTypeName(t.dataType()) + ')'; + } else if constexpr (std::is_same_v<DiscreteFunctionVariant, std::decay_t<T>>) { + return std::visit([](auto&& v) -> std::string { return getOperandTypeName(v); }, t.discreteFunction()); + } else if constexpr (is_discrete_function_v<std::decay_t<T>>) { + std::string type_name = "Vh(" + name(t.descriptor().type()) + ':' + dataTypeName(t.dataType()) + ')'; + return type_name; } else { return dataTypeName(ast_node_data_type_from<T>); } } - static bool isSameDiscretization(const IDiscreteFunction& f, const IDiscreteFunction& g); - - static PUGS_INLINE bool - isSameDiscretization(const std::shared_ptr<const IDiscreteFunction>& f, - const std::shared_ptr<const IDiscreteFunction>& g) - { - return isSameDiscretization(*f, *g); - } - template <typename T1, typename T2> PUGS_INLINE static std::string incompatibleOperandTypes(const T1& t1, const T2& t2) @@ -47,4 +43,4 @@ struct EmbeddedIDiscreteFunctionUtils } }; -#endif // EMBEDDED_I_DISCRETE_FUNCTION_UTILS_HPP +#endif // EMBEDDED_DISCRETE_FUNCTION_UTILS_HPP diff --git a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp deleted file mode 100644 index 67622f4a7c2ebbc7284f7305be98aeb3beb8768f..0000000000000000000000000000000000000000 --- a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp +++ /dev/null @@ -1,1157 +0,0 @@ -#include <language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp> - -#include <language/utils/EmbeddedIDiscreteFunctionUtils.hpp> -#include <mesh/IMesh.hpp> -#include <scheme/DiscreteFunctionP0.hpp> -#include <scheme/DiscreteFunctionP0Vector.hpp> -#include <scheme/DiscreteFunctionUtils.hpp> -#include <scheme/IDiscreteFunction.hpp> -#include <scheme/IDiscreteFunctionDescriptor.hpp> - -#define DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(FUNCTION, ARG) \ - if (ARG->dataType() == ASTNodeDataType::double_t and ARG->descriptor().type() == DiscreteFunctionType::P0) { \ - switch (ARG->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 NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(ARG)); \ - } - -std::shared_ptr<const IDiscreteFunction> -sqrt(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(sqrt, f); -} - -std::shared_ptr<const IDiscreteFunction> -abs(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(abs, f); -} - -std::shared_ptr<const IDiscreteFunction> -sin(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(sin, f); -} - -std::shared_ptr<const IDiscreteFunction> -cos(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(cos, f); -} - -std::shared_ptr<const IDiscreteFunction> -tan(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(tan, f); -} - -std::shared_ptr<const IDiscreteFunction> -asin(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(asin, f); -} - -std::shared_ptr<const IDiscreteFunction> -acos(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(acos, f); -} - -std::shared_ptr<const IDiscreteFunction> -atan(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_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 - (g->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))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } -} - -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))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, 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)); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); - } -} - -std::shared_ptr<const IDiscreteFunction> -sinh(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(sinh, f); -} - -std::shared_ptr<const IDiscreteFunction> -cosh(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(cosh, f); -} - -std::shared_ptr<const IDiscreteFunction> -tanh(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(tanh, f); -} - -std::shared_ptr<const IDiscreteFunction> -asinh(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(asinh, f); -} - -std::shared_ptr<const IDiscreteFunction> -acosh(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(acosh, f); -} - -std::shared_ptr<const IDiscreteFunction> -atanh(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(atanh, f); -} - -std::shared_ptr<const IDiscreteFunction> -exp(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_FUNCTION_CALL(exp, f); -} - -std::shared_ptr<const IDiscreteFunction> -log(const std::shared_ptr<const IDiscreteFunction>& f) -{ - DISCRETE_VH_TO_VH_REAL_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 - (g->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))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } -} - -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))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, 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)); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); - } -} - -template <size_t Dimension> -std::shared_ptr<const IDiscreteFunction> -dot(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) -{ - Assert(((f->descriptor().type() == DiscreteFunctionType::P0Vector) and - (g->descriptor().type() == DiscreteFunctionType::P0Vector)) or - ((f->dataType() == ASTNodeDataType::vector_t and f->descriptor().type() == DiscreteFunctionType::P0) and - (g->dataType() == ASTNodeDataType::vector_t and g->descriptor().type() == DiscreteFunctionType::P0) and - (f->dataType().dimension() == g->dataType().dimension()))); - - if ((f->descriptor().type() == DiscreteFunctionType::P0Vector) and - (g->descriptor().type() == DiscreteFunctionType::P0Vector)) { - using DiscreteFunctionResultType = DiscreteFunctionP0<Dimension, double>; - using DiscreteFunctionType = DiscreteFunctionP0Vector<Dimension, double>; - - const DiscreteFunctionType& f_vector = dynamic_cast<const DiscreteFunctionType&>(*f); - const DiscreteFunctionType& g_vector = dynamic_cast<const DiscreteFunctionType&>(*g); - - if (f_vector.size() != g_vector.size()) { - throw NormalError("operands have different dimension"); - } else { - return std::make_shared<const DiscreteFunctionResultType>(dot(f_vector, g_vector)); - } - - } else { - using DiscreteFunctionResultType = DiscreteFunctionP0<Dimension, double>; - - switch (f->dataType().dimension()) { - case 1: { - using Rd = TinyVector<1>; - using DiscreteFunctionType = DiscreteFunctionP0<Dimension, Rd>; - return std::make_shared<const DiscreteFunctionResultType>( - dot(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); - } - case 2: { - using Rd = TinyVector<2>; - using DiscreteFunctionType = DiscreteFunctionP0<Dimension, Rd>; - return std::make_shared<const DiscreteFunctionResultType>( - dot(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); - } - case 3: { - using Rd = TinyVector<3>; - using DiscreteFunctionType = DiscreteFunctionP0<Dimension, Rd>; - return std::make_shared<const DiscreteFunctionResultType>( - dot(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } - // LCOV_EXCL_STOP - } - } -} - -std::shared_ptr<const IDiscreteFunction> -dot(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) -{ - if (((f->descriptor().type() == DiscreteFunctionType::P0Vector) and - (g->descriptor().type() == DiscreteFunctionType::P0Vector)) or - ((f->dataType() == ASTNodeDataType::vector_t and f->descriptor().type() == DiscreteFunctionType::P0) and - (g->dataType() == ASTNodeDataType::vector_t and g->descriptor().type() == DiscreteFunctionType::P0) and - (f->dataType().dimension() == g->dataType().dimension()))) { - 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: { - return dot<1>(f, g); - } - case 2: { - return dot<2>(f, g); - } - case 3: { - return dot<3>(f, g); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } -} - -template <size_t Dimension, size_t VectorDimension> -std::shared_ptr<const IDiscreteFunction> -dot(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<VectorDimension>& a) -{ - Assert((f->dataType() == ASTNodeDataType::vector_t and f->descriptor().type() == DiscreteFunctionType::P0) and - (f->dataType().dimension() == a.dimension())); - - using DiscreteFunctionResultType = DiscreteFunctionP0<Dimension, double>; - using DiscreteFunctionType = DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>>; - - return std::make_shared<const DiscreteFunctionResultType>(dot(dynamic_cast<const DiscreteFunctionType&>(*f), a)); -} - -template <size_t VectorDimension> -std::shared_ptr<const IDiscreteFunction> -dot(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<VectorDimension>& a) -{ - if ((f->dataType() == ASTNodeDataType::vector_t and f->descriptor().type() == DiscreteFunctionType::P0) and - (f->dataType().dimension() == a.dimension())) { - switch (f->mesh()->dimension()) { - case 1: { - return dot<1, VectorDimension>(f, a); - } - case 2: { - return dot<2, VectorDimension>(f, a); - } - case 3: { - return dot<3, VectorDimension>(f, a); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); - } -} - -template <size_t Dimension, size_t VectorDimension> -std::shared_ptr<const IDiscreteFunction> -dot(const TinyVector<VectorDimension>& a, const std::shared_ptr<const IDiscreteFunction>& f) -{ - Assert((f->dataType() == ASTNodeDataType::vector_t and f->descriptor().type() == DiscreteFunctionType::P0) and - (f->dataType().dimension() == a.dimension())); - - using DiscreteFunctionResultType = DiscreteFunctionP0<Dimension, double>; - using DiscreteFunctionType = DiscreteFunctionP0<Dimension, TinyVector<VectorDimension>>; - - return std::make_shared<const DiscreteFunctionResultType>(dot(a, dynamic_cast<const DiscreteFunctionType&>(*f))); -} - -template <size_t VectorDimension> -std::shared_ptr<const IDiscreteFunction> -dot(const TinyVector<VectorDimension>& a, const std::shared_ptr<const IDiscreteFunction>& f) -{ - if ((f->dataType() == ASTNodeDataType::vector_t and f->descriptor().type() == DiscreteFunctionType::P0) and - (f->dataType().dimension() == a.dimension())) { - switch (f->mesh()->dimension()) { - case 1: { - return dot<1, VectorDimension>(a, f); - } - case 2: { - return dot<2, VectorDimension>(a, f); - } - case 3: { - return dot<3, VectorDimension>(a, f); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } -} - -template std::shared_ptr<const IDiscreteFunction> dot(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<1>&); - -template std::shared_ptr<const IDiscreteFunction> dot(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<2>&); - -template std::shared_ptr<const IDiscreteFunction> dot(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<3>&); - -template std::shared_ptr<const IDiscreteFunction> dot(const TinyVector<1>&, - const std::shared_ptr<const IDiscreteFunction>&); - -template std::shared_ptr<const IDiscreteFunction> dot(const TinyVector<2>&, - const std::shared_ptr<const IDiscreteFunction>&); - -template std::shared_ptr<const IDiscreteFunction> dot(const TinyVector<3>&, - const std::shared_ptr<const IDiscreteFunction>&); - -template <typename MatrixType> -std::shared_ptr<const IDiscreteFunction> -det(const std::shared_ptr<const IDiscreteFunction>& A) -{ - switch (A->mesh()->dimension()) { - case 1: { - using DiscreteFunctionType = DiscreteFunctionP0<1, MatrixType>; - return std::make_shared<const DiscreteFunctionP0<1, double>>(det(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, MatrixType>; - return std::make_shared<const DiscreteFunctionP0<2, double>>(det(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, MatrixType>; - return std::make_shared<const DiscreteFunctionP0<3, double>>(det(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - default: { - throw UnexpectedError("invalid mesh dimension"); - } - } -} - -std::shared_ptr<const IDiscreteFunction> -det(const std::shared_ptr<const IDiscreteFunction>& A) -{ - if (A->dataType() == ASTNodeDataType::matrix_t and A->descriptor().type() == DiscreteFunctionType::P0) { - if (A->dataType().numberOfRows() != A->dataType().numberOfColumns()) { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); - } - switch (A->dataType().numberOfRows()) { - case 1: { - return det<TinyMatrix<1>>(A); - } - case 2: { - return det<TinyMatrix<2>>(A); - } - case 3: { - return det<TinyMatrix<3>>(A); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid matrix type"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); - } -} - -template <typename MatrixType> -std::shared_ptr<const IDiscreteFunction> -trace(const std::shared_ptr<const IDiscreteFunction>& A) -{ - switch (A->mesh()->dimension()) { - case 1: { - using DiscreteFunctionType = DiscreteFunctionP0<1, MatrixType>; - return std::make_shared<const DiscreteFunctionP0<1, double>>(trace(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, MatrixType>; - return std::make_shared<const DiscreteFunctionP0<2, double>>(trace(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, MatrixType>; - return std::make_shared<const DiscreteFunctionP0<3, double>>(trace(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - default: { - throw UnexpectedError("invalid mesh dimension"); - } - } -} - -std::shared_ptr<const IDiscreteFunction> -trace(const std::shared_ptr<const IDiscreteFunction>& A) -{ - if (A->dataType() == ASTNodeDataType::matrix_t and A->descriptor().type() == DiscreteFunctionType::P0) { - if (A->dataType().numberOfRows() != A->dataType().numberOfColumns()) { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); - } - switch (A->dataType().numberOfRows()) { - case 1: { - return trace<TinyMatrix<1>>(A); - } - case 2: { - return trace<TinyMatrix<2>>(A); - } - case 3: { - return trace<TinyMatrix<3>>(A); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid matrix type"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); - } -} - -template <typename MatrixType> -std::shared_ptr<const IDiscreteFunction> -inverse(const std::shared_ptr<const IDiscreteFunction>& A) -{ - switch (A->mesh()->dimension()) { - case 1: { - using DiscreteFunctionType = DiscreteFunctionP0<1, MatrixType>; - return std::make_shared<const DiscreteFunctionType>(inverse(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, MatrixType>; - return std::make_shared<const DiscreteFunctionType>(inverse(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, MatrixType>; - return std::make_shared<const DiscreteFunctionType>(inverse(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - default: { - throw UnexpectedError("invalid mesh dimension"); - } - } -} - -std::shared_ptr<const IDiscreteFunction> -inverse(const std::shared_ptr<const IDiscreteFunction>& A) -{ - if (A->dataType() == ASTNodeDataType::matrix_t and A->descriptor().type() == DiscreteFunctionType::P0) { - if (A->dataType().numberOfRows() != A->dataType().numberOfColumns()) { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); - } - switch (A->dataType().numberOfRows()) { - case 1: { - return inverse<TinyMatrix<1>>(A); - } - case 2: { - return inverse<TinyMatrix<2>>(A); - } - case 3: { - return inverse<TinyMatrix<3>>(A); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid matrix type"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); - } -} - -template <typename MatrixType> -std::shared_ptr<const IDiscreteFunction> -transpose(const std::shared_ptr<const IDiscreteFunction>& A) -{ - switch (A->mesh()->dimension()) { - case 1: { - using DiscreteFunctionType = DiscreteFunctionP0<1, MatrixType>; - return std::make_shared<const DiscreteFunctionType>(transpose(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, MatrixType>; - return std::make_shared<const DiscreteFunctionType>(transpose(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, MatrixType>; - return std::make_shared<const DiscreteFunctionType>(transpose(dynamic_cast<const DiscreteFunctionType&>(*A))); - } - default: { - throw UnexpectedError("invalid mesh dimension"); - } - } -} - -std::shared_ptr<const IDiscreteFunction> -transpose(const std::shared_ptr<const IDiscreteFunction>& A) -{ - if (A->dataType() == ASTNodeDataType::matrix_t and A->descriptor().type() == DiscreteFunctionType::P0) { - if (A->dataType().numberOfRows() != A->dataType().numberOfColumns()) { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); - } - switch (A->dataType().numberOfRows()) { - case 1: { - return transpose<TinyMatrix<1>>(A); - } - case 2: { - return transpose<TinyMatrix<2>>(A); - } - case 3: { - return transpose<TinyMatrix<3>>(A); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid matrix type"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); - } -} - -double -min(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 min(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, double>; - return min(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, double>; - return min(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } -} - -std::shared_ptr<const IDiscreteFunction> -min(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 - (g->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>( - min(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, double>; - return std::make_shared<const DiscreteFunctionType>( - min(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, double>; - return std::make_shared<const DiscreteFunctionType>( - min(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } -} - -std::shared_ptr<const IDiscreteFunction> -min(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>(min(a, dynamic_cast<const DiscreteFunctionType&>(*f))); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, double>; - return std::make_shared<const DiscreteFunctionType>(min(a, dynamic_cast<const DiscreteFunctionType&>(*f))); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, double>; - return std::make_shared<const DiscreteFunctionType>(min(a, dynamic_cast<const DiscreteFunctionType&>(*f))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } -} - -std::shared_ptr<const IDiscreteFunction> -min(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>(min(dynamic_cast<const DiscreteFunctionType&>(*f), a)); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, double>; - return std::make_shared<const DiscreteFunctionType>(min(dynamic_cast<const DiscreteFunctionType&>(*f), a)); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, double>; - return std::make_shared<const DiscreteFunctionType>(min(dynamic_cast<const DiscreteFunctionType&>(*f), a)); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); - } -} - -double -max(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 max(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, double>; - return max(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, double>; - return max(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } -} - -std::shared_ptr<const IDiscreteFunction> -max(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 - (g->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>( - max(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, double>; - return std::make_shared<const DiscreteFunctionType>( - max(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, double>; - return std::make_shared<const DiscreteFunctionType>( - max(dynamic_cast<const DiscreteFunctionType&>(*f), dynamic_cast<const DiscreteFunctionType&>(*g))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } -} - -std::shared_ptr<const IDiscreteFunction> -max(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>(max(a, dynamic_cast<const DiscreteFunctionType&>(*f))); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, double>; - return std::make_shared<const DiscreteFunctionType>(max(a, dynamic_cast<const DiscreteFunctionType&>(*f))); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, double>; - return std::make_shared<const DiscreteFunctionType>(max(a, dynamic_cast<const DiscreteFunctionType&>(*f))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } -} - -std::shared_ptr<const IDiscreteFunction> -max(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>(max(dynamic_cast<const DiscreteFunctionType&>(*f), a)); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, double>; - return std::make_shared<const DiscreteFunctionType>(max(dynamic_cast<const DiscreteFunctionType&>(*f), a)); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, double>; - return std::make_shared<const DiscreteFunctionType>(max(dynamic_cast<const DiscreteFunctionType&>(*f), a)); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); - } -} - -template <typename ValueT> -ValueT -sum_of(const std::shared_ptr<const IDiscreteFunction>& f) -{ - if (f->dataType() == ast_node_data_type_from<ValueT> and f->descriptor().type() == DiscreteFunctionType::P0) { - switch (f->mesh()->dimension()) { - case 1: { - using DiscreteFunctionType = DiscreteFunctionP0<1, ValueT>; - return sum(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, ValueT>; - return sum(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, ValueT>; - return sum(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } -} - -std::shared_ptr<const IDiscreteFunction> -sum_of_Vh_components(const std::shared_ptr<const IDiscreteFunction>& f) -{ - if (f->descriptor().type() == DiscreteFunctionType::P0Vector) { - switch (f->mesh()->dimension()) { - case 1: { - constexpr size_t Dimension = 1; - using DiscreteFunctionType = DiscreteFunctionP0Vector<Dimension, double>; - return std::make_shared<const DiscreteFunctionP0<Dimension, double>>( - sumOfComponents(dynamic_cast<const DiscreteFunctionType&>(*f))); - } - case 2: { - constexpr size_t Dimension = 2; - using DiscreteFunctionType = DiscreteFunctionP0Vector<Dimension, double>; - return std::make_shared<const DiscreteFunctionP0<Dimension, double>>( - sumOfComponents(dynamic_cast<const DiscreteFunctionType&>(*f))); - } - case 3: { - constexpr size_t Dimension = 3; - using DiscreteFunctionType = DiscreteFunctionP0Vector<Dimension, double>; - return std::make_shared<const DiscreteFunctionP0<Dimension, double>>( - sumOfComponents(dynamic_cast<const DiscreteFunctionType&>(*f))); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } -} - -std::shared_ptr<const IDiscreteFunction> -vectorize(const std::vector<std::shared_ptr<const IDiscreteFunction>>& discrete_function_list) -{ - Assert(discrete_function_list.size() > 0); - std::shared_ptr p_i_mesh = [&] { - auto i = discrete_function_list.begin(); - - std::shared_ptr<const IMesh> i_mesh = (*i)->mesh(); - ++i; - for (; i != discrete_function_list.end(); ++i) { - if ((*i)->mesh() != i_mesh) { - throw NormalError("discrete functions are not defined on the same mesh"); - } - } - - return i_mesh; - }(); - - for (auto&& i_discrete_function : discrete_function_list) { - if ((i_discrete_function->descriptor().type() != DiscreteFunctionType::P0) or - (i_discrete_function->dataType() != ASTNodeDataType::double_t)) { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(i_discrete_function)); - } - } - - switch (p_i_mesh->dimension()) { - case 1: { - constexpr size_t Dimension = 1; - using DiscreteFunctionVectorType = DiscreteFunctionP0Vector<Dimension, double>; - using DiscreteFunctionType = DiscreteFunctionP0<Dimension, double>; - std::shared_ptr<const Mesh<Connectivity<Dimension>>> p_mesh = - std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(p_i_mesh); - - DiscreteFunctionVectorType vector_function(p_mesh, discrete_function_list.size()); - for (size_t i = 0; i < discrete_function_list.size(); ++i) { - const DiscreteFunctionType& f = dynamic_cast<const DiscreteFunctionType&>(*discrete_function_list[i]); - for (CellId cell_id = 0; cell_id < p_mesh->numberOfCells(); ++cell_id) { - vector_function[cell_id][i] = f[cell_id]; - } - } - - return std::make_shared<DiscreteFunctionVectorType>(vector_function); - } - case 2: { - constexpr size_t Dimension = 2; - using DiscreteFunctionVectorType = DiscreteFunctionP0Vector<Dimension, double>; - using DiscreteFunctionType = DiscreteFunctionP0<Dimension, double>; - std::shared_ptr<const Mesh<Connectivity<Dimension>>> p_mesh = - std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(p_i_mesh); - - DiscreteFunctionVectorType vector_function(p_mesh, discrete_function_list.size()); - for (size_t i = 0; i < discrete_function_list.size(); ++i) { - const DiscreteFunctionType& f = dynamic_cast<const DiscreteFunctionType&>(*discrete_function_list[i]); - for (CellId cell_id = 0; cell_id < p_mesh->numberOfCells(); ++cell_id) { - vector_function[cell_id][i] = f[cell_id]; - } - } - - return std::make_shared<DiscreteFunctionVectorType>(vector_function); - } - case 3: { - constexpr size_t Dimension = 3; - using DiscreteFunctionVectorType = DiscreteFunctionP0Vector<Dimension, double>; - using DiscreteFunctionType = DiscreteFunctionP0<Dimension, double>; - std::shared_ptr<const Mesh<Connectivity<Dimension>>> p_mesh = - std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(p_i_mesh); - - DiscreteFunctionVectorType vector_function(p_mesh, discrete_function_list.size()); - for (size_t i = 0; i < discrete_function_list.size(); ++i) { - const DiscreteFunctionType& f = dynamic_cast<const DiscreteFunctionType&>(*discrete_function_list[i]); - for (CellId cell_id = 0; cell_id < p_mesh->numberOfCells(); ++cell_id) { - vector_function[cell_id][i] = f[cell_id]; - } - } - - return std::make_shared<DiscreteFunctionVectorType>(vector_function); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } -} - -template double sum_of<double>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyVector<1> sum_of<TinyVector<1>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyVector<2> sum_of<TinyVector<2>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyVector<3> sum_of<TinyVector<3>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyMatrix<1> sum_of<TinyMatrix<1>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyMatrix<2> sum_of<TinyMatrix<2>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyMatrix<3> sum_of<TinyMatrix<3>>(const std::shared_ptr<const IDiscreteFunction>&); - -template <typename ValueT> -ValueT -integral_of(const std::shared_ptr<const IDiscreteFunction>& f) -{ - if (f->dataType() == ast_node_data_type_from<ValueT> and f->descriptor().type() == DiscreteFunctionType::P0) { - switch (f->mesh()->dimension()) { - case 1: { - using DiscreteFunctionType = DiscreteFunctionP0<1, ValueT>; - return integrate(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - case 2: { - using DiscreteFunctionType = DiscreteFunctionP0<2, ValueT>; - return integrate(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - case 3: { - using DiscreteFunctionType = DiscreteFunctionP0<3, ValueT>; - return integrate(dynamic_cast<const DiscreteFunctionType&>(*f)); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } -} - -template double integral_of<double>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyVector<1> integral_of<TinyVector<1>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyVector<2> integral_of<TinyVector<2>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyVector<3> integral_of<TinyVector<3>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyMatrix<1> integral_of<TinyMatrix<1>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyMatrix<2> integral_of<TinyMatrix<2>>(const std::shared_ptr<const IDiscreteFunction>&); - -template TinyMatrix<3> integral_of<TinyMatrix<3>>(const std::shared_ptr<const IDiscreteFunction>&); diff --git a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp deleted file mode 100644 index 24994c743428d98befb8d34cc18c2cbbf12a2ba4..0000000000000000000000000000000000000000 --- a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#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); - -std::shared_ptr<const IDiscreteFunction> dot(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); - -template <size_t VectorDimension> -std::shared_ptr<const IDiscreteFunction> dot(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<VectorDimension>&); - -template <size_t VectorDimension> -std::shared_ptr<const IDiscreteFunction> dot(const TinyVector<VectorDimension>&, - const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> det(const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> trace(const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> inverse(const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> transpose(const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> sum_of_Vh_components(const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> vectorize( - const std::vector<std::shared_ptr<const IDiscreteFunction>>& discrete_function_list); - -double min(const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> min(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> min(const double, const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> min(const std::shared_ptr<const IDiscreteFunction>&, const double); - -double max(const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> max(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> max(const double, const std::shared_ptr<const IDiscreteFunction>&); - -std::shared_ptr<const IDiscreteFunction> max(const std::shared_ptr<const IDiscreteFunction>&, const double); - -template <typename ValueT> -ValueT sum_of(const std::shared_ptr<const IDiscreteFunction>&); - -template <typename ValueT> -ValueT integral_of(const std::shared_ptr<const IDiscreteFunction>&); - -#endif // EMBEDDED_I_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP diff --git a/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp b/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp deleted file mode 100644 index 656164d6fc012ef2469f846d3e54f32a9c1d4927..0000000000000000000000000000000000000000 --- a/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp +++ /dev/null @@ -1,1097 +0,0 @@ -#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> - -// unary operators -template <typename UnaryOperatorT, typename DiscreteFunctionT> -std::shared_ptr<const IDiscreteFunction> -applyUnaryOperation(const DiscreteFunctionT& f) -{ - return std::make_shared<decltype(UnaryOp<UnaryOperatorT>{}.eval(f))>(UnaryOp<UnaryOperatorT>{}.eval(f)); -} - -template <typename UnaryOperatorT, size_t Dimension> -std::shared_ptr<const IDiscreteFunction> -applyUnaryOperation(const std::shared_ptr<const IDiscreteFunction>& f) -{ - 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); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } - // LCOV_EXCL_STOP - } - } - case ASTNodeDataType::matrix_t: { - Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); - switch (f->dataType().numberOfRows()) { - 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); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } - // LCOV_EXCL_STOP - } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } - // LCOV_EXCL_STOP - } - break; - } - case DiscreteFunctionType::P0Vector: { - switch (f->dataType()) { - case ASTNodeDataType::double_t: { - auto fh = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*f); - return applyUnaryOperation<UnaryOperatorT>(fh); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } - // LCOV_EXCL_STOP - } - break; - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } - // LCOV_EXCL_STOP - } -} - -template <typename UnaryOperatorT> -std::shared_ptr<const IDiscreteFunction> -applyUnaryOperation(const std::shared_ptr<const IDiscreteFunction>& f) -{ - 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); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } -} - -std::shared_ptr<const IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f) -{ - return applyUnaryOperation<language::unary_minus>(f); -} - -// binary operators - -template <typename BinOperatorT, typename DiscreteFunctionT> -std::shared_ptr<const IDiscreteFunction> -innerCompositionLaw(const DiscreteFunctionT& lhs, const DiscreteFunctionT& rhs) -{ - Assert(lhs.mesh() == rhs.mesh()); - using data_type = typename DiscreteFunctionT::data_type; - if constexpr ((std::is_same_v<language::multiply_op, BinOperatorT> and is_tiny_vector_v<data_type>) or - (std::is_same_v<language::divide_op, BinOperatorT> and not std::is_arithmetic_v<data_type>)) { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(lhs, rhs)); - } else { - return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(lhs, rhs))>(BinOp<BinOperatorT>{}.eval(lhs, rhs)); - } -} - -template <typename BinOperatorT, size_t Dimension> -std::shared_ptr<const IDiscreteFunction> -innerCompositionLaw(const std::shared_ptr<const IDiscreteFunction>& f, - const std::shared_ptr<const IDiscreteFunction>& g) -{ - Assert(f->mesh() == g->mesh()); - Assert(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)); - - switch (f->dataType()) { - case ASTNodeDataType::double_t: { - if (f->descriptor().type() == DiscreteFunctionType::P0) { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*f); - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*g); - - return innerCompositionLaw<BinOperatorT>(fh, gh); - - } else if (f->descriptor().type() == DiscreteFunctionType::P0Vector) { - if constexpr (std::is_same_v<BinOperatorT, language::plus_op> or - std::is_same_v<BinOperatorT, language::minus_op>) { - auto fh = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*f); - auto gh = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*g); - - if (fh.size() != gh.size()) { - throw NormalError(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(f) + " spaces have different sizes"); - } - - return innerCompositionLaw<BinOperatorT>(fh, gh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } - } else { - // LCOV_EXCL_START - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - // LCOV_EXCL_STOP - } - } - case ASTNodeDataType::vector_t: { - Assert(f->descriptor().type() == DiscreteFunctionType::P0); - switch (f->dataType().dimension()) { - case 1: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<1>>&>(*f); - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<1>>&>(*g); - - return innerCompositionLaw<BinOperatorT>(fh, gh); - } - case 2: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<2>>&>(*f); - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<2>>&>(*g); - - return innerCompositionLaw<BinOperatorT>(fh, gh); - } - case 3: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<3>>&>(*f); - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<3>>&>(*g); - - return innerCompositionLaw<BinOperatorT>(fh, gh); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } - // LCOV_EXCL_STOP - } - } - case ASTNodeDataType::matrix_t: { - Assert(f->descriptor().type() == DiscreteFunctionType::P0); - Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); - switch (f->dataType().numberOfRows()) { - case 1: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*g); - - return innerCompositionLaw<BinOperatorT>(fh, gh); - } - case 2: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>&>(*f); - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>&>(*g); - - return innerCompositionLaw<BinOperatorT>(fh, gh); - } - case 3: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>&>(*f); - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>&>(*g); - - return innerCompositionLaw<BinOperatorT>(fh, gh); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } - // LCOV_EXCL_STOP - } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); - } - // LCOV_EXCL_STOP - } -} - -template <typename BinOperatorT> -std::shared_ptr<const IDiscreteFunction> -innerCompositionLaw(const std::shared_ptr<const IDiscreteFunction>& f, - const std::shared_ptr<const IDiscreteFunction>& g) -{ - std::shared_ptr mesh = getCommonMesh({f, g}); - if (mesh.use_count() == 0) { - throw NormalError("operands are defined on different meshes"); - } - - Assert(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)); - - switch (mesh->dimension()) { - case 1: { - return innerCompositionLaw<BinOperatorT, 1>(f, g); - } - case 2: { - return innerCompositionLaw<BinOperatorT, 2>(f, g); - } - case 3: { - return innerCompositionLaw<BinOperatorT, 3>(f, g); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } -} - -template <typename BinOperatorT, typename LeftDiscreteFunctionT, typename RightDiscreteFunctionT> -std::shared_ptr<const IDiscreteFunction> -applyBinaryOperation(const LeftDiscreteFunctionT& lhs, const RightDiscreteFunctionT& rhs) -{ - Assert(lhs.mesh() == rhs.mesh()); - - static_assert(not std::is_same_v<LeftDiscreteFunctionT, RightDiscreteFunctionT>, - "use innerCompositionLaw when data types are the same"); - - return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(lhs, rhs))>(BinOp<BinOperatorT>{}.eval(lhs, rhs)); -} - -template <typename BinOperatorT, size_t Dimension, typename DiscreteFunctionT> -std::shared_ptr<const IDiscreteFunction> -applyBinaryOperation(const DiscreteFunctionT& fh, const std::shared_ptr<const IDiscreteFunction>& g) -{ - Assert(fh.mesh() == g->mesh()); - Assert(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(fh, *g)); - using lhs_data_type = std::decay_t<typename DiscreteFunctionT::data_type>; - - switch (g->dataType()) { - case ASTNodeDataType::double_t: { - if constexpr (std::is_same_v<BinOperatorT, language::multiply_op> and - 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 { - // LCOV_EXCL_START - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(fh, g)); - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(fh, g)); - } - } - case ASTNodeDataType::vector_t: { - if constexpr (std::is_same_v<language::multiply_op, BinOperatorT>) { - switch (g->dataType().dimension()) { - case 1: { - if constexpr (not is_tiny_vector_v<lhs_data_type> and - (std::is_same_v<lhs_data_type, TinyMatrix<1>> or std::is_same_v<lhs_data_type, double>)) { - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<1>>&>(*g); - - return applyBinaryOperation<BinOperatorT>(fh, gh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(fh, g)); - } - } - case 2: { - if constexpr (not is_tiny_vector_v<lhs_data_type> and - (std::is_same_v<lhs_data_type, TinyMatrix<2>> or std::is_same_v<lhs_data_type, double>)) { - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<2>>&>(*g); - - return applyBinaryOperation<BinOperatorT>(fh, gh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(fh, g)); - } - } - case 3: { - if constexpr (not is_tiny_vector_v<lhs_data_type> and - (std::is_same_v<lhs_data_type, TinyMatrix<3>> or std::is_same_v<lhs_data_type, double>)) { - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<3>>&>(*g); - - return applyBinaryOperation<BinOperatorT>(fh, gh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(fh, g)); - } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid rhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(g)); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(fh, g)); - } - } - case ASTNodeDataType::matrix_t: { - Assert(g->dataType().numberOfRows() == g->dataType().numberOfColumns()); - if constexpr (std::is_same_v<lhs_data_type, double> and std::is_same_v<language::multiply_op, BinOperatorT>) { - switch (g->dataType().numberOfRows()) { - case 1: { - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*g); - - return applyBinaryOperation<BinOperatorT>(fh, gh); - } - case 2: { - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>&>(*g); - - return applyBinaryOperation<BinOperatorT>(fh, gh); - } - case 3: { - auto gh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>&>(*g); - - return applyBinaryOperation<BinOperatorT>(fh, gh); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid rhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(g)); - } - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(fh, g)); - } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid rhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(g)); - } - // LCOV_EXCL_STOP - } -} - -template <typename BinOperatorT, size_t Dimension> -std::shared_ptr<const IDiscreteFunction> -applyBinaryOperation(const std::shared_ptr<const IDiscreteFunction>& f, - const std::shared_ptr<const IDiscreteFunction>& g) -{ - Assert(f->mesh() == g->mesh()); - Assert(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)); - - if (f->descriptor().type() == DiscreteFunctionType::P0) { - switch (f->dataType()) { - case ASTNodeDataType::double_t: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*f); - return applyBinaryOperation<BinOperatorT, Dimension>(fh, g); - } - case ASTNodeDataType::matrix_t: { - Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); - switch (f->dataType().numberOfRows()) { - case 1: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); - - return applyBinaryOperation<BinOperatorT, Dimension>(fh, g); - } - case 2: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>&>(*f); - - return applyBinaryOperation<BinOperatorT, Dimension>(fh, g); - } - case 3: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>&>(*f); - - return applyBinaryOperation<BinOperatorT, Dimension>(fh, g); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid lhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(f)); - } - // LCOV_EXCL_STOP - } - } - default: { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } -} - -template <typename BinOperatorT> -std::shared_ptr<const IDiscreteFunction> -applyBinaryOperation(const std::shared_ptr<const IDiscreteFunction>& f, - const std::shared_ptr<const IDiscreteFunction>& g) -{ - std::shared_ptr mesh = getCommonMesh({f, g}); - if (mesh.use_count() == 0) { - throw NormalError("operands are defined on different meshes"); - } - - Assert(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g), "should call inner composition instead"); - - switch (mesh->dimension()) { - case 1: { - return applyBinaryOperation<BinOperatorT, 1>(f, g); - } - case 2: { - return applyBinaryOperation<BinOperatorT, 2>(f, g); - } - case 3: { - return applyBinaryOperation<BinOperatorT, 3>(f, g); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } -} - -std::shared_ptr<const IDiscreteFunction> -operator+(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) -{ - if (EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)) { - return innerCompositionLaw<language::plus_op>(f, g); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } -} - -std::shared_ptr<const IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) -{ - if (EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)) { - return innerCompositionLaw<language::minus_op>(f, g); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); - } -} - -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) -{ - if (EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)) { - return innerCompositionLaw<language::multiply_op>(f, g); - } else { - return applyBinaryOperation<language::multiply_op>(f, g); - } -} - -std::shared_ptr<const IDiscreteFunction> -operator/(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) -{ - if (EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)) { - return innerCompositionLaw<language::divide_op>(f, g); - } else { - return applyBinaryOperation<language::divide_op>(f, g); - } -} - -template <typename BinOperatorT, typename DataType, typename DiscreteFunctionT> -std::shared_ptr<const IDiscreteFunction> -applyBinaryOperationWithLeftConstant(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)); - } 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(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 { - // LCOV_EXCL_START - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - // LCOV_EXCL_STOP - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(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)); - } 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } -} - -template <typename BinOperatorT, size_t Dimension, typename DataType> -std::shared_ptr<const IDiscreteFunction> -applyBinaryOperationWithLeftConstant(const DataType& a, const std::shared_ptr<const IDiscreteFunction>& f) -{ - switch (f->dataType()) { - case ASTNodeDataType::bool_t: - case ASTNodeDataType::unsigned_int_t: - case ASTNodeDataType::int_t: - case ASTNodeDataType::double_t: { - if (f->descriptor().type() == DiscreteFunctionType::P0) { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } else if (f->descriptor().type() == DiscreteFunctionType::P0Vector) { - auto fh = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*f); - return applyBinaryOperationToVectorWithLeftConstant<BinOperatorT>(a, fh); - } else { - // LCOV_EXCL_START - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - // LCOV_EXCL_STOP - } - } - case ASTNodeDataType::vector_t: { - if constexpr (is_tiny_matrix_v<DataType>) { - switch (f->dataType().dimension()) { - case 1: { - if constexpr (std::is_same_v<DataType, TinyMatrix<1>>) { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<1>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } - } - case 2: { - if constexpr (std::is_same_v<DataType, TinyMatrix<2>>) { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<2>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } - } - case 3: { - if constexpr (std::is_same_v<DataType, TinyMatrix<3>>) { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<3>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid lhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(f)); - } - // LCOV_EXCL_STOP - } - } else { - switch (f->dataType().dimension()) { - case 1: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<1>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } - case 2: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<2>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } - case 3: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<3>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid lhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(f)); - } - // LCOV_EXCL_STOP - } - } - } - case ASTNodeDataType::matrix_t: { - Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); - if constexpr (is_tiny_matrix_v<DataType>) { - switch (f->dataType().numberOfRows()) { - case 1: { - if constexpr (std::is_same_v<DataType, TinyMatrix<1>>) { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } - } - case 2: { - if constexpr (std::is_same_v<DataType, TinyMatrix<2>>) { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } - } - case 3: { - if constexpr (std::is_same_v<DataType, TinyMatrix<3>>) { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid lhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(f)); - } - // LCOV_EXCL_STOP - } - } else { - switch (f->dataType().numberOfRows()) { - case 1: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } - case 2: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } - case 3: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>&>(*f); - return applyBinaryOperationWithLeftConstant<BinOperatorT>(a, fh); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid lhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(f)); - } - // LCOV_EXCL_STOP - } - } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); - } - // LCOV_EXCL_STOP - } -} - -template <typename BinOperatorT, typename DataType> -std::shared_ptr<const IDiscreteFunction> -applyBinaryOperationWithLeftConstant(const DataType& a, const std::shared_ptr<const IDiscreteFunction>& f) -{ - switch (f->mesh()->dimension()) { - case 1: { - return applyBinaryOperationWithLeftConstant<BinOperatorT, 1>(a, f); - } - case 2: { - return applyBinaryOperationWithLeftConstant<BinOperatorT, 2>(a, f); - } - case 3: { - return applyBinaryOperationWithLeftConstant<BinOperatorT, 3>(a, f); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } -} - -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); - - using lhs_data_type = std::decay_t<typename DiscreteFunctionT::data_type>; - using rhs_data_type = std::decay_t<DataType>; - - if constexpr (std::is_same_v<language::multiply_op, BinOperatorT>) { - if constexpr (is_tiny_matrix_v<lhs_data_type> and is_tiny_matrix_v<rhs_data_type>) { - if constexpr (lhs_data_type::NumberOfColumns == rhs_data_type::NumberOfRows) { - return std::make_shared<decltype(BinOp<BinOperatorT>{}.eval(f, a))>(BinOp<BinOperatorT>{}.eval(f, a)); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(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> 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); - } - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); - } -} - -template <typename BinOperatorT, size_t Dimension, typename DataType> -std::shared_ptr<const IDiscreteFunction> -applyBinaryOperationWithRightConstant(const std::shared_ptr<const IDiscreteFunction>& f, const DataType& a) -{ - if (f->descriptor().type() != DiscreteFunctionType::P0) { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); - } - - switch (f->dataType()) { - case ASTNodeDataType::bool_t: - case ASTNodeDataType::unsigned_int_t: - case ASTNodeDataType::int_t: - case ASTNodeDataType::double_t: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*f); - return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); - } - case ASTNodeDataType::vector_t: { - switch (f->dataType().dimension()) { - case 1: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<1>>&>(*f); - return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); - } - case 2: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<2>>&>(*f); - return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); - } - case 3: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyVector<3>>&>(*f); - return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid lhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(f)); - } - // LCOV_EXCL_STOP - } - } - case ASTNodeDataType::matrix_t: { - Assert(f->dataType().numberOfRows() == f->dataType().numberOfColumns()); - switch (f->dataType().numberOfRows()) { - case 1: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*f); - return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); - } - case 2: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>&>(*f); - return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); - } - case 3: { - auto fh = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>&>(*f); - return applyBinaryOperationWithRightConstant<BinOperatorT>(fh, a); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid lhs data type " + EmbeddedIDiscreteFunctionUtils::getOperandTypeName(f)); - } - // LCOV_EXCL_STOP - } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); - } - // LCOV_EXCL_STOP - } -} - -template <typename BinOperatorT, typename DataType> -std::shared_ptr<const IDiscreteFunction> -applyBinaryOperationWithRightConstant(const std::shared_ptr<const IDiscreteFunction>& f, const DataType& a) -{ - switch (f->mesh()->dimension()) { - case 1: { - return applyBinaryOperationWithRightConstant<BinOperatorT, 1>(f, a); - } - case 2: { - return applyBinaryOperationWithRightConstant<BinOperatorT, 2>(f, a); - } - case 3: { - return applyBinaryOperationWithRightConstant<BinOperatorT, 3>(f, a); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } -} - -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) -{ - return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, B); -} - -std::shared_ptr<const IDiscreteFunction> -operator*(const TinyMatrix<2>& A, const std::shared_ptr<const IDiscreteFunction>& B) -{ - return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, B); -} - -std::shared_ptr<const IDiscreteFunction> -operator*(const TinyMatrix<3>& A, const std::shared_ptr<const IDiscreteFunction>& B) -{ - return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, B); -} - -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyVector<1>& u) -{ - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, u); -} - -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyVector<2>& u) -{ - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, u); -} - -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyVector<3>& u) -{ - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, u); -} - -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyMatrix<1>& A) -{ - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, A); -} - -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyMatrix<2>& A) -{ - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, A); -} - -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyMatrix<3>& A) -{ - 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 deleted file mode 100644 index f797a95d03e19a796d9af965d81bbd3970c6cddd..0000000000000000000000000000000000000000 --- a/src/language/utils/EmbeddedIDiscreteFunctionOperators.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef EMBEDDED_I_DISCRETE_FUNCTION_OPERATORS_HPP -#define EMBEDDED_I_DISCRETE_FUNCTION_OPERATORS_HPP - -#include <algebra/TinyMatrix.hpp> -#include <algebra/TinyVector.hpp> - -#include <memory> - -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 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>&); - -// 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>&); - -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>&); - -// 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.cpp b/src/language/utils/EmbeddedIDiscreteFunctionUtils.cpp deleted file mode 100644 index 286988b9b2849fb34dc84948be05414ebbad6d5b..0000000000000000000000000000000000000000 --- a/src/language/utils/EmbeddedIDiscreteFunctionUtils.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include <language/utils/EmbeddedIDiscreteFunctionUtils.hpp> - -#include <utils/Exceptions.hpp> - -bool -EmbeddedIDiscreteFunctionUtils::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().numberOfRows() == g.dataType().numberOfRows()) and - (f.dataType().numberOfColumns() == g.dataType().numberOfColumns()); - } - default: { - throw UnexpectedError("invalid data type " + getOperandTypeName(f)); - } - } - } else { - return false; - } -} diff --git a/src/mesh/CMakeLists.txt b/src/mesh/CMakeLists.txt index 66ce42ae6f9e490a0b3e6e406934478b0f026f4a..62dbd50536ad2e725e67a25d9cddf481a62b40c6 100644 --- a/src/mesh/CMakeLists.txt +++ b/src/mesh/CMakeLists.txt @@ -7,6 +7,7 @@ add_library( ConnectivityBuilderBase.cpp ConnectivityComputer.cpp ConnectivityDispatcher.cpp + ConnectivityUtils.cpp DiamondDualConnectivityBuilder.cpp DiamondDualMeshBuilder.cpp Dual1DConnectivityBuilder.cpp diff --git a/src/mesh/Connectivity.cpp b/src/mesh/Connectivity.cpp index 22e722a11f0a53aabbde7a243386f854fcd41a59..dc03c1ee65224a07466e5f08352b53004ad3c1ea 100644 --- a/src/mesh/Connectivity.cpp +++ b/src/mesh/Connectivity.cpp @@ -13,44 +13,36 @@ template <size_t Dimension> void Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor) { - Assert(descriptor.cell_to_node_vector.size() == descriptor.cell_type_vector.size()); - Assert(descriptor.cell_number_vector.size() == descriptor.cell_type_vector.size()); + Assert(descriptor.cellToNodeMatrix().numberOfRows() == descriptor.cellTypeVector().size()); + Assert(descriptor.cellNumberVector().size() == descriptor.cellTypeVector().size()); if constexpr (Dimension > 1) { - Assert(descriptor.cell_to_face_vector.size() == descriptor.cell_type_vector.size()); - Assert(descriptor.face_to_node_vector.size() == descriptor.face_number_vector.size()); - Assert(descriptor.face_owner_vector.size() == descriptor.face_number_vector.size()); + Assert(descriptor.cellToFaceMatrix().numberOfRows() == descriptor.cellTypeVector().size()); + Assert(descriptor.faceToNodeMatrix().numberOfRows() == descriptor.faceNumberVector().size()); + Assert(descriptor.faceOwnerVector().size() == descriptor.faceNumberVector().size()); } - m_number_of_cells = descriptor.cell_number_vector.size(); - m_number_of_nodes = descriptor.node_number_vector.size(); + m_number_of_cells = descriptor.cellNumberVector().size(); + m_number_of_nodes = descriptor.nodeNumberVector().size(); if constexpr (Dimension == 1) { m_number_of_edges = m_number_of_nodes; m_number_of_faces = m_number_of_nodes; } else { - m_number_of_faces = descriptor.face_number_vector.size(); + m_number_of_faces = descriptor.faceNumberVector().size(); if constexpr (Dimension == 2) { m_number_of_edges = m_number_of_faces; } else { static_assert(Dimension == 3, "unexpected dimension"); - m_number_of_edges = descriptor.edge_number_vector.size(); + m_number_of_edges = descriptor.edgeNumberVector().size(); } } auto& cell_to_node_matrix = m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::node)]; - cell_to_node_matrix = descriptor.cell_to_node_vector; + cell_to_node_matrix = descriptor.cellToNodeMatrix(); - { - WeakCellValue<CellType> cell_type(*this); - parallel_for( - this->numberOfCells(), PUGS_LAMBDA(CellId j) { cell_type[j] = descriptor.cell_type_vector[j]; }); - m_cell_type = cell_type; - } - - m_cell_number = WeakCellValue<int>(*this, convert_to_array(descriptor.cell_number_vector)); - - Array node_number_array = convert_to_array(descriptor.node_number_vector); - m_node_number = WeakNodeValue<int>(*this, node_number_array); + m_cell_type = WeakCellValue<const CellType>(*this, descriptor.cellTypeVector()); + m_cell_number = WeakCellValue<const int>(*this, descriptor.cellNumberVector()); + m_node_number = WeakNodeValue<const int>(*this, descriptor.nodeNumberVector()); { WeakCellValue<int> cell_global_index(*this); @@ -60,7 +52,7 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor) m_cell_global_index = cell_global_index; } - m_cell_owner = WeakCellValue<int>(*this, convert_to_array(descriptor.cell_owner_vector)); + m_cell_owner = WeakCellValue<const int>(*this, descriptor.cellOwnerVector()); { const int rank = parallel::rank(); @@ -70,8 +62,7 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor) m_cell_is_owned = cell_is_owned; } - Array node_owner_array = convert_to_array(descriptor.node_owner_vector); - m_node_owner = WeakNodeValue<int>{*this, node_owner_array}; + m_node_owner = WeakNodeValue<const int>{*this, descriptor.nodeOwnerVector()}; Array<bool> node_is_owned_array(this->numberOfNodes()); { @@ -87,13 +78,13 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor) if constexpr (Dimension == 1) { // faces are similar to nodes - m_face_number = WeakFaceValue<int>(*this, node_number_array); - m_face_owner = WeakFaceValue<int>(*this, node_owner_array); + m_face_number = WeakFaceValue<const int>(*this, descriptor.nodeNumberVector()); + m_face_owner = WeakFaceValue<const int>(*this, descriptor.nodeOwnerVector()); m_face_is_owned = WeakFaceValue<bool>(*this, node_is_owned_array); // edges are similar to nodes - m_edge_number = WeakEdgeValue<int>(*this, node_number_array); - m_edge_owner = WeakEdgeValue<int>(*this, node_owner_array); + m_edge_number = WeakEdgeValue<const int>(*this, descriptor.nodeNumberVector()); + m_edge_owner = WeakEdgeValue<const int>(*this, descriptor.nodeOwnerVector()); m_edge_is_owned = WeakEdgeValue<bool>(*this, node_is_owned_array); // edge and face references are set equal to node references @@ -114,26 +105,15 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor) } } else { - m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::node)] = descriptor.face_to_node_vector; + m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::node)] = descriptor.faceToNodeMatrix(); - m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::face)] = descriptor.cell_to_face_vector; + m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::face)] = descriptor.cellToFaceMatrix(); - { - FaceValuePerCell<bool> cell_face_is_reversed(*this); - for (CellId j = 0; j < descriptor.cell_face_is_reversed_vector.size(); ++j) { - const auto& face_cells_vector = descriptor.cell_face_is_reversed_vector[j]; - for (unsigned short lj = 0; lj < face_cells_vector.size(); ++lj) { - cell_face_is_reversed(j, lj) = face_cells_vector[lj]; - } - } - m_cell_face_is_reversed = cell_face_is_reversed; - } + m_cell_face_is_reversed = FaceValuePerCell<const bool>(*this, descriptor.cellFaceIsReversed()); - Array face_number_array = convert_to_array(descriptor.face_number_vector); - m_face_number = WeakFaceValue<int>(*this, face_number_array); + m_face_number = WeakFaceValue<const int>(*this, descriptor.faceNumberVector()); - Array face_owner_array = convert_to_array(descriptor.face_owner_vector); - m_face_owner = WeakFaceValue<int>(*this, face_owner_array); + m_face_owner = WeakFaceValue<const int>(*this, descriptor.faceOwnerVector()); Array<bool> face_is_owned_array(this->numberOfFaces()); { @@ -148,8 +128,8 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor) if constexpr (Dimension == 2) { // edges are similar to faces - m_edge_number = WeakEdgeValue<int>(*this, face_number_array); - m_edge_owner = WeakEdgeValue<int>(*this, face_owner_array); + m_edge_number = WeakEdgeValue<const int>(*this, descriptor.faceNumberVector()); + m_edge_owner = WeakEdgeValue<const int>(*this, descriptor.faceOwnerVector()); m_edge_is_owned = WeakEdgeValue<bool>(*this, face_is_owned_array); // edge references are set equal to face references @@ -166,25 +146,16 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor) } } else { - m_item_to_item_matrix[itemTId(ItemType::edge)][itemTId(ItemType::node)] = descriptor.edge_to_node_vector; + m_item_to_item_matrix[itemTId(ItemType::edge)][itemTId(ItemType::node)] = descriptor.edgeToNodeMatrix(); - m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::edge)] = descriptor.face_to_edge_vector; + m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::edge)] = descriptor.faceToEdgeMatrix(); - m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::edge)] = descriptor.cell_to_edge_vector; + m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::edge)] = descriptor.cellToEdgeMatrix(); - { - EdgeValuePerFace<bool> face_edge_is_reversed(*this); - for (FaceId l = 0; l < descriptor.face_edge_is_reversed_vector.size(); ++l) { - const auto& edge_faces_vector = descriptor.face_edge_is_reversed_vector[l]; - for (unsigned short el = 0; el < edge_faces_vector.size(); ++el) { - face_edge_is_reversed(l, el) = edge_faces_vector[el]; - } - } - m_face_edge_is_reversed = face_edge_is_reversed; - } + m_face_edge_is_reversed = EdgeValuePerFace<const bool>(*this, descriptor.faceEdgeIsReversed()); - m_edge_number = WeakEdgeValue<int>(*this, convert_to_array(descriptor.edge_number_vector)); - m_edge_owner = WeakEdgeValue<int>(*this, convert_to_array(descriptor.edge_owner_vector)); + m_edge_number = WeakEdgeValue<const int>(*this, descriptor.edgeNumberVector()); + m_edge_owner = WeakEdgeValue<const int>(*this, descriptor.edgeOwnerVector()); { const int rank = parallel::rank(); diff --git a/src/mesh/Connectivity.hpp b/src/mesh/Connectivity.hpp index b0279507ee41e6f6d3433bda2b5dd7beaf406265..ee7b07fe043a44262c23afc053e748bcac448b50 100644 --- a/src/mesh/Connectivity.hpp +++ b/src/mesh/Connectivity.hpp @@ -122,7 +122,7 @@ class Connectivity final : public IConnectivity const ConnectivityMatrix& connectivity_matrix = m_item_to_item_matrix[itemTId(item_type_0)][itemTId(item_type_1)]; if (not connectivity_matrix.isBuilt()) { const_cast<ConnectivityMatrix&>(connectivity_matrix) = - m_connectivity_computer.computeConnectivityMatrix(*this, item_type_0, item_type_1); + m_connectivity_computer.computeInverseConnectivityMatrix(*this, item_type_0, item_type_1); } return connectivity_matrix; } diff --git a/src/mesh/ConnectivityBuilderBase.cpp b/src/mesh/ConnectivityBuilderBase.cpp index 55c56b3a4b78f28ecdf8613d04d4d0348b9e5c4a..e7eb95fc6ed064805d12b5a8ece6e2844c37b9e9 100644 --- a/src/mesh/ConnectivityBuilderBase.cpp +++ b/src/mesh/ConnectivityBuilderBase.cpp @@ -7,8 +7,6 @@ #include <utils/PugsAssert.hpp> #include <utils/PugsMacros.hpp> -#include <map> -#include <unordered_map> #include <vector> template <size_t Dimension> @@ -16,240 +14,583 @@ void ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities(ConnectivityDescriptor& descriptor) { static_assert((Dimension == 2) or (Dimension == 3), "Invalid dimension to compute cell-face connectivities"); - using CellFaceInfo = std::tuple<CellId, unsigned short, bool>; - using Face = ConnectivityFace<Dimension>; - const auto& node_number_vector = descriptor.node_number_vector; - Array<unsigned short> cell_nb_faces(descriptor.cell_to_node_vector.size()); - std::map<Face, std::vector<CellFaceInfo>> face_cells_map; - for (CellId j = 0; j < descriptor.cell_to_node_vector.size(); ++j) { - const auto& cell_nodes = descriptor.cell_to_node_vector[j]; + const auto& node_number_vector = descriptor.nodeNumberVector(); + const auto& cell_to_node_matrix = descriptor.cellToNodeMatrix(); + const auto& cell_type_vector = descriptor.cellTypeVector(); + + size_t total_number_of_faces = 0; + + for (CellId j = 0; j < cell_to_node_matrix.numberOfRows(); ++j) { + const auto& cell_nodes = cell_to_node_matrix[j]; if constexpr (Dimension == 2) { - switch (descriptor.cell_type_vector[j]) { - case CellType::Triangle: { - cell_nb_faces[j] = 3; - // face 0 - Face f0({cell_nodes[1], cell_nodes[2]}, node_number_vector); - face_cells_map[f0].emplace_back(std::make_tuple(j, 0, f0.reversed())); - - // face 1 - Face f1({cell_nodes[2], cell_nodes[0]}, node_number_vector); - face_cells_map[f1].emplace_back(std::make_tuple(j, 1, f1.reversed())); - - // face 2 - Face f2({cell_nodes[0], cell_nodes[1]}, node_number_vector); - face_cells_map[f2].emplace_back(std::make_tuple(j, 2, f2.reversed())); + total_number_of_faces += cell_nodes.size(); + } else if constexpr (Dimension == 3) { + switch (cell_type_vector[j]) { + case CellType::Hexahedron: { + total_number_of_faces += 6; break; } - case CellType::Quadrangle: { - cell_nb_faces[j] = 4; - // face 0 - Face f0({cell_nodes[0], cell_nodes[1]}, node_number_vector); - face_cells_map[f0].emplace_back(std::make_tuple(j, 0, f0.reversed())); - - // face 1 - Face f1({cell_nodes[1], cell_nodes[2]}, node_number_vector); - face_cells_map[f1].emplace_back(std::make_tuple(j, 1, f1.reversed())); - - // face 2 - Face f2({cell_nodes[2], cell_nodes[3]}, node_number_vector); - face_cells_map[f2].emplace_back(std::make_tuple(j, 2, f2.reversed())); - - // face 3 - Face f3({cell_nodes[3], cell_nodes[0]}, node_number_vector); - face_cells_map[f3].emplace_back(std::make_tuple(j, 3, f3.reversed())); + case CellType::Tetrahedron: { + total_number_of_faces += 4; break; } - case CellType::Polygon: { - cell_nb_faces[j] = cell_nodes.size(); - for (size_t i = 0; i < cell_nodes.size(); ++i) { - Face f({cell_nodes[i], cell_nodes[(i + 1) % cell_nodes.size()]}, node_number_vector); - face_cells_map[f].emplace_back(std::make_tuple(j, i, f.reversed())); - } + case CellType::Prism: { + total_number_of_faces += 5; + break; + } + case CellType::Pyramid: { + total_number_of_faces += cell_nodes.size(); + break; + } + case CellType::Diamond: { + total_number_of_faces += 2 * (cell_nodes.size() - 2); break; } default: { std::ostringstream error_msg; - error_msg << name(descriptor.cell_type_vector[j]) << ": unexpected cell type in dimension 2"; + error_msg << name(cell_type_vector[j]) << ": unexpected cell type in dimension 3"; throw UnexpectedError(error_msg.str()); } } - } else if constexpr (Dimension == 3) { - switch (descriptor.cell_type_vector[j]) { - case CellType::Hexahedron: { - // face 0 - Face f0({cell_nodes[3], cell_nodes[2], cell_nodes[1], cell_nodes[0]}, node_number_vector); - face_cells_map[f0].emplace_back(std::make_tuple(j, 0, f0.reversed())); + } + } - // face 1 - Face f1({cell_nodes[4], cell_nodes[5], cell_nodes[6], cell_nodes[7]}, node_number_vector); - face_cells_map[f1].emplace_back(std::make_tuple(j, 1, f1.reversed())); + const size_t total_number_of_face_by_node = [&] { + if constexpr (Dimension == 2) { + return 2 * total_number_of_faces; + } else { + Assert(Dimension == 3); + size_t count_number_of_face_by_node = 0; + for (CellId j = 0; j < cell_to_node_matrix.numberOfRows(); ++j) { + switch (cell_type_vector[j]) { + case CellType::Hexahedron: { + count_number_of_face_by_node += 6 * 4; + break; + } + case CellType::Tetrahedron: { + count_number_of_face_by_node += 4 * 3; + break; + } + case CellType::Prism: { + count_number_of_face_by_node += 3 * 4 + 2 * 3; + break; + } + case CellType::Pyramid: { + const auto& cell_nodes = cell_to_node_matrix[j]; + count_number_of_face_by_node += 1 * cell_nodes.size() + cell_nodes.size() * 3; + break; + } + case CellType::Diamond: { + const auto& cell_nodes = cell_to_node_matrix[j]; + count_number_of_face_by_node += cell_nodes.size() * 3 * 2; + break; + } + default: { + std::ostringstream error_msg; + error_msg << name(cell_type_vector[j]) << ": unexpected cell type in dimension 3"; + throw UnexpectedError(error_msg.str()); + } + } + } + return count_number_of_face_by_node; + } + }(); - // face 2 - Face f2({cell_nodes[0], cell_nodes[4], cell_nodes[7], cell_nodes[3]}, node_number_vector); - face_cells_map[f2].emplace_back(std::make_tuple(j, 2, f2.reversed())); + Array<unsigned int> dup_faces_to_node_list(total_number_of_face_by_node); + Array<unsigned int> dup_face_to_node_row(total_number_of_faces + 1); + size_t i_face = 0; + dup_face_to_node_row[0] = 0; - // face 3 - Face f3({cell_nodes[1], cell_nodes[2], cell_nodes[6], cell_nodes[5]}, node_number_vector); - face_cells_map[f3].emplace_back(std::make_tuple(j, 3, f3.reversed())); + Array<unsigned short> cell_nb_faces(cell_to_node_matrix.numberOfRows()); + { + size_t i_face_node = 0; + for (CellId j = 0; j < cell_to_node_matrix.numberOfRows(); ++j) { + const auto& cell_nodes = cell_to_node_matrix[j]; + + if constexpr (Dimension == 2) { + switch (cell_type_vector[j]) { + case CellType::Triangle: { + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 2; + i_face++; + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 2; + i_face++; + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 2; + i_face++; + cell_nb_faces[j] = 3; + break; + } + case CellType::Quadrangle: { + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 2; + i_face++; + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 2; + i_face++; + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 2; + i_face++; + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 2; + i_face++; + cell_nb_faces[j] = 4; + break; + } + case CellType::Polygon: { + for (size_t i = 0; i < cell_nodes.size(); ++i) { + dup_faces_to_node_list[i_face_node] = cell_nodes[i]; + i_face_node++; + dup_faces_to_node_list[i_face_node] = cell_nodes[(i + 1) % cell_nodes.size()]; + i_face_node++; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 2; + i_face++; + } - // face 4 - Face f4({cell_nodes[0], cell_nodes[1], cell_nodes[5], cell_nodes[4]}, node_number_vector); - face_cells_map[f4].emplace_back(std::make_tuple(j, 4, f4.reversed())); + cell_nb_faces[j] = cell_nodes.size(); + break; + } + default: { + std::ostringstream error_msg; + error_msg << name(cell_type_vector[j]) << ": unexpected cell type in dimension 2"; + throw UnexpectedError(error_msg.str()); + } + } + } else if constexpr (Dimension == 3) { + switch (cell_type_vector[j]) { + case CellType::Hexahedron: { + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 4; + i_face++; + + dup_faces_to_node_list[i_face_node++] = cell_nodes[4]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[5]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[6]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[7]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 4; + i_face++; + + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[4]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[7]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 4; + i_face++; + + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[6]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[5]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 4; + i_face++; + + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[5]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[4]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 4; + i_face++; + + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[7]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[6]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 4; + i_face++; + + cell_nb_faces[j] = 6; + break; + } + case CellType::Tetrahedron: { + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; - // face 5 - Face f5({cell_nodes[3], cell_nodes[7], cell_nodes[6], cell_nodes[2]}, node_number_vector); - face_cells_map[f5].emplace_back(std::make_tuple(j, 5, f5.reversed())); + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 3; + i_face++; - cell_nb_faces[j] = 6; - break; - } - case CellType::Tetrahedron: { - cell_nb_faces[j] = 4; - // face 0 - Face f0({cell_nodes[1], cell_nodes[2], cell_nodes[3]}, node_number_vector); - face_cells_map[f0].emplace_back(std::make_tuple(j, 0, f0.reversed())); - - // face 1 - Face f1({cell_nodes[0], cell_nodes[3], cell_nodes[2]}, node_number_vector); - face_cells_map[f1].emplace_back(std::make_tuple(j, 1, f1.reversed())); - - // face 2 - Face f2({cell_nodes[0], cell_nodes[1], cell_nodes[3]}, node_number_vector); - face_cells_map[f2].emplace_back(std::make_tuple(j, 2, f2.reversed())); - - // face 3 - Face f3({cell_nodes[0], cell_nodes[2], cell_nodes[1]}, node_number_vector); - face_cells_map[f3].emplace_back(std::make_tuple(j, 3, f3.reversed())); - break; - } - case CellType::Prism: { - // face 0 - Face f0({cell_nodes[2], cell_nodes[1], cell_nodes[0]}, node_number_vector); - face_cells_map[f0].emplace_back(std::make_tuple(j, 0, f0.reversed())); + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; - // face 1 - Face f1({cell_nodes[3], cell_nodes[4], cell_nodes[5]}, node_number_vector); - face_cells_map[f1].emplace_back(std::make_tuple(j, 1, f1.reversed())); + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 3; + i_face++; - // face 2 - Face f2({cell_nodes[1], cell_nodes[2], cell_nodes[5], cell_nodes[4]}, node_number_vector); - face_cells_map[f2].emplace_back(std::make_tuple(j, 2, f2.reversed())); + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; - // face 3 - Face f3({cell_nodes[0], cell_nodes[1], cell_nodes[4], cell_nodes[3]}, node_number_vector); - face_cells_map[f3].emplace_back(std::make_tuple(j, 3, f3.reversed())); + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 3; + i_face++; - // face 4 - Face f4({cell_nodes[2], cell_nodes[0], cell_nodes[3], cell_nodes[5]}, node_number_vector); - face_cells_map[f4].emplace_back(std::make_tuple(j, 4, f4.reversed())); + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; - cell_nb_faces[j] = 5; - break; - } - case CellType::Pyramid: { - cell_nb_faces[j] = cell_nodes.size(); - std::vector<unsigned int> base_nodes(cell_nodes.size() - 1); - for (size_t i = 0; i < base_nodes.size(); ++i) { - base_nodes[base_nodes.size() - 1 - i] = cell_nodes[i]; - } + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 3; + i_face++; - // base face - { - Face base_face(base_nodes, node_number_vector); - face_cells_map[base_face].emplace_back(std::make_tuple(j, 0, base_face.reversed())); + cell_nb_faces[j] = 4; + break; } - // side faces - const auto pyramid_vertex = cell_nodes[cell_nodes.size() - 1]; - for (size_t i_node = 0; i_node < base_nodes.size(); ++i_node) { - Face side_face({base_nodes[(i_node + 1) % base_nodes.size()], base_nodes[i_node], pyramid_vertex}, - node_number_vector); - face_cells_map[side_face].emplace_back(std::make_tuple(j, i_node + 1, side_face.reversed())); + case CellType::Prism: { + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 3; + i_face++; + + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[4]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[5]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 3; + i_face++; + + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[5]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[4]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 4; + i_face++; + + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[1]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[4]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 4; + i_face++; + + dup_faces_to_node_list[i_face_node++] = cell_nodes[2]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[0]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[3]; + dup_faces_to_node_list[i_face_node++] = cell_nodes[5]; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 4; + i_face++; + + cell_nb_faces[j] = 5; + break; } - break; - } - case CellType::Diamond: { - cell_nb_faces[j] = 2 * (cell_nodes.size() - 2); - std::vector<unsigned int> base_nodes; - std::copy_n(cell_nodes.begin() + 1, cell_nodes.size() - 2, std::back_inserter(base_nodes)); + case CellType::Pyramid: { + cell_nb_faces[j] = cell_nodes.size(); + std::vector<unsigned int> base_nodes(cell_nodes.size() - 1); + for (size_t i = 0; i < base_nodes.size(); ++i) { + base_nodes[base_nodes.size() - 1 - i] = cell_nodes[i]; + } - { // top faces - const auto top_vertex = cell_nodes[cell_nodes.size() - 1]; + for (size_t i = 0; i < base_nodes.size(); ++i) { + dup_faces_to_node_list[i_face_node++] = base_nodes[i]; + } + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + base_nodes.size(); + i_face++; + + // side faces + const auto pyramid_vertex = cell_nodes[cell_nodes.size() - 1]; for (size_t i_node = 0; i_node < base_nodes.size(); ++i_node) { - Face top_face({base_nodes[i_node], base_nodes[(i_node + 1) % base_nodes.size()], top_vertex}, - node_number_vector); - face_cells_map[top_face].emplace_back(std::make_tuple(j, i_node, top_face.reversed())); + dup_faces_to_node_list[i_face_node++] = base_nodes[(i_node + 1) % base_nodes.size()]; + dup_faces_to_node_list[i_face_node++] = base_nodes[i_node]; + dup_faces_to_node_list[i_face_node++] = pyramid_vertex; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 3; + i_face++; } + break; } + case CellType::Diamond: { + auto base_nodes = [&](size_t i) { return cell_nodes[i + 1]; }; + + { // top faces + const auto top_vertex = cell_nodes[cell_nodes.size() - 1]; + for (size_t i_node = 0; i_node < cell_nodes.size() - 2; ++i_node) { + dup_faces_to_node_list[i_face_node++] = base_nodes(i_node); + dup_faces_to_node_list[i_face_node++] = base_nodes((i_node + 1) % (cell_nodes.size() - 2)); + dup_faces_to_node_list[i_face_node++] = top_vertex; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 3; + i_face++; + } + } - { // bottom faces - const auto bottom_vertex = cell_nodes[0]; - for (size_t i_node = 0; i_node < base_nodes.size(); ++i_node) { - Face bottom_face({base_nodes[(i_node + 1) % base_nodes.size()], base_nodes[i_node], bottom_vertex}, - node_number_vector); - face_cells_map[bottom_face].emplace_back( - std::make_tuple(j, i_node + base_nodes.size(), bottom_face.reversed())); + { // bottom faces + const auto bottom_vertex = cell_nodes[0]; + for (size_t i_node = 0; i_node < cell_nodes.size() - 2; ++i_node) { + dup_faces_to_node_list[i_face_node++] = base_nodes((i_node + 1) % (cell_nodes.size() - 2)); + dup_faces_to_node_list[i_face_node++] = base_nodes(i_node); + dup_faces_to_node_list[i_face_node++] = bottom_vertex; + + dup_face_to_node_row[i_face + 1] = dup_face_to_node_row[i_face] + 3; + i_face++; + } } + cell_nb_faces[j] = 2 * (cell_nodes.size() - 2); + break; + } + default: { + std::ostringstream error_msg; + error_msg << name(cell_type_vector[j]) << ": unexpected cell type in dimension 3"; + throw UnexpectedError(error_msg.str()); + } } - break; } - default: { - std::ostringstream error_msg; - error_msg << name(descriptor.cell_type_vector[j]) << ": unexpected cell type in dimension 3"; - throw UnexpectedError(error_msg.str()); + } + } + + Array<bool> cell_face_is_reversed(total_number_of_faces); + + if constexpr (Dimension == 2) { + for (size_t i_face = 0; i_face < total_number_of_faces; ++i_face) { + if (node_number_vector[dup_faces_to_node_list[2 * i_face]] > + node_number_vector[dup_faces_to_node_list[2 * i_face + 1]]) { + std::swap(dup_faces_to_node_list[2 * i_face], dup_faces_to_node_list[2 * i_face + 1]); + cell_face_is_reversed[i_face] = true; + } else { + cell_face_is_reversed[i_face] = false; } + } + } else if constexpr (Dimension == 3) { + std::vector<int> buffer; + + for (size_t i_face = 0; i_face < total_number_of_faces; ++i_face) { + const size_t face_node_number = dup_face_to_node_row[i_face + 1] - dup_face_to_node_row[i_face]; + size_t i_face_node_smallest_number = 0; + for (size_t i_face_node = 1; i_face_node < face_node_number; ++i_face_node) { + if (node_number_vector[dup_faces_to_node_list[dup_face_to_node_row[i_face] + i_face_node]] < + node_number_vector[dup_faces_to_node_list[dup_face_to_node_row[i_face] + i_face_node_smallest_number]]) { + i_face_node_smallest_number = i_face_node; + } } + + if (i_face_node_smallest_number != 0) { + buffer.resize(face_node_number); + for (size_t i_node = i_face_node_smallest_number; i_node < face_node_number; ++i_node) { + buffer[i_node - i_face_node_smallest_number] = dup_faces_to_node_list[dup_face_to_node_row[i_face] + i_node]; + } + for (size_t i_node = 0; i_node < i_face_node_smallest_number; ++i_node) { + buffer[i_node + face_node_number - i_face_node_smallest_number] = + dup_faces_to_node_list[dup_face_to_node_row[i_face] + i_node]; + } + + for (size_t i_node = 0; i_node < face_node_number; ++i_node) { + dup_faces_to_node_list[dup_face_to_node_row[i_face] + i_node] = buffer[i_node]; + } + } + + if (node_number_vector[dup_faces_to_node_list[dup_face_to_node_row[i_face] + 1]] > + node_number_vector[dup_faces_to_node_list[dup_face_to_node_row[i_face + 1] - 1]]) { + for (size_t i_node = 1; i_node <= (face_node_number + 1) / 2 - 1; ++i_node) { + std::swap(dup_faces_to_node_list[dup_face_to_node_row[i_face] + i_node], + dup_faces_to_node_list[dup_face_to_node_row[i_face + 1] - i_node]); + } + + cell_face_is_reversed[i_face] = true; + } else { + cell_face_is_reversed[i_face] = false; + } + } + } + + Array<unsigned int> node_to_duplicate_face_row(node_number_vector.size() + 1); + node_to_duplicate_face_row.fill(0); + for (size_t i_face = 0; i_face < total_number_of_faces; ++i_face) { + for (size_t i_node_face = dup_face_to_node_row[i_face]; i_node_face < dup_face_to_node_row[i_face + 1]; + ++i_node_face) { + node_to_duplicate_face_row[dup_faces_to_node_list[i_node_face] + 1]++; } } + for (size_t i_node = 1; i_node < node_to_duplicate_face_row.size(); ++i_node) { + node_to_duplicate_face_row[i_node] += node_to_duplicate_face_row[i_node - 1]; + } + + Array<unsigned int> node_duplicate_face_list(node_to_duplicate_face_row[node_to_duplicate_face_row.size() - 1]); + { - descriptor.cell_to_face_vector.resize(descriptor.cell_to_node_vector.size()); - for (CellId j = 0; j < descriptor.cell_to_face_vector.size(); ++j) { - descriptor.cell_to_face_vector[j].resize(cell_nb_faces[j]); + Array<unsigned int> node_duplicate_face_row_idx(node_number_vector.size()); + node_duplicate_face_row_idx.fill(0); + + for (size_t i_face = 0; i_face < total_number_of_faces; ++i_face) { + for (size_t i_node_face = dup_face_to_node_row[i_face]; i_node_face < dup_face_to_node_row[i_face + 1]; + ++i_node_face) { + const size_t node_id = dup_faces_to_node_list[i_node_face]; + node_duplicate_face_list[node_to_duplicate_face_row[node_id] + node_duplicate_face_row_idx[node_id]] = i_face; + node_duplicate_face_row_idx[node_id]++; + } } - FaceId l = 0; - for (const auto& face_cells_vector : face_cells_map) { - const auto& cells_vector = face_cells_vector.second; - for (unsigned short lj = 0; lj < cells_vector.size(); ++lj) { - const auto& [cell_number, cell_local_face, reversed] = cells_vector[lj]; - descriptor.cell_to_face_vector[cell_number][cell_local_face] = l; - } - ++l; + } + + Array<unsigned int> dup_face_to_face(total_number_of_faces); + parallel_for( + total_number_of_faces, PUGS_LAMBDA(size_t i_face) { dup_face_to_face[i_face] = i_face; }); + + auto is_same_face = [=](const size_t i_face, const size_t j_face) { + if ((dup_face_to_node_row[i_face + 1] - dup_face_to_node_row[i_face]) != + (dup_face_to_node_row[j_face + 1] - dup_face_to_node_row[j_face])) { + return false; + } else { + auto i_face_node = dup_face_to_node_row[i_face]; + auto j_face_node = dup_face_to_node_row[j_face]; + while (i_face_node < dup_face_to_node_row[i_face + 1]) { + if (dup_faces_to_node_list[i_face_node] != dup_faces_to_node_list[j_face_node]) { + return false; + } + i_face_node++; + j_face_node++; + } + return true; + } + }; + + size_t nb_dup_faces = 0; + for (size_t i_node = 0; i_node < node_number_vector.size(); ++i_node) { + for (size_t i_node_face = node_to_duplicate_face_row[i_node]; + i_node_face < node_to_duplicate_face_row[i_node + 1] - 1; ++i_node_face) { + for (size_t j_node_face = i_node_face + 1; j_node_face < node_to_duplicate_face_row[i_node + 1]; ++j_node_face) { + if (dup_face_to_face[node_duplicate_face_list[i_node_face]] == + dup_face_to_face[node_duplicate_face_list[j_node_face]]) + continue; + if (is_same_face(node_duplicate_face_list[i_node_face], node_duplicate_face_list[j_node_face])) { + dup_face_to_face[node_duplicate_face_list[j_node_face]] = + dup_face_to_face[node_duplicate_face_list[i_node_face]]; + nb_dup_faces++; + } + } } } + // compute face_id + Array<FaceId> dup_face_to_face_id(total_number_of_faces); { - descriptor.cell_face_is_reversed_vector.resize(descriptor.cell_to_node_vector.size()); - for (CellId j = 0; j < descriptor.cell_face_is_reversed_vector.size(); ++j) { - descriptor.cell_face_is_reversed_vector[j] = Array<bool>(cell_nb_faces[j]); + FaceId face_id = 0; + for (size_t i_dup_face = 0; i_dup_face < total_number_of_faces; ++i_dup_face) { + if (dup_face_to_face[i_dup_face] == i_dup_face) { + dup_face_to_face_id[i_dup_face] = face_id; + ++face_id; + } else { + size_t i_face = dup_face_to_face[i_dup_face]; + while (i_face != dup_face_to_face[i_face]) { + i_face = dup_face_to_face[i_face]; + } + dup_face_to_face_id[i_dup_face] = dup_face_to_face_id[i_face]; + } } - for (const auto& face_cells_vector : face_cells_map) { - const auto& cells_vector = face_cells_vector.second; - for (unsigned short lj = 0; lj < cells_vector.size(); ++lj) { - const auto& [cell_number, cell_local_face, reversed] = cells_vector[lj]; - descriptor.cell_face_is_reversed_vector[cell_number][cell_local_face] = reversed; + } + + Array<unsigned int> node_to_face_row(node_to_duplicate_face_row.size()); + { + unsigned int nb_faces = 0; + for (size_t i_node = 0; i_node < node_to_duplicate_face_row.size() - 1; ++i_node) { + node_to_face_row[i_node] = nb_faces; + for (size_t i_face = node_to_duplicate_face_row[i_node]; i_face < node_to_duplicate_face_row[i_node + 1]; + ++i_face) { + if (dup_face_to_face[node_duplicate_face_list[i_face]] == node_duplicate_face_list[i_face]) { + ++nb_faces; + } + } + } + node_to_face_row[node_to_duplicate_face_row.size() - 1] = nb_faces; + } + + Array<unsigned int> node_to_face_list(node_to_face_row[node_to_duplicate_face_row.size() - 1]); + { + unsigned int i_node_to_face = 0; + for (size_t i_node = 0; i_node < node_to_duplicate_face_row.size() - 1; ++i_node) { + for (size_t i_face = node_to_duplicate_face_row[i_node]; i_face < node_to_duplicate_face_row[i_node + 1]; + ++i_face) { + if (dup_face_to_face[node_duplicate_face_list[i_face]] == node_duplicate_face_list[i_face]) { + node_to_face_list[i_node_to_face++] = dup_face_to_face_id[node_duplicate_face_list[i_face]]; + } + } + } + } + + descriptor.setNodeToFaceMatrix(ConnectivityMatrix(node_to_face_row, node_to_face_list)); + + Array<unsigned int> cell_to_face_row(cell_nb_faces.size() + 1); + cell_to_face_row[0] = 0; + for (size_t i = 0; i < cell_nb_faces.size(); ++i) { + cell_to_face_row[i + 1] = cell_to_face_row[i] + cell_nb_faces[i]; + } + + Array<unsigned int> cell_to_face_list(cell_to_face_row[cell_to_face_row.size() - 1]); + { + size_t i_cell_face = 0; + for (CellId cell_id = 0; cell_id < cell_nb_faces.size(); ++cell_id) { + for (size_t i_face = 0; i_face < cell_nb_faces[cell_id]; ++i_face) { + cell_to_face_list[i_cell_face++] = dup_face_to_face_id[cell_to_face_row[cell_id] + i_face]; } } } + descriptor.setCellToFaceMatrix(ConnectivityMatrix(cell_to_face_row, cell_to_face_list)); + + descriptor.setFaceNumberVector([&] { + Array<int> face_number_vector(total_number_of_faces - nb_dup_faces); + parallel_for( + face_number_vector.size(), PUGS_LAMBDA(const size_t l) { face_number_vector[l] = l; }); + return face_number_vector; + }()); + + Array<unsigned int> face_ending(total_number_of_faces - nb_dup_faces + 1); { - descriptor.face_to_node_vector.resize(face_cells_map.size()); - int l = 0; - for (const auto& face_info : face_cells_map) { - const Face& face = face_info.first; - descriptor.face_to_node_vector[l] = face.nodeIdList(); - ++l; + size_t i_face = 0; + face_ending[0] = 0; + for (size_t i_dup_face = 0; i_dup_face < dup_face_to_face.size(); ++i_dup_face) { + if (dup_face_to_face[i_dup_face] == i_dup_face) { + face_ending[i_face + 1] = + dup_face_to_node_row[i_dup_face + 1] - dup_face_to_node_row[i_dup_face] + face_ending[i_face]; + ++i_face; + } } } + Array<unsigned int> faces_node_list(face_ending[face_ending.size() - 1]); { - // Face numbers may change if numbers are provided in the file - descriptor.face_number_vector.resize(face_cells_map.size()); - for (size_t l = 0; l < face_cells_map.size(); ++l) { - descriptor.face_number_vector[l] = l; + size_t i_face = 0; + face_ending[0] = 0; + for (size_t i_dup_face = 0; i_dup_face < dup_face_to_face.size(); ++i_dup_face) { + if (dup_face_to_face[i_dup_face] == i_dup_face) { + size_t dup_face_node_begin = dup_face_to_node_row[i_dup_face]; + size_t face_node_begin = face_ending[i_face]; + + for (size_t i_face_node = 0; + i_face_node < dup_face_to_node_row[i_dup_face + 1] - dup_face_to_node_row[i_dup_face]; ++i_face_node) { + faces_node_list[face_node_begin + i_face_node] = dup_faces_to_node_list[dup_face_node_begin + i_face_node]; + } + ++i_face; + } } } + + descriptor.setFaceToNodeMatrix(ConnectivityMatrix(face_ending, faces_node_list)); + + descriptor.setCellFaceIsReversed(cell_face_is_reversed); } template <size_t Dimension> @@ -257,206 +598,331 @@ void ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities(ConnectivityDescriptor& descriptor) { static_assert(Dimension == 3, "Invalid dimension to compute face-edge connectivities"); - using FaceEdgeInfo = std::tuple<FaceId, unsigned short, bool>; - using Edge = ConnectivityFace<2>; - - const auto& node_number_vector = descriptor.node_number_vector; - Array<unsigned short> face_nb_edges(descriptor.face_to_node_vector.size()); - std::map<Edge, std::vector<FaceEdgeInfo>> edge_faces_map; - for (FaceId l = 0; l < descriptor.face_to_node_vector.size(); ++l) { - const auto& face_nodes = descriptor.face_to_node_vector[l]; - - face_nb_edges[l] = face_nodes.size(); - for (size_t r = 0; r < face_nodes.size() - 1; ++r) { - Edge e({face_nodes[r], face_nodes[r + 1]}, node_number_vector); - edge_faces_map[e].emplace_back(std::make_tuple(l, r, e.reversed())); - } - { - Edge e({face_nodes[face_nodes.size() - 1], face_nodes[0]}, node_number_vector); - edge_faces_map[e].emplace_back(std::make_tuple(l, face_nodes.size() - 1, e.reversed())); + + const auto& face_to_node_matrix = descriptor.faceToNodeMatrix(); + + Array<const unsigned int> face_to_edge_row = face_to_node_matrix.rowsMap(); + + const size_t total_number_of_face_edges = face_to_edge_row[face_to_edge_row.size() - 1]; + + const size_t total_number_of_node_by_face_edges = 2 * total_number_of_face_edges; + + Array<unsigned int> face_edge_to_node_list(total_number_of_node_by_face_edges); + { + size_t i_edge_node = 0; + for (size_t i_face = 0; i_face < face_to_edge_row.size() - 1; ++i_face) { + const auto& face_node_list = face_to_node_matrix[i_face]; + for (size_t i_node = 0; i_node < face_node_list.size() - 1; ++i_node) { + face_edge_to_node_list[i_edge_node++] = face_node_list[i_node]; + face_edge_to_node_list[i_edge_node++] = face_node_list[i_node + 1]; + } + face_edge_to_node_list[i_edge_node++] = face_node_list[face_node_list.size() - 1]; + face_edge_to_node_list[i_edge_node++] = face_node_list[0]; } } - std::unordered_map<Edge, EdgeId, typename Edge::Hash> edge_id_map; - { - descriptor.face_to_edge_vector.resize(descriptor.face_to_node_vector.size()); - for (FaceId l = 0; l < descriptor.face_to_node_vector.size(); ++l) { - descriptor.face_to_edge_vector[l].resize(face_nb_edges[l]); + auto node_number_vector = descriptor.nodeNumberVector(); + Array<bool> face_edge_is_reversed(total_number_of_face_edges); + for (size_t i_edge = 0; i_edge < total_number_of_face_edges; ++i_edge) { + if (node_number_vector[face_edge_to_node_list[2 * i_edge]] > + node_number_vector[face_edge_to_node_list[2 * i_edge + 1]]) { + std::swap(face_edge_to_node_list[2 * i_edge], face_edge_to_node_list[2 * i_edge + 1]); + face_edge_is_reversed[i_edge] = true; + } else { + face_edge_is_reversed[i_edge] = false; } - EdgeId e = 0; - for (const auto& edge_faces_vector : edge_faces_map) { - const auto& faces_vector = edge_faces_vector.second; - for (unsigned short l = 0; l < faces_vector.size(); ++l) { - const auto& [face_number, face_local_edge, reversed] = faces_vector[l]; - descriptor.face_to_edge_vector[face_number][face_local_edge] = e; - } - edge_id_map[edge_faces_vector.first] = e; - ++e; + } + + const size_t total_number_of_edges = face_edge_is_reversed.size(); + Array<unsigned int> node_to_face_edge_row(node_number_vector.size() + 1); + node_to_face_edge_row.fill(0); + for (size_t i_edge = 0; i_edge < total_number_of_edges; ++i_edge) { + for (size_t i_edge_node = 0; i_edge_node < 2; ++i_edge_node) { + node_to_face_edge_row[face_edge_to_node_list[2 * i_edge + i_edge_node] + 1]++; } } + for (size_t i_node = 1; i_node < node_to_face_edge_row.size(); ++i_node) { + node_to_face_edge_row[i_node] += node_to_face_edge_row[i_node - 1]; + } + + Array<unsigned int> node_to_face_edge_list(node_to_face_edge_row[node_to_face_edge_row.size() - 1]); { - descriptor.face_edge_is_reversed_vector.resize(descriptor.face_to_node_vector.size()); - for (FaceId j = 0; j < descriptor.face_edge_is_reversed_vector.size(); ++j) { - descriptor.face_edge_is_reversed_vector[j] = Array<bool>(face_nb_edges[j]); + Array<unsigned int> node_to_face_edge_row_idx(node_number_vector.size()); + node_to_face_edge_row_idx.fill(0); + + for (size_t i_edge = 0; i_edge < total_number_of_edges; ++i_edge) { + for (size_t i_edge_node = 0; i_edge_node < 2; ++i_edge_node) { + const size_t node_id = face_edge_to_node_list[2 * i_edge + i_edge_node]; + + node_to_face_edge_list[node_to_face_edge_row[node_id] + node_to_face_edge_row_idx[node_id]] = i_edge; + node_to_face_edge_row_idx[node_id]++; + } } - for (const auto& edge_faces_vector : edge_faces_map) { - const auto& faces_vector = edge_faces_vector.second; - for (unsigned short lj = 0; lj < faces_vector.size(); ++lj) { - const auto& [face_number, face_local_edge, reversed] = faces_vector[lj]; - descriptor.face_edge_is_reversed_vector[face_number][face_local_edge] = reversed; + } + + Array<unsigned int> face_edge_to_edge(total_number_of_edges); + parallel_for( + total_number_of_edges, PUGS_LAMBDA(size_t i_edge) { face_edge_to_edge[i_edge] = i_edge; }); + + auto is_same_face = [=](const size_t i_edge, const size_t j_edge) { + auto i_edge_first_node = 2 * i_edge; + auto j_edge_first_node = 2 * j_edge; + return ((face_edge_to_node_list[i_edge_first_node] == face_edge_to_node_list[j_edge_first_node]) and + (face_edge_to_node_list[i_edge_first_node + 1] == face_edge_to_node_list[j_edge_first_node + 1])); + }; + + size_t nb_duplicate_edges = 0; + for (size_t i_node = 0; i_node < node_number_vector.size(); ++i_node) { + for (size_t i_node_face = node_to_face_edge_row[i_node]; i_node_face < node_to_face_edge_row[i_node + 1] - 1; + ++i_node_face) { + const unsigned int i_edge = node_to_face_edge_list[i_node_face]; + const unsigned int i_edge_id = face_edge_to_edge[i_edge]; + for (size_t j_node_face = i_node_face + 1; j_node_face < node_to_face_edge_row[i_node + 1]; ++j_node_face) { + const unsigned int j_edge = node_to_face_edge_list[j_node_face]; + unsigned int& j_edge_id = face_edge_to_edge[j_edge]; + if (i_edge_id != j_edge_id) { + if (is_same_face(i_edge, j_edge)) { + j_edge_id = i_edge_id; + nb_duplicate_edges++; + } + } } } } + // compute edge_id + Array<EdgeId> dup_edge_to_edge_id(total_number_of_edges); { - descriptor.edge_to_node_vector.resize(edge_faces_map.size()); - int e = 0; - for (const auto& edge_info : edge_faces_map) { - const Edge& edge = edge_info.first; - descriptor.edge_to_node_vector[e] = edge.nodeIdList(); - ++e; + EdgeId edge_id = 0; + for (size_t i_dup_edge = 0; i_dup_edge < total_number_of_edges; ++i_dup_edge) { + if (face_edge_to_edge[i_dup_edge] == i_dup_edge) { + dup_edge_to_edge_id[i_dup_edge] = edge_id++; + } else { + size_t i_edge = i_dup_edge; + do { + i_edge = face_edge_to_edge[i_edge]; + } while (i_edge != face_edge_to_edge[i_edge]); + + dup_edge_to_edge_id[i_dup_edge] = dup_edge_to_edge_id[i_edge]; + } } } + Array<unsigned int> edge_to_node_list(2 * (total_number_of_edges - nb_duplicate_edges)); { - // Edge numbers may change if numbers are provided in the file - descriptor.edge_number_vector.resize(edge_faces_map.size()); - for (size_t e = 0; e < edge_faces_map.size(); ++e) { - descriptor.edge_number_vector[e] = e; + for (size_t i_dup_edge = 0; i_dup_edge < total_number_of_edges; ++i_dup_edge) { + if (face_edge_to_edge[i_dup_edge] == i_dup_edge) { + const EdgeId edge_id = dup_edge_to_edge_id[i_dup_edge]; + edge_to_node_list[2 * edge_id] = face_edge_to_node_list[2 * i_dup_edge]; + edge_to_node_list[2 * edge_id + 1] = face_edge_to_node_list[2 * i_dup_edge + 1]; + } } } - { - descriptor.cell_to_edge_vector.reserve(descriptor.cell_to_node_vector.size()); - for (CellId j = 0; j < descriptor.cell_to_node_vector.size(); ++j) { - const auto& cell_nodes = descriptor.cell_to_node_vector[j]; + descriptor.setEdgeNumberVector([&] { + Array<int> edge_number_vector(total_number_of_edges - nb_duplicate_edges); + parallel_for( + edge_number_vector.size(), PUGS_LAMBDA(const size_t i_edge) { edge_number_vector[i_edge] = i_edge; }); + return edge_number_vector; + }()); - switch (descriptor.cell_type_vector[j]) { - case CellType::Tetrahedron: { - constexpr int local_edge[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {3, 1}}; - std::vector<unsigned int> cell_edge_vector; - cell_edge_vector.reserve(6); - for (int i_edge = 0; i_edge < 6; ++i_edge) { - const auto e = local_edge[i_edge]; - Edge edge{{cell_nodes[e[0]], cell_nodes[e[1]]}, node_number_vector}; - auto i = edge_id_map.find(edge); - if (i == edge_id_map.end()) { - throw NormalError("could not find this edge"); + Array<unsigned int> edge_to_node_row(total_number_of_edges - nb_duplicate_edges + 1); + parallel_for( + edge_to_node_row.size(), PUGS_LAMBDA(const size_t i_edge) { edge_to_node_row[i_edge] = 2 * i_edge; }); + + descriptor.setEdgeToNodeMatrix(ConnectivityMatrix(edge_to_node_row, edge_to_node_list)); + + // Use real edge ids + for (size_t i_edge = 0; i_edge < face_edge_to_edge.size(); ++i_edge) { + face_edge_to_edge[i_edge] = dup_edge_to_edge_id[face_edge_to_edge[i_edge]]; + } + + descriptor.setFaceToEdgeMatrix(ConnectivityMatrix(face_to_edge_row, face_edge_to_edge)); + descriptor.setFaceEdgeIsReversed(face_edge_is_reversed); + + Array<size_t> node_to_duplicated_edge_id_list(node_to_face_edge_list.size()); + for (size_t i_node_edge = 0; i_node_edge < node_to_duplicated_edge_id_list.size(); ++i_node_edge) { + node_to_duplicated_edge_id_list[i_node_edge] = dup_edge_to_edge_id[node_to_face_edge_list[i_node_edge]]; + } + + Array<bool> node_to_edge_is_duplicated(node_to_face_edge_list.size()); + node_to_edge_is_duplicated.fill(false); + + Array<unsigned int> node_nb_edges(node_number_vector.size()); + node_nb_edges.fill(0); + + for (size_t node_id = 0; node_id < node_number_vector.size(); ++node_id) { + size_t nb_dup_edges = 0; + for (EdgeId i_edge = node_to_face_edge_row[node_id]; i_edge < node_to_face_edge_row[node_id + 1] - 1; ++i_edge) { + if (not node_to_edge_is_duplicated[i_edge]) { + for (EdgeId j_edge = i_edge + 1; j_edge < node_to_face_edge_row[node_id + 1]; ++j_edge) { + if (node_to_duplicated_edge_id_list[i_edge] == node_to_duplicated_edge_id_list[j_edge]) { + node_to_edge_is_duplicated[j_edge] = true; + nb_dup_edges++; } - cell_edge_vector.push_back(i->second); } - descriptor.cell_to_edge_vector.emplace_back(cell_edge_vector); - break; } - case CellType::Hexahedron: { - constexpr int local_edge[12][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6}, - {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}}; - std::vector<unsigned int> cell_edge_vector; - cell_edge_vector.reserve(12); - for (int i_edge = 0; i_edge < 12; ++i_edge) { - const auto e = local_edge[i_edge]; - Edge edge{{cell_nodes[e[0]], cell_nodes[e[1]]}, node_number_vector}; - auto i = edge_id_map.find(edge); - if (i == edge_id_map.end()) { - throw NormalError("could not find this edge"); - } - cell_edge_vector.push_back(i->second); - } - descriptor.cell_to_edge_vector.emplace_back(cell_edge_vector); - break; + } + node_nb_edges[node_id] = node_to_face_edge_row[node_id + 1] - node_to_face_edge_row[node_id] - nb_dup_edges; + } + + Array<unsigned int> node_to_edge_row(node_number_vector.size() + 1); + node_to_edge_row[0] = 0; + for (size_t node_id = 0; node_id < node_number_vector.size(); ++node_id) { + node_to_edge_row[node_id + 1] = node_to_edge_row[node_id] + node_nb_edges[node_id]; + } + + Array<unsigned int> node_to_edge_list(node_to_edge_row[node_to_edge_row.size() - 1]); + { + size_t l = 0; + for (size_t i_edge_id = 0; i_edge_id < node_to_duplicated_edge_id_list.size(); ++i_edge_id) { + if (not node_to_edge_is_duplicated[i_edge_id]) { + node_to_edge_list[l++] = node_to_duplicated_edge_id_list[i_edge_id]; } - case CellType::Prism: { - constexpr int local_edge[12][2] = {{0, 1}, {1, 2}, {2, 0}, {3, 4}, {4, 5}, {5, 3}, {0, 3}, {1, 4}, {2, 5}}; - std::vector<unsigned int> cell_edge_vector; - cell_edge_vector.reserve(9); - for (int i_edge = 0; i_edge < 9; ++i_edge) { - const auto e = local_edge[i_edge]; - Edge edge{{cell_nodes[e[0]], cell_nodes[e[1]]}, node_number_vector}; - auto i = edge_id_map.find(edge); - if (i == edge_id_map.end()) { - throw NormalError("could not find this edge"); - } - cell_edge_vector.push_back(i->second); + } + } + + descriptor.setNodeToEdgeMatrix(ConnectivityMatrix(node_to_edge_row, node_to_edge_list)); + + auto find_edge = [=](const NodeId& node0_id, const NodeId& node1_id) -> EdgeId { + auto [first_node_id, second_node_id] = [&] { + if (node_number_vector[node0_id] < node_number_vector[node1_id]) { + return std::make_pair(node0_id, node1_id); + } else { + return std::make_pair(node1_id, node0_id); + } + }(); + + for (size_t i_node_edge = node_to_edge_row[first_node_id]; i_node_edge < node_to_edge_row[first_node_id + 1]; + ++i_node_edge) { + EdgeId edge_id = node_to_edge_list[i_node_edge]; + if (edge_to_node_list[2 * edge_id + 1] == second_node_id) { + return edge_id; + } + } + throw UnexpectedError("Cannot find cell edge in edge list"); + }; + + const auto& cell_to_node_matrix = descriptor.cellToNodeMatrix(); + const auto& cell_type_vector = descriptor.cellTypeVector(); + { + Array<unsigned int> cell_to_edge_row(cell_to_node_matrix.numberOfRows() + 1); + { + cell_to_edge_row[0] = 0; + + for (CellId cell_id = 0; cell_id < cell_to_node_matrix.numberOfRows(); ++cell_id) { + switch (cell_type_vector[cell_id]) { + case CellType::Tetrahedron: { + cell_to_edge_row[cell_id + 1] = cell_to_edge_row[cell_id] + 6; + break; + } + case CellType::Hexahedron: { + cell_to_edge_row[cell_id + 1] = cell_to_edge_row[cell_id] + 12; + break; + } + case CellType::Prism: { + cell_to_edge_row[cell_id + 1] = cell_to_edge_row[cell_id] + 9; + break; + } + case CellType::Pyramid: { + cell_to_edge_row[cell_id + 1] = cell_to_edge_row[cell_id] + 2 * (cell_to_node_matrix[cell_id].size() - 1); + break; + } + case CellType::Diamond: { + cell_to_edge_row[cell_id + 1] = cell_to_edge_row[cell_id] + 3 * (cell_to_node_matrix[cell_id].size() - 2); + break; + } + default: { + std::stringstream error_msg; + error_msg << name(cell_type_vector[cell_id]) << ": unexpected cell type in dimension 3"; + throw NotImplementedError(error_msg.str()); + } } - descriptor.cell_to_edge_vector.emplace_back(cell_edge_vector); - break; } - case CellType::Pyramid: { - const size_t number_of_edges = 2 * cell_nodes.size(); - std::vector<unsigned int> base_nodes; - std::copy_n(cell_nodes.begin(), cell_nodes.size() - 1, std::back_inserter(base_nodes)); - - std::vector<unsigned int> cell_edge_vector; - cell_edge_vector.reserve(number_of_edges); - for (size_t i_edge = 0; i_edge < base_nodes.size(); ++i_edge) { - Edge edge{{base_nodes[i_edge], base_nodes[(i_edge + 1) % base_nodes.size()]}, node_number_vector}; - auto i = edge_id_map.find(edge); - if (i == edge_id_map.end()) { - throw NormalError("could not find this edge"); + } + + Array<unsigned int> cell_to_edge_list(cell_to_edge_row[cell_to_edge_row.size() - 1]); + { + size_t i_cell_edge = 0; + for (CellId cell_id = 0; cell_id < cell_to_node_matrix.numberOfRows(); ++cell_id) { + const auto& cell_nodes = cell_to_node_matrix[cell_id]; + + switch (cell_type_vector[cell_id]) { + case CellType::Tetrahedron: { + constexpr int local_edge[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {3, 1}}; + for (int i_edge = 0; i_edge < 6; ++i_edge) { + const auto& e = local_edge[i_edge]; + cell_to_edge_list[i_cell_edge++] = find_edge(cell_nodes[e[0]], cell_nodes[e[1]]); } - cell_edge_vector.push_back(i->second); + break; } + case CellType::Hexahedron: { + constexpr int local_edge[12][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6}, + {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}}; - const unsigned int top_vertex = cell_nodes[cell_nodes.size() - 1]; - for (size_t i_edge = 0; i_edge < base_nodes.size(); ++i_edge) { - Edge edge{{base_nodes[i_edge], top_vertex}, node_number_vector}; - auto i = edge_id_map.find(edge); - if (i == edge_id_map.end()) { - throw NormalError("could not find this edge"); + for (int i_edge = 0; i_edge < 12; ++i_edge) { + const auto& e = local_edge[i_edge]; + cell_to_edge_list[i_cell_edge++] = find_edge(cell_nodes[e[0]], cell_nodes[e[1]]); } - cell_edge_vector.push_back(i->second); + break; } - descriptor.cell_to_edge_vector.emplace_back(cell_edge_vector); - break; - } - case CellType::Diamond: { - const size_t number_of_edges = 3 * cell_nodes.size(); - std::vector<unsigned int> base_nodes; - std::copy_n(cell_nodes.begin() + 1, cell_nodes.size() - 2, std::back_inserter(base_nodes)); - - std::vector<unsigned int> cell_edge_vector; - cell_edge_vector.reserve(number_of_edges); - for (size_t i_edge = 0; i_edge < base_nodes.size(); ++i_edge) { - Edge edge{{base_nodes[i_edge], base_nodes[(i_edge + 1) % base_nodes.size()]}, node_number_vector}; - auto i = edge_id_map.find(edge); - if (i == edge_id_map.end()) { - throw NormalError("could not find this edge"); + case CellType::Prism: { + constexpr int local_edge[9][2] = {{0, 1}, {1, 2}, {2, 0}, {3, 4}, {4, 5}, {5, 3}, {0, 3}, {1, 4}, {2, 5}}; + for (int i_edge = 0; i_edge < 9; ++i_edge) { + const auto& e = local_edge[i_edge]; + cell_to_edge_list[i_cell_edge++] = find_edge(cell_nodes[e[0]], cell_nodes[e[1]]); } - cell_edge_vector.push_back(i->second); + break; } + case CellType::Pyramid: { + auto base_nodes = [&](size_t i) { return cell_nodes[i]; }; - const unsigned int top_vertex = cell_nodes[cell_nodes.size() - 1]; - for (size_t i_edge = 0; i_edge < base_nodes.size(); ++i_edge) { - Edge edge{{base_nodes[i_edge], top_vertex}, node_number_vector}; - auto i = edge_id_map.find(edge); - if (i == edge_id_map.end()) { - throw NormalError("could not find this edge"); + for (size_t i_edge = 0; i_edge < cell_nodes.size() - 1; ++i_edge) { + cell_to_edge_list[i_cell_edge++] = + find_edge(base_nodes(i_edge), base_nodes((i_edge + 1) % (cell_nodes.size() - 1))); } - cell_edge_vector.push_back(i->second); - } - const unsigned int bottom_vertex = cell_nodes[0]; - for (size_t i_edge = 0; i_edge < base_nodes.size(); ++i_edge) { - Edge edge{{base_nodes[i_edge], bottom_vertex}, node_number_vector}; - auto i = edge_id_map.find(edge); - if (i == edge_id_map.end()) { - throw NormalError("could not find this edge"); + const unsigned int top_vertex = cell_nodes[cell_nodes.size() - 1]; + for (size_t i_edge = 0; i_edge < cell_nodes.size() - 1; ++i_edge) { + cell_to_edge_list[i_cell_edge++] = find_edge(base_nodes(i_edge), top_vertex); } - cell_edge_vector.push_back(i->second); + break; } + case CellType::Diamond: { + auto base_nodes = [&](size_t i) { return cell_nodes[i + 1]; }; - descriptor.cell_to_edge_vector.emplace_back(cell_edge_vector); + for (size_t i_edge = 0; i_edge < cell_nodes.size() - 2; ++i_edge) { + cell_to_edge_list[i_cell_edge++] = + find_edge(base_nodes(i_edge), base_nodes((i_edge + 1) % (cell_nodes.size() - 2))); + } - break; - } - default: { - std::stringstream error_msg; - error_msg << name(descriptor.cell_type_vector[j]) << ": unexpected cell type in dimension 3"; - throw NotImplementedError(error_msg.str()); - } + { + const unsigned int top_vertex = cell_nodes[cell_nodes.size() - 1]; + for (size_t i_edge = 0; i_edge < cell_nodes.size() - 2; ++i_edge) { + cell_to_edge_list[i_cell_edge++] = find_edge(base_nodes(i_edge), top_vertex); + } + } + + { + const unsigned int bottom_vertex = cell_nodes[0]; + for (size_t i_edge = 0; i_edge < cell_nodes.size() - 2; ++i_edge) { + cell_to_edge_list[i_cell_edge++] = find_edge(base_nodes(i_edge), bottom_vertex); + } + } + + break; + } + default: { + std::stringstream error_msg; + error_msg << name(cell_type_vector[cell_id]) << ": unexpected cell type in dimension 3"; + throw NotImplementedError(error_msg.str()); + } + } } } + + descriptor.setCellToEdgeMatrix(ConnectivityMatrix(cell_to_edge_row, cell_to_edge_list)); } } diff --git a/src/mesh/ConnectivityBuilderBase.hpp b/src/mesh/ConnectivityBuilderBase.hpp index f9b0d28a7a9389093348648573c85875f1e4a7de..a621e91f46ffe7e6ecb5ea6d496934a03571ba6e 100644 --- a/src/mesh/ConnectivityBuilderBase.hpp +++ b/src/mesh/ConnectivityBuilderBase.hpp @@ -15,9 +15,6 @@ class ConnectivityDescriptor; class ConnectivityBuilderBase { protected: - template <size_t Dimension> - class ConnectivityFace; - std::shared_ptr<const IConnectivity> m_connectivity; template <size_t Dimension> @@ -37,190 +34,4 @@ class ConnectivityBuilderBase ~ConnectivityBuilderBase() = default; }; -template <> -class ConnectivityBuilderBase::ConnectivityFace<2> -{ - public: - friend struct Hash; - - struct Hash - { - size_t - operator()(const ConnectivityFace& f) const - { - size_t hash = 0; - hash ^= std::hash<unsigned int>()(f.m_node0_id); - hash ^= std::hash<unsigned int>()(f.m_node1_id) >> 1; - return hash; - } - }; - - private: - const std::vector<int>& m_node_number_vector; - - unsigned int m_node0_id; - unsigned int m_node1_id; - - bool m_reversed; - - public: - std::vector<unsigned int> - nodeIdList() const - { - return {m_node0_id, m_node1_id}; - } - - bool - reversed() const - { - return m_reversed; - } - - PUGS_INLINE - bool - operator==(const ConnectivityFace& f) const - { - return ((m_node0_id == f.m_node0_id) and (m_node1_id == f.m_node1_id)); - } - - PUGS_INLINE - bool - operator<(const ConnectivityFace& f) const - { - return ((m_node_number_vector[m_node0_id] < m_node_number_vector[f.m_node0_id]) or - ((m_node_number_vector[m_node0_id] == m_node_number_vector[f.m_node0_id]) and - (m_node_number_vector[m_node1_id] < m_node_number_vector[f.m_node1_id]))); - } - - PUGS_INLINE - ConnectivityFace(const std::vector<unsigned int>& node_id_list, const std::vector<int>& node_number_vector) - : m_node_number_vector(node_number_vector) - { - Assert(node_id_list.size() == 2); - - if (m_node_number_vector[node_id_list[0]] < m_node_number_vector[node_id_list[1]]) { - m_node0_id = node_id_list[0]; - m_node1_id = node_id_list[1]; - m_reversed = false; - } else { - m_node0_id = node_id_list[1]; - m_node1_id = node_id_list[0]; - m_reversed = true; - } - } - - PUGS_INLINE - ConnectivityFace(const ConnectivityFace&) = default; - - PUGS_INLINE - ~ConnectivityFace() = default; -}; - -template <> -class ConnectivityBuilderBase::ConnectivityFace<3> -{ - public: - friend struct Hash; - - struct Hash - { - size_t - operator()(const ConnectivityFace& f) const - { - size_t hash = 0; - for (size_t i = 0; i < f.m_node_id_list.size(); ++i) { - hash ^= std::hash<unsigned int>()(f.m_node_id_list[i]) >> i; - } - return hash; - } - }; - - private: - bool m_reversed; - std::vector<NodeId::base_type> m_node_id_list; - const std::vector<int>& m_node_number_vector; - - PUGS_INLINE - std::vector<unsigned int> - _sort(const std::vector<unsigned int>& node_list) - { - const auto min_id = std::min_element(node_list.begin(), node_list.end()); - const int shift = std::distance(node_list.begin(), min_id); - - std::vector<unsigned int> rotated_node_list(node_list.size()); - if (node_list[(shift + 1) % node_list.size()] > node_list[(shift + node_list.size() - 1) % node_list.size()]) { - for (size_t i = 0; i < node_list.size(); ++i) { - rotated_node_list[i] = node_list[(shift + node_list.size() - i) % node_list.size()]; - m_reversed = true; - } - } else { - for (size_t i = 0; i < node_list.size(); ++i) { - rotated_node_list[i] = node_list[(shift + i) % node_list.size()]; - } - } - - return rotated_node_list; - } - - public: - PUGS_INLINE - const bool& - reversed() const - { - return m_reversed; - } - - PUGS_INLINE - const std::vector<unsigned int>& - nodeIdList() const - { - return m_node_id_list; - } - - PUGS_INLINE - ConnectivityFace(const std::vector<unsigned int>& given_node_id_list, const std::vector<int>& node_number_vector) - : m_reversed(false), m_node_id_list(_sort(given_node_id_list)), m_node_number_vector(node_number_vector) - { - ; - } - - public: - bool - operator==(const ConnectivityFace& f) const - { - if (m_node_id_list.size() == f.nodeIdList().size()) { - for (size_t j = 0; j < m_node_id_list.size(); ++j) { - if (m_node_id_list[j] != f.nodeIdList()[j]) { - return false; - } - } - return true; - } - return false; - } - - PUGS_INLINE - bool - operator<(const ConnectivityFace& f) const - { - const size_t min_nb_nodes = std::min(f.m_node_id_list.size(), m_node_id_list.size()); - for (size_t i = 0; i < min_nb_nodes; ++i) { - if (m_node_id_list[i] < f.m_node_id_list[i]) - return true; - if (m_node_id_list[i] != f.m_node_id_list[i]) - return false; - } - return m_node_id_list.size() < f.m_node_id_list.size(); - } - - PUGS_INLINE - ConnectivityFace(const ConnectivityFace&) = default; - - PUGS_INLINE - ConnectivityFace() = delete; - - PUGS_INLINE - ~ConnectivityFace() = default; -}; - #endif // CONNECTIVITY_BUILDER_BASE_HPP diff --git a/src/mesh/ConnectivityComputer.cpp b/src/mesh/ConnectivityComputer.cpp index aa8ca779cfb965ffb3e85e4feb1b4b9feabb79ca..1d5514627a5dac75d41ba5e4d08fa182d37e552f 100644 --- a/src/mesh/ConnectivityComputer.cpp +++ b/src/mesh/ConnectivityComputer.cpp @@ -7,62 +7,90 @@ template <typename ConnectivityType> PUGS_INLINE ConnectivityMatrix -ConnectivityComputer::computeConnectivityMatrix(const ConnectivityType& connectivity, - ItemType item_type, - ItemType child_item_type) const +ConnectivityComputer::computeInverseConnectivityMatrix(const ConnectivityType& connectivity, + ItemType item_type, + ItemType child_item_type) const { - ConnectivityMatrix item_to_child_item_matrix; - if (connectivity.isConnectivityMatrixBuilt(child_item_type, item_type)) { - const ConnectivityMatrix& child_to_item_matrix = connectivity.getMatrix(child_item_type, item_type); + if (item_type < child_item_type) { + ConnectivityMatrix item_to_child_item_matrix; + if (connectivity.isConnectivityMatrixBuilt(child_item_type, item_type)) { + const ConnectivityMatrix& child_to_item_matrix = connectivity.getMatrix(child_item_type, item_type); + + switch (child_item_type) { + case ItemType::cell: { + item_to_child_item_matrix = + this->_computeInverseConnectivity<ConnectivityType, ItemType::cell>(connectivity, child_to_item_matrix); + break; + } + case ItemType::face: { + item_to_child_item_matrix = + this->_computeInverseConnectivity<ConnectivityType, ItemType::face>(connectivity, child_to_item_matrix); + break; + } + case ItemType::edge: { + item_to_child_item_matrix = + this->_computeInverseConnectivity<ConnectivityType, ItemType::edge>(connectivity, child_to_item_matrix); + break; + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("node cannot be child item when computing inverse connectivity"); + } + // LCOV_EXCL_STOP + } + } else { + std::stringstream error_msg; + error_msg << "unable to compute connectivity " << itemName(item_type) << " -> " << itemName(child_item_type); + throw UnexpectedError(error_msg.str()); + } - item_to_child_item_matrix = this->_computeInverse(child_to_item_matrix); + return item_to_child_item_matrix; } else { std::stringstream error_msg; - error_msg << "unable to compute connectivity " << itemName(item_type) << " -> " << itemName(child_item_type); + error_msg << "cannot deduce " << itemName(item_type) << " -> " << itemName(child_item_type) << " connectivity"; throw UnexpectedError(error_msg.str()); } - - return item_to_child_item_matrix; } -template ConnectivityMatrix ConnectivityComputer::computeConnectivityMatrix(const Connectivity1D&, - ItemType, - ItemType) const; +template ConnectivityMatrix ConnectivityComputer::computeInverseConnectivityMatrix(const Connectivity1D&, + ItemType, + ItemType) const; -template ConnectivityMatrix ConnectivityComputer::computeConnectivityMatrix(const Connectivity2D&, - ItemType, - ItemType) const; +template ConnectivityMatrix ConnectivityComputer::computeInverseConnectivityMatrix(const Connectivity2D&, + ItemType, + ItemType) const; -template ConnectivityMatrix ConnectivityComputer::computeConnectivityMatrix(const Connectivity3D&, - ItemType, - ItemType) const; +template ConnectivityMatrix ConnectivityComputer::computeInverseConnectivityMatrix(const Connectivity3D&, + ItemType, + ItemType) const; +template <typename ConnectivityType, ItemType child_item_type> ConnectivityMatrix -ConnectivityComputer::_computeInverse(const ConnectivityMatrix& item_to_child_matrix) const +ConnectivityComputer::_computeInverseConnectivity(const ConnectivityType& connectivity, + const ConnectivityMatrix& child_to_item_matrix) const { - const size_t& number_of_rows = item_to_child_matrix.numberOfRows(); + const size_t number_of_transposed_columns = child_to_item_matrix.numberOfRows(); - if ((item_to_child_matrix.values().size() > 0)) { - const size_t& number_of_columns = max(item_to_child_matrix.values()); + if ((child_to_item_matrix.values().size() > 0)) { + const size_t number_of_transposed_rows = max(child_to_item_matrix.values()) + 1; - Array<uint32_t> transposed_next_free_column_index(number_of_columns + 1); + Array<uint32_t> transposed_next_free_column_index(number_of_transposed_rows); transposed_next_free_column_index.fill(0); Array<uint32_t> transposed_rows_map(transposed_next_free_column_index.size() + 1); transposed_rows_map.fill(0); - for (size_t i = 0; i < number_of_rows; ++i) { - for (size_t j = item_to_child_matrix.rowsMap()[i]; j < item_to_child_matrix.rowsMap()[i + 1]; ++j) { - transposed_rows_map[item_to_child_matrix.values()[j] + 1]++; + for (size_t i = 0; i < number_of_transposed_columns; ++i) { + for (size_t j = child_to_item_matrix.rowsMap()[i]; j < child_to_item_matrix.rowsMap()[i + 1]; ++j) { + transposed_rows_map[child_to_item_matrix.values()[j] + 1]++; } } for (size_t i = 1; i < transposed_rows_map.size(); ++i) { transposed_rows_map[i] += transposed_rows_map[i - 1]; } Array<uint32_t> transposed_column_indices(transposed_rows_map[transposed_rows_map.size() - 1]); - - for (size_t i = 0; i < number_of_rows; ++i) { - for (size_t j = item_to_child_matrix.rowsMap()[i]; j < item_to_child_matrix.rowsMap()[i + 1]; ++j) { - size_t i_column_index = item_to_child_matrix.values()[j]; + for (size_t i = 0; i < number_of_transposed_columns; ++i) { + for (size_t j = child_to_item_matrix.rowsMap()[i]; j < child_to_item_matrix.rowsMap()[i + 1]; ++j) { + size_t i_column_index = child_to_item_matrix.values()[j]; uint32_t& shift = transposed_next_free_column_index[i_column_index]; transposed_column_indices[transposed_rows_map[i_column_index] + shift] = i; @@ -71,6 +99,18 @@ ConnectivityComputer::_computeInverse(const ConnectivityMatrix& item_to_child_ma } } + auto target_item_number = connectivity.template number<child_item_type>(); + // Finally one sorts target item_ids for parallel reproducibility + for (size_t i = 0; i < number_of_transposed_rows; ++i) { + auto row_begining = &(transposed_column_indices[transposed_rows_map[i]]); + auto row_size = (transposed_rows_map[i + 1] - transposed_rows_map[i]); + std::sort(row_begining, row_begining + row_size, + [&target_item_number](const ItemIdT<child_item_type> item0_id, + const ItemIdT<child_item_type> item1_id) { + return target_item_number[item0_id] < target_item_number[item1_id]; + }); + } + return ConnectivityMatrix{transposed_rows_map, transposed_column_indices}; } else { // empty connectivity diff --git a/src/mesh/ConnectivityComputer.hpp b/src/mesh/ConnectivityComputer.hpp index b033a25d5ccc04db84c194e79e492a081216a49e..7093aeef17707c37452b5e6874f6ed50a285dbb3 100644 --- a/src/mesh/ConnectivityComputer.hpp +++ b/src/mesh/ConnectivityComputer.hpp @@ -7,13 +7,15 @@ class ConnectivityComputer { private: - ConnectivityMatrix _computeInverse(const ConnectivityMatrix& item_to_child_matrix) const; + template <typename ConnectivityType, ItemType child_item_type> + ConnectivityMatrix _computeInverseConnectivity(const ConnectivityType& connectivity, + const ConnectivityMatrix& item_to_child_matrix) const; public: template <typename ConnectivityType> - ConnectivityMatrix computeConnectivityMatrix(const ConnectivityType& connectivity, - ItemType item_type, - ItemType child_item_type) const; + ConnectivityMatrix computeInverseConnectivityMatrix(const ConnectivityType& connectivity, + ItemType item_type, + ItemType child_item_type) const; template <typename ItemOfItem, typename ConnectivityType> void computeLocalItemNumberInChildItem(const ConnectivityType& connectivity) const; diff --git a/src/mesh/ConnectivityDescriptor.hpp b/src/mesh/ConnectivityDescriptor.hpp index 8f26988eadaa01dfec8aa0f14404a82819273475..dacf84d3cc84ab13629c09f163a16739db70dba3 100644 --- a/src/mesh/ConnectivityDescriptor.hpp +++ b/src/mesh/ConnectivityDescriptor.hpp @@ -2,6 +2,7 @@ #define CONNECTIVITY_DESCRIPTOR_HPP #include <mesh/CellType.hpp> +#include <mesh/ConnectivityMatrix.hpp> #include <mesh/ItemOfItemType.hpp> #include <mesh/RefItemList.hpp> #include <utils/PugsTraits.hpp> @@ -16,68 +17,337 @@ class ConnectivityDescriptor std::vector<RefEdgeList> m_ref_edge_list_vector; std::vector<RefNodeList> m_ref_node_list_vector; + ConnectivityMatrix m_cell_to_face_matrix = ConnectivityMatrix{true}; + ConnectivityMatrix m_cell_to_edge_matrix = ConnectivityMatrix{true}; + ConnectivityMatrix m_cell_to_node_matrix = ConnectivityMatrix{true}; + + ConnectivityMatrix m_face_to_edge_matrix = ConnectivityMatrix{true}; + ConnectivityMatrix m_face_to_node_matrix = ConnectivityMatrix{true}; + + ConnectivityMatrix m_edge_to_node_matrix = ConnectivityMatrix{true}; + + ConnectivityMatrix m_node_to_face_matrix = ConnectivityMatrix{true}; + ConnectivityMatrix m_node_to_edge_matrix = ConnectivityMatrix{true}; + + Array<const bool> m_cell_face_is_reversed; + Array<const bool> m_face_edge_is_reversed; + + Array<const CellType> m_cell_type_vector; + + Array<const int> m_cell_number_vector; + Array<const int> m_face_number_vector; + Array<const int> m_edge_number_vector; + Array<const int> m_node_number_vector; + + Array<const int> m_cell_owner_vector; + Array<const int> m_face_owner_vector; + Array<const int> m_edge_owner_vector; + Array<const int> m_node_owner_vector; + public: - std::vector<std::vector<unsigned int>> cell_to_node_vector; - std::vector<std::vector<unsigned int>> cell_to_face_vector; - std::vector<std::vector<unsigned int>> cell_to_edge_vector; + void + setCellNumberVector(const Array<const int>& cell_number_vector) + { + // No check since it can change reading file for instance + m_cell_number_vector = cell_number_vector; + } - std::vector<std::vector<unsigned int>> face_to_node_vector; - std::vector<std::vector<unsigned int>> face_to_edge_vector; + PUGS_INLINE + const Array<const int>& + cellNumberVector() const + { + return m_cell_number_vector; + } - std::vector<std::vector<unsigned int>> edge_to_node_vector; + void + setFaceNumberVector(const Array<const int>& face_number_vector) + { + // No check since it can change reading file for instance + m_face_number_vector = face_number_vector; + } - template <typename ItemOfItemT> - auto& - itemOfItemVector() + PUGS_INLINE + const Array<const int>& + faceNumberVector() const { - if constexpr (std::is_same_v<ItemOfItemT, NodeOfCell>) { - return cell_to_node_vector; - } else if constexpr (std::is_same_v<ItemOfItemT, FaceOfCell>) { - return cell_to_face_vector; - } else if constexpr (std::is_same_v<ItemOfItemT, EdgeOfCell>) { - return cell_to_edge_vector; - } else if constexpr (std::is_same_v<ItemOfItemT, EdgeOfFace>) { - return face_to_edge_vector; - } else if constexpr (std::is_same_v<ItemOfItemT, NodeOfFace>) { - return face_to_node_vector; - } else if constexpr (std::is_same_v<ItemOfItemT, NodeOfEdge>) { - return edge_to_node_vector; - } else { - static_assert(is_false_v<ItemOfItemT>, "Unexpected item of item type"); - } + return m_face_number_vector; + } + + void + setEdgeNumberVector(const Array<const int>& edge_number_vector) + { + // No check since it can change reading file for instance + m_edge_number_vector = edge_number_vector; } - std::vector<Array<bool>> cell_face_is_reversed_vector; - std::vector<Array<bool>> face_edge_is_reversed_vector; + PUGS_INLINE + const Array<const int>& + edgeNumberVector() const + { + return m_edge_number_vector; + } - std::vector<CellType> cell_type_vector; + void + setNodeNumberVector(const Array<const int>& node_number_vector) + { + // No check since it can change reading file for instance + m_node_number_vector = node_number_vector; + } - std::vector<int> cell_number_vector; - std::vector<int> face_number_vector; - std::vector<int> edge_number_vector; - std::vector<int> node_number_vector; + PUGS_INLINE + const Array<const int>& + nodeNumberVector() const + { + return m_node_number_vector; + } template <ItemType item_type> - const std::vector<int>& + Array<const int> itemNumberVector() const { if constexpr (item_type == ItemType::cell) { - return cell_number_vector; + return m_cell_number_vector; } else if constexpr (item_type == ItemType::face) { - return face_number_vector; + return m_face_number_vector; } else if constexpr (item_type == ItemType::edge) { - return edge_number_vector; + return m_edge_number_vector; } else if constexpr (item_type == ItemType::node) { - return node_number_vector; + return m_node_number_vector; } else { static_assert(is_false_item_type_v<item_type>, "Unexpected item type"); } } - std::vector<int> cell_owner_vector; - std::vector<int> face_owner_vector; - std::vector<int> edge_owner_vector; - std::vector<int> node_owner_vector; + void + setCellOwnerVector(const Array<const int>& cell_owner_vector) + { + Assert(m_cell_owner_vector.size() == 0); + m_cell_owner_vector = cell_owner_vector; + } + + PUGS_INLINE + const Array<const int>& + cellOwnerVector() const + { + return m_cell_owner_vector; + } + + void + setFaceOwnerVector(const Array<const int>& face_owner_vector) + { + Assert(m_face_owner_vector.size() == 0); + m_face_owner_vector = face_owner_vector; + } + + PUGS_INLINE + const Array<const int>& + faceOwnerVector() const + { + return m_face_owner_vector; + } + + void + setEdgeOwnerVector(const Array<const int>& edge_owner_vector) + { + Assert(m_edge_owner_vector.size() == 0); + m_edge_owner_vector = edge_owner_vector; + } + + PUGS_INLINE + const Array<const int>& + edgeOwnerVector() const + { + return m_edge_owner_vector; + } + + void + setNodeOwnerVector(const Array<const int>& node_owner_vector) + { + Assert(m_node_owner_vector.size() == 0); + m_node_owner_vector = node_owner_vector; + } + + PUGS_INLINE + const Array<const int>& + nodeOwnerVector() const + { + return m_node_owner_vector; + } + + void + setCellFaceIsReversed(const Array<const bool>& cell_face_is_reversed) + { + Assert(m_cell_face_is_reversed.size() == 0); + m_cell_face_is_reversed = cell_face_is_reversed; + } + + PUGS_INLINE + const Array<const bool>& + cellFaceIsReversed() const + { + return m_cell_face_is_reversed; + } + + void + setFaceEdgeIsReversed(const Array<const bool>& face_edge_is_reversed) + { + Assert(m_face_edge_is_reversed.size() == 0); + m_face_edge_is_reversed = face_edge_is_reversed; + } + + PUGS_INLINE + const Array<const bool>& + faceEdgeIsReversed() const + { + return m_face_edge_is_reversed; + } + + void + setCellTypeVector(const Array<const CellType>& cell_type_vector) + { + Assert(m_face_edge_is_reversed.size() == 0); + m_cell_type_vector = cell_type_vector; + } + + PUGS_INLINE + const Array<const CellType>& + cellTypeVector() const + { + return m_cell_type_vector; + } + + void + setCellToFaceMatrix(const ConnectivityMatrix& cell_to_face_matrix) + { + Assert(m_cell_to_face_matrix.numberOfRows() == 0); + m_cell_to_face_matrix = cell_to_face_matrix; + } + + void + setCellToEdgeMatrix(const ConnectivityMatrix& cell_to_edge_matrix) + { + Assert(m_cell_to_edge_matrix.numberOfRows() == 0); + m_cell_to_edge_matrix = cell_to_edge_matrix; + } + + void + setCellToNodeMatrix(const ConnectivityMatrix& cell_to_node_matrix) + { + Assert(m_cell_to_node_matrix.numberOfRows() == 0); + m_cell_to_node_matrix = cell_to_node_matrix; + } + + void + setFaceToEdgeMatrix(const ConnectivityMatrix& face_to_edge_matrix) + { + Assert(m_face_to_edge_matrix.numberOfRows() == 0); + m_face_to_edge_matrix = face_to_edge_matrix; + } + + void + setFaceToNodeMatrix(const ConnectivityMatrix& face_to_node_matrix) + { + Assert(m_face_to_node_matrix.numberOfRows() == 0); + m_face_to_node_matrix = face_to_node_matrix; + } + + void + setEdgeToNodeMatrix(const ConnectivityMatrix& edge_to_node_matrix) + { + Assert(m_edge_to_node_matrix.numberOfRows() == 0); + m_edge_to_node_matrix = edge_to_node_matrix; + } + + void + setNodeToFaceMatrix(const ConnectivityMatrix& node_to_face_matrix) + { + Assert(m_node_to_face_matrix.numberOfRows() == 0); + m_node_to_face_matrix = node_to_face_matrix; + } + + void + setNodeToEdgeMatrix(const ConnectivityMatrix& node_to_edge_matrix) + { + Assert(m_node_to_edge_matrix.numberOfRows() == 0); + m_node_to_edge_matrix = node_to_edge_matrix; + } + + PUGS_INLINE + const ConnectivityMatrix& + cellToFaceMatrix() const + { + return m_cell_to_face_matrix; + } + + PUGS_INLINE + const ConnectivityMatrix& + cellToEdgeMatrix() const + { + return m_cell_to_edge_matrix; + } + + PUGS_INLINE + const ConnectivityMatrix& + cellToNodeMatrix() const + { + return m_cell_to_node_matrix; + } + + PUGS_INLINE + const ConnectivityMatrix& + faceToEdgeMatrix() const + { + return m_face_to_edge_matrix; + } + + PUGS_INLINE + const ConnectivityMatrix& + faceToNodeMatrix() const + { + return m_face_to_node_matrix; + } + + PUGS_INLINE + const ConnectivityMatrix& + edgeToNodeMatrix() const + { + return m_edge_to_node_matrix; + } + + PUGS_INLINE + const ConnectivityMatrix& + nodeToFaceMatrix() const + { + return m_node_to_face_matrix; + } + + PUGS_INLINE + const ConnectivityMatrix& + nodeToEdgeMatrix() const + { + return m_node_to_edge_matrix; + } + + template <typename ItemOfItemT> + auto& + itemOfItemVector() + { + if constexpr (std::is_same_v<ItemOfItemT, NodeOfCell>) { + return m_cell_to_node_matrix; + } else if constexpr (std::is_same_v<ItemOfItemT, FaceOfCell>) { + return m_cell_to_face_matrix; + } else if constexpr (std::is_same_v<ItemOfItemT, EdgeOfCell>) { + return m_cell_to_edge_matrix; + } else if constexpr (std::is_same_v<ItemOfItemT, EdgeOfFace>) { + return m_face_to_edge_matrix; + } else if constexpr (std::is_same_v<ItemOfItemT, NodeOfFace>) { + return m_face_to_node_matrix; + } else if constexpr (std::is_same_v<ItemOfItemT, NodeOfEdge>) { + return m_edge_to_node_matrix; + } else { + static_assert(is_false_v<ItemOfItemT>, "Unexpected item of item type"); + } + } template <ItemType item_type> const std::vector<RefItemList<item_type>>& @@ -114,7 +384,7 @@ class ConnectivityDescriptor } ConnectivityDescriptor& operator=(const ConnectivityDescriptor&) = delete; - ConnectivityDescriptor& operator=(ConnectivityDescriptor&&) = delete; + ConnectivityDescriptor& operator=(ConnectivityDescriptor&&) = delete; ConnectivityDescriptor() = default; ConnectivityDescriptor(const ConnectivityDescriptor&) = default; diff --git a/src/mesh/ConnectivityDispatcher.cpp b/src/mesh/ConnectivityDispatcher.cpp index fd5b58c6daaf5fd44c0cb440e7af472b9f9aebbf..641d7f8666946a448d98e0a3311d5bd2a94329fc 100644 --- a/src/mesh/ConnectivityDispatcher.cpp +++ b/src/mesh/ConnectivityDispatcher.cpp @@ -145,19 +145,19 @@ template <int Dimension> template <typename DataType, ItemType item_type, typename ConnectivityPtr> void ConnectivityDispatcher<Dimension>::_gatherFrom(const ItemValue<DataType, item_type, ConnectivityPtr>& data_to_gather, - std::vector<std::remove_const_t<DataType>>& gathered_vector) + Array<std::remove_const_t<DataType>>& gathered_array) { std::vector<Array<const DataType>> recv_item_data_by_proc = this->exchange(data_to_gather); const auto& recv_id_correspondance_by_proc = this->_dispatchedInfo<item_type>().m_recv_id_correspondance_by_proc; Assert(recv_id_correspondance_by_proc.size() == parallel::size()); - gathered_vector.resize(this->_dispatchedInfo<item_type>().m_number_to_id_map.size()); + gathered_array = Array<std::remove_const_t<DataType>>(this->_dispatchedInfo<item_type>().m_number_to_id_map.size()); for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) { Assert(recv_id_correspondance_by_proc[i_rank].size() == recv_item_data_by_proc[i_rank].size()); for (size_t r = 0; r < recv_id_correspondance_by_proc[i_rank].size(); ++r) { - const auto& item_id = recv_id_correspondance_by_proc[i_rank][r]; - gathered_vector[item_id] = recv_item_data_by_proc[i_rank][r]; + const auto& item_id = recv_id_correspondance_by_proc[i_rank][r]; + gathered_array[item_id] = recv_item_data_by_proc[i_rank][r]; } } } @@ -167,7 +167,7 @@ template <typename DataType, typename ItemOfItem, typename ConnectivityPtr> void ConnectivityDispatcher<Dimension>::_gatherFrom( const SubItemValuePerItem<DataType, ItemOfItem, ConnectivityPtr>& data_to_gather, - std::vector<Array<std::remove_const_t<DataType>>>& gathered_vector) + Array<std::remove_const_t<DataType>>& gathered_array) { using MutableDataType = std::remove_const_t<DataType>; @@ -201,17 +201,23 @@ ConnectivityDispatcher<Dimension>::_gatherFrom( parallel::exchange(data_to_send_by_proc, recv_data_to_gather_by_proc); - const auto& item_list_to_recv_size_by_proc = this->_dispatchedInfo<item_type>().m_list_to_recv_size_by_proc; + const size_t recv_array_size = [&] { + size_t size = 0; + for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) { + size += recv_data_to_gather_by_proc[i_rank].size(); + } + return size; + }(); - for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) { - int l = 0; - for (size_t i = 0; i < item_list_to_recv_size_by_proc[i_rank]; ++i) { - Array<MutableDataType> data_vector(number_of_sub_item_per_item_to_recv_by_proc[i_rank][i]); - for (size_t k = 0; k < data_vector.size(); ++k) { - data_vector[k] = recv_data_to_gather_by_proc[i_rank][l++]; + gathered_array = Array<std::remove_const_t<DataType>>(recv_array_size); + { + size_t l = 0; + for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) { + for (size_t j = 0; j < recv_data_to_gather_by_proc[i_rank].size(); ++j) { + gathered_array[l++] = recv_data_to_gather_by_proc[i_rank][j]; } - gathered_vector.emplace_back(data_vector); } + Assert(gathered_array.size() == l); } } @@ -342,6 +348,8 @@ ConnectivityDispatcher<Dimension>::_buildItemToSubItemDescriptor() const auto& recv_item_of_item_numbers_by_proc = this->_dispatchedInfo<ItemOfItemT>().m_sub_item_numbers_to_recv_by_proc; + std::vector<std::vector<unsigned int>> item_to_subitem_legacy; + size_t number_of_node_by_cell = 0; for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) { int l = 0; for (size_t i = 0; i < item_list_to_recv_size_by_proc[i_rank]; ++i) { @@ -351,9 +359,30 @@ ConnectivityDispatcher<Dimension>::_buildItemToSubItemDescriptor() Assert(searched_sub_item_id != sub_item_number_id_map.end()); sub_item_vector.push_back(searched_sub_item_id->second); } - m_new_descriptor.itemOfItemVector<ItemOfItemT>().emplace_back(sub_item_vector); + number_of_node_by_cell += sub_item_vector.size(); + + item_to_subitem_legacy.emplace_back(sub_item_vector); + } + } + Array<unsigned int> item_to_subitem_row_map(item_to_subitem_legacy.size() + 1); + Array<unsigned int> item_to_subitem_list(number_of_node_by_cell); + + item_to_subitem_row_map.fill(10000000); + item_to_subitem_list.fill(10000000); + + item_to_subitem_row_map[0] = 0; + for (size_t i = 0; i < item_to_subitem_legacy.size(); ++i) { + item_to_subitem_row_map[i + 1] = item_to_subitem_row_map[i] + item_to_subitem_legacy[i].size(); + } + size_t l = 0; + for (size_t i = 0; i < item_to_subitem_legacy.size(); ++i) { + const auto& subitem_list = item_to_subitem_legacy[i]; + for (size_t j = 0; j < subitem_list.size(); ++j, ++l) { + item_to_subitem_list[l] = subitem_list[j]; } } + + m_new_descriptor.itemOfItemVector<ItemOfItemT>() = ConnectivityMatrix(item_to_subitem_row_map, item_to_subitem_list); } template <int Dimension> @@ -582,7 +611,11 @@ ConnectivityDispatcher<Dimension>::_dispatchEdges() this->_buildSubItemNumberToIdMap<EdgeOfCell>(); this->_buildItemToExchangeLists<ItemType::edge>(); - this->_gatherFrom(m_connectivity.template number<ItemType::edge>(), m_new_descriptor.edge_number_vector); + m_new_descriptor.setEdgeNumberVector([&] { + Array<int> edge_number_vector; + this->_gatherFrom(m_connectivity.template number<ItemType::edge>(), edge_number_vector); + return edge_number_vector; + }()); this->_buildItemToSubItemDescriptor<EdgeOfCell>(); @@ -594,9 +627,17 @@ ConnectivityDispatcher<Dimension>::_dispatchEdges() this->_buildSubItemNumbersToRecvByProc<EdgeOfFace>(); this->_buildItemToSubItemDescriptor<EdgeOfFace>(); - this->_gatherFrom(m_connectivity.faceEdgeIsReversed(), m_new_descriptor.face_edge_is_reversed_vector); + m_new_descriptor.setFaceEdgeIsReversed([&] { + Array<bool> face_edge_is_reversed; + this->_gatherFrom(m_connectivity.faceEdgeIsReversed(), face_edge_is_reversed); + return face_edge_is_reversed; + }()); - this->_gatherFrom(this->_dispatchedInfo<ItemType::edge>().m_new_owner, m_new_descriptor.edge_owner_vector); + m_new_descriptor.setEdgeOwnerVector([&] { + Array<int> edge_owner_vector; + this->_gatherFrom(this->_dispatchedInfo<ItemType::edge>().m_new_owner, edge_owner_vector); + return edge_owner_vector; + }()); this->_buildItemReferenceList<ItemType::edge>(); } @@ -616,13 +657,25 @@ ConnectivityDispatcher<Dimension>::_dispatchFaces() this->_buildSubItemNumbersToRecvByProc<NodeOfFace>(); this->_buildItemToSubItemDescriptor<NodeOfFace>(); - this->_gatherFrom(m_connectivity.template number<ItemType::face>(), m_new_descriptor.face_number_vector); + m_new_descriptor.setFaceNumberVector([&] { + Array<int> face_number_vector; + this->_gatherFrom(m_connectivity.template number<ItemType::face>(), face_number_vector); + return face_number_vector; + }()); this->_buildItemToSubItemDescriptor<FaceOfCell>(); - this->_gatherFrom(m_connectivity.cellFaceIsReversed(), m_new_descriptor.cell_face_is_reversed_vector); + m_new_descriptor.setCellFaceIsReversed([&] { + Array<bool> cell_face_is_reversed; + this->_gatherFrom(m_connectivity.cellFaceIsReversed(), cell_face_is_reversed); + return cell_face_is_reversed; + }()); - this->_gatherFrom(this->_dispatchedInfo<ItemType::face>().m_new_owner, m_new_descriptor.face_owner_vector); + m_new_descriptor.setFaceOwnerVector([&] { + Array<int> face_owner_vector; + this->_gatherFrom(this->_dispatchedInfo<ItemType::face>().m_new_owner, face_owner_vector); + return face_owner_vector; + }()); this->_buildItemReferenceList<ItemType::face>(); } @@ -647,18 +700,39 @@ ConnectivityDispatcher<Dimension>::ConnectivityDispatcher(const ConnectivityType this->_buildSubItemNumbersToRecvByProc<NodeOfCell>(); - this->_gatherFrom(m_connectivity.template number<ItemType::cell>(), m_new_descriptor.cell_number_vector); + m_new_descriptor.setCellNumberVector([&] { + Array<int> cell_number_vector; + this->_gatherFrom(m_connectivity.template number<ItemType::cell>(), cell_number_vector); + return cell_number_vector; + }()); this->_buildSubItemNumberToIdMap<NodeOfCell>(); this->_buildItemToExchangeLists<ItemType::node>(); - // Fill new descriptor - this->_gatherFrom(m_connectivity.cellType(), m_new_descriptor.cell_type_vector); - this->_gatherFrom(this->_dispatchedInfo<ItemType::cell>().m_new_owner, m_new_descriptor.cell_owner_vector); - - this->_gatherFrom(m_connectivity.template number<ItemType::node>(), m_new_descriptor.node_number_vector); - this->_gatherFrom(this->_dispatchedInfo<ItemType::node>().m_new_owner, m_new_descriptor.node_owner_vector); + m_new_descriptor.setCellTypeVector([&] { + Array<CellType> cell_type_vector; + this->_gatherFrom(m_connectivity.cellType(), cell_type_vector); + return cell_type_vector; + }()); + + m_new_descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector; + this->_gatherFrom(this->_dispatchedInfo<ItemType::cell>().m_new_owner, cell_owner_vector); + return cell_owner_vector; + }()); + + m_new_descriptor.setNodeNumberVector([&] { + Array<int> node_number_vector; + this->_gatherFrom(m_connectivity.template number<ItemType::node>(), node_number_vector); + return node_number_vector; + }()); + + m_new_descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector; + this->_gatherFrom(this->_dispatchedInfo<ItemType::node>().m_new_owner, node_owner_vector); + return node_owner_vector; + }()); this->_buildItemToSubItemDescriptor<NodeOfCell>(); diff --git a/src/mesh/ConnectivityDispatcher.hpp b/src/mesh/ConnectivityDispatcher.hpp index 73ebc548d98a01e4999611927272206df4af1c23..9ff5913b60799148f99bb6fdf4cff2cedd56973c 100644 --- a/src/mesh/ConnectivityDispatcher.hpp +++ b/src/mesh/ConnectivityDispatcher.hpp @@ -180,11 +180,11 @@ class ConnectivityDispatcher template <typename DataType, ItemType item_type, typename ConnectivityPtr> void _gatherFrom(const ItemValue<DataType, item_type, ConnectivityPtr>& data_to_gather, - std::vector<std::remove_const_t<DataType>>& gathered_vector); + Array<std::remove_const_t<DataType>>& gathered_array); template <typename DataType, typename ItemOfItem, typename ConnectivityPtr> void _gatherFrom(const SubItemValuePerItem<DataType, ItemOfItem, ConnectivityPtr>& data_to_gather, - std::vector<Array<std::remove_const_t<DataType>>>& gathered_vector); + Array<std::remove_const_t<DataType>>& gathered_array); template <typename SubItemOfItemT> void _buildNumberOfSubItemPerItemToRecvByProc(); diff --git a/src/mesh/ConnectivityMatrix.hpp b/src/mesh/ConnectivityMatrix.hpp index 6b777288cd6b8e3793a9addff6629c661d45d82d..eadc85347cb756932616e655d7b625a2a15505b7 100644 --- a/src/mesh/ConnectivityMatrix.hpp +++ b/src/mesh/ConnectivityMatrix.hpp @@ -70,34 +70,22 @@ class ConnectivityMatrix #endif // NDEBUG } - PUGS_INLINE - ConnectivityMatrix(const std::vector<std::vector<unsigned int>>& initializer) noexcept : m_is_built{true} - { - m_row_map = [&] { - Array<uint32_t> row_map(initializer.size() + 1); - row_map[0] = 0; - for (size_t i = 0; i < initializer.size(); ++i) { - row_map[i + 1] = row_map[i] + initializer[i].size(); - } - return row_map; - }(); - - m_column_indices = [&] { - Array<uint32_t> column_indices(m_row_map[m_row_map.size() - 1]); - size_t index = 0; - for (const auto& row : initializer) { - for (const auto& col_index : row) { - column_indices[index++] = col_index; - } - } - return column_indices; - }(); - } - ConnectivityMatrix& operator=(const ConnectivityMatrix&) = default; - ConnectivityMatrix& operator=(ConnectivityMatrix&&) = default; + ConnectivityMatrix& operator=(ConnectivityMatrix&&) = default; - ConnectivityMatrix() = default; + ConnectivityMatrix(bool is_built = false) : m_is_built{is_built} + { + // this is useful to build + if (is_built) { + m_row_map = [&] { + Array<uint32_t> row_map(1); + row_map[0] = 0; + return row_map; + }(); + + m_column_indices = Array<uint32_t>(0); + } + } ConnectivityMatrix(const ConnectivityMatrix&) = default; ConnectivityMatrix(ConnectivityMatrix&&) = default; ~ConnectivityMatrix() = default; diff --git a/src/mesh/ConnectivityUtils.cpp b/src/mesh/ConnectivityUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af0220ac448b76fb2e0101c278719cc07da989bc --- /dev/null +++ b/src/mesh/ConnectivityUtils.cpp @@ -0,0 +1,88 @@ +#include <mesh/ConnectivityUtils.hpp> + +#include <mesh/Connectivity.hpp> +#include <utils/Messenger.hpp> + +template <size_t Dimension, ItemType SourceItemType, ItemType TargetItemType> +bool +checkItemToHigherDimensionItem(const Connectivity<Dimension>& connectivity) +{ + static_assert(SourceItemType < TargetItemType); + bool is_valid = true; + + const auto& item_to_item_matrix = connectivity.template getItemToItemMatrix<SourceItemType, TargetItemType>(); + const auto& item_number = connectivity.template number<TargetItemType>(); + + for (ItemIdT<SourceItemType> source_item_id = 0; source_item_id < connectivity.template numberOf<SourceItemType>(); + ++source_item_id) { + auto target_item_list = item_to_item_matrix[source_item_id]; + for (size_t i = 0; i < target_item_list.size() - 1; ++i) { + is_valid &= (item_number[target_item_list[i + 1]] > item_number[target_item_list[i]]); + } + } + + return is_valid; +} + +template <size_t Dimension> +bool checkConnectivityOrdering(const Connectivity<Dimension>&); + +template <> +bool +checkConnectivityOrdering(const Connectivity<1>& connectivity) +{ + bool is_valid = true; + is_valid &= checkItemToHigherDimensionItem<1, ItemType::node, ItemType::cell>(connectivity); + + return is_valid; +} +template <> + +bool +checkConnectivityOrdering(const Connectivity<2>& connectivity) +{ + bool is_valid = true; + is_valid &= checkItemToHigherDimensionItem<2, ItemType::node, ItemType::face>(connectivity); + is_valid &= checkItemToHigherDimensionItem<2, ItemType::node, ItemType::cell>(connectivity); + + is_valid &= checkItemToHigherDimensionItem<2, ItemType::face, ItemType::cell>(connectivity); + + return is_valid; +} + +bool +checkConnectivityOrdering(const Connectivity<3>& connectivity) +{ + bool is_valid = true; + is_valid &= checkItemToHigherDimensionItem<3, ItemType::node, ItemType::edge>(connectivity); + is_valid &= checkItemToHigherDimensionItem<3, ItemType::node, ItemType::face>(connectivity); + is_valid &= checkItemToHigherDimensionItem<3, ItemType::node, ItemType::cell>(connectivity); + + is_valid &= checkItemToHigherDimensionItem<3, ItemType::edge, ItemType::face>(connectivity); + is_valid &= checkItemToHigherDimensionItem<3, ItemType::edge, ItemType::cell>(connectivity); + + is_valid &= checkItemToHigherDimensionItem<3, ItemType::face, ItemType::cell>(connectivity); + + return parallel::allReduceAnd(is_valid); +} + +bool +checkConnectivityOrdering(const IConnectivity& connecticity) +{ + switch (connecticity.dimension()) { + case 1: { + return checkConnectivityOrdering(dynamic_cast<const Connectivity<1>&>(connecticity)); + } + case 2: { + return checkConnectivityOrdering(dynamic_cast<const Connectivity<2>&>(connecticity)); + } + case 3: { + return checkConnectivityOrdering(dynamic_cast<const Connectivity<3>&>(connecticity)); + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("invalid dimension"); + } + // LCOV_EXCL_STOP + } +} diff --git a/src/mesh/ConnectivityUtils.hpp b/src/mesh/ConnectivityUtils.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fa359a7e1c532e3b83c91d3e42d1bd8e3d7a45d8 --- /dev/null +++ b/src/mesh/ConnectivityUtils.hpp @@ -0,0 +1,8 @@ +#ifndef CONNECTIVITY_UTILS_HPP +#define CONNECTIVITY_UTILS_HPP + +#include "mesh/IConnectivity.hpp" + +bool checkConnectivityOrdering(const IConnectivity&); + +#endif // CONNECTIVITY_UTILS_HPP diff --git a/src/mesh/DiamondDualConnectivityBuilder.cpp b/src/mesh/DiamondDualConnectivityBuilder.cpp index 71e316461d94a0891b721a0fff85e85c145ef26f..c6a8fd78a9774dc63cbc5e5398ce721c5cfb9acb 100644 --- a/src/mesh/DiamondDualConnectivityBuilder.cpp +++ b/src/mesh/DiamondDualConnectivityBuilder.cpp @@ -11,6 +11,7 @@ #include <utils/Messenger.hpp> #include <utils/Stringify.hpp> +#include <optional> #include <vector> template <size_t Dimension> @@ -44,21 +45,21 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityDescriptor(const Connec } } - diamond_descriptor.node_number_vector.resize(diamond_number_of_nodes); + Array<int> node_number_vector(diamond_number_of_nodes); parallel_for(m_primal_node_to_dual_node_map.size(), [&](size_t i) { const auto [primal_node_id, diamond_dual_node_id] = m_primal_node_to_dual_node_map[i]; - diamond_descriptor.node_number_vector[diamond_dual_node_id] = primal_node_number[primal_node_id]; + node_number_vector[diamond_dual_node_id] = primal_node_number[primal_node_id]; }); const size_t cell_number_shift = max(primal_node_number) + 1; parallel_for(primal_number_of_cells, [&](size_t i) { const auto [primal_cell_id, diamond_dual_node_id] = m_primal_cell_to_dual_node_map[i]; - diamond_descriptor.node_number_vector[diamond_dual_node_id] = - primal_cell_number[primal_cell_id] + cell_number_shift; + node_number_vector[diamond_dual_node_id] = primal_cell_number[primal_cell_id] + cell_number_shift; }); + diamond_descriptor.setNodeNumberVector(node_number_vector); { m_primal_face_to_dual_cell_map = FaceIdToCellIdMap{primal_number_of_faces}; @@ -68,14 +69,17 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityDescriptor(const Connec } } - diamond_descriptor.cell_number_vector.resize(diamond_number_of_cells); - const auto& primal_face_number = primal_connectivity.faceNumber(); - parallel_for(diamond_number_of_cells, [&](size_t i) { - const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i]; - diamond_descriptor.cell_number_vector[dual_cell_id] = primal_face_number[primal_face_id]; - }); + diamond_descriptor.setCellNumberVector([&] { + Array<int> cell_number_vector(diamond_number_of_cells); + const auto& primal_face_number = primal_connectivity.faceNumber(); + parallel_for(diamond_number_of_cells, [&](size_t i) { + const auto [primal_face_id, dual_cell_id] = m_primal_face_to_dual_cell_map[i]; + cell_number_vector[dual_cell_id] = primal_face_number[primal_face_id]; + }); + return cell_number_vector; + }()); - diamond_descriptor.cell_type_vector.resize(diamond_number_of_cells); + Array<CellType> cell_type_vector(diamond_number_of_cells); const auto& primal_face_to_cell_matrix = primal_connectivity.faceToCellMatrix(); const auto& primal_face_to_node_matrix = primal_connectivity.faceToNodeMatrix(); @@ -87,97 +91,108 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityDescriptor(const Connec if constexpr (Dimension == 2) { if (primal_face_cell_list.size() == 1) { - diamond_descriptor.cell_type_vector[i_cell] = CellType::Triangle; + cell_type_vector[i_cell] = CellType::Triangle; } else { Assert(primal_face_cell_list.size() == 2); - diamond_descriptor.cell_type_vector[i_cell] = CellType::Quadrangle; + cell_type_vector[i_cell] = CellType::Quadrangle; } } else if constexpr (Dimension == 3) { if (primal_face_cell_list.size() == 1) { if (primal_face_to_node_matrix[face_id].size() == 3) { - diamond_descriptor.cell_type_vector[i_cell] = CellType::Tetrahedron; + cell_type_vector[i_cell] = CellType::Tetrahedron; } else { - diamond_descriptor.cell_type_vector[i_cell] = CellType::Pyramid; + cell_type_vector[i_cell] = CellType::Pyramid; } } else { Assert(primal_face_cell_list.size() == 2); - diamond_descriptor.cell_type_vector[i_cell] = CellType::Diamond; + cell_type_vector[i_cell] = CellType::Diamond; } } }); - diamond_descriptor.cell_to_node_vector.resize(diamond_number_of_cells); + diamond_descriptor.setCellTypeVector(cell_type_vector); - const auto& primal_face_local_number_in_their_cells = primal_connectivity.faceLocalNumbersInTheirCells(); - const auto& cell_face_is_reversed = primal_connectivity.cellFaceIsReversed(); - parallel_for(primal_number_of_faces, [&](FaceId face_id) { - const size_t& i_diamond_cell = face_id; - const auto& primal_face_cell_list = primal_face_to_cell_matrix[face_id]; - const auto& primal_face_node_list = primal_face_to_node_matrix[face_id]; - if (primal_face_cell_list.size() == 1) { - diamond_descriptor.cell_to_node_vector[i_diamond_cell].resize(primal_face_node_list.size() + 1); - - const CellId cell_id = primal_face_cell_list[0]; - const auto i_face_in_cell = primal_face_local_number_in_their_cells(face_id, 0); + Array<const unsigned int> cell_to_node_row = [&] { + Array<unsigned int> tmp_cell_to_node_row(primal_number_of_faces + 1); + tmp_cell_to_node_row[0] = 0; + for (FaceId face_id = 0; face_id < primal_number_of_faces; ++face_id) { + tmp_cell_to_node_row[face_id + 1] = tmp_cell_to_node_row[face_id] + primal_face_to_node_matrix[face_id].size() + + primal_face_to_cell_matrix[face_id].size(); + } - for (size_t i_node = 0; i_node < primal_face_node_list.size(); ++i_node) { - diamond_descriptor.cell_to_node_vector[i_diamond_cell][i_node] = primal_face_node_list[i_node]; - } - diamond_descriptor.cell_to_node_vector[i_diamond_cell][primal_face_node_list.size()] = - primal_number_of_nodes + cell_id; + return tmp_cell_to_node_row; + }(); + + Array<const unsigned int> cell_to_node_list = [&] { + Array<unsigned int> tmp_cell_to_node_list(cell_to_node_row[cell_to_node_row.size() - 1]); + const auto& primal_face_local_number_in_their_cells = primal_connectivity.faceLocalNumbersInTheirCells(); + const auto& cell_face_is_reversed = primal_connectivity.cellFaceIsReversed(); + parallel_for(primal_number_of_faces, [&](FaceId face_id) { + const auto& primal_face_cell_list = primal_face_to_cell_matrix[face_id]; + const auto& primal_face_node_list = primal_face_to_node_matrix[face_id]; + const size_t first_node = cell_to_node_row[face_id]; + if (primal_face_cell_list.size() == 1) { + const CellId cell_id = primal_face_cell_list[0]; + const auto i_face_in_cell = primal_face_local_number_in_their_cells(face_id, 0); - if constexpr (Dimension == 2) { - if (cell_face_is_reversed(cell_id, i_face_in_cell)) { - std::swap(diamond_descriptor.cell_to_node_vector[i_diamond_cell][0], - diamond_descriptor.cell_to_node_vector[i_diamond_cell][1]); + for (size_t i_node = 0; i_node < primal_face_node_list.size(); ++i_node) { + tmp_cell_to_node_list[first_node + i_node] = primal_face_node_list[i_node]; } - } else { - if (not cell_face_is_reversed(cell_id, i_face_in_cell)) { - // In 3D the basis of the pyramid is described in the - // indirect way IF the face is not reversed. In other words - // the "topological normal" must point to the "top" of the - // pyramid. - for (size_t i_node = 0; i_node < primal_face_node_list.size() / 2; ++i_node) { - std::swap(diamond_descriptor.cell_to_node_vector[i_diamond_cell][i_node], - diamond_descriptor - .cell_to_node_vector[i_diamond_cell][primal_face_node_list.size() - 1 - i_node]); + tmp_cell_to_node_list[first_node + primal_face_node_list.size()] = primal_number_of_nodes + cell_id; + + if constexpr (Dimension == 2) { + if (cell_face_is_reversed(cell_id, i_face_in_cell)) { + std::swap(tmp_cell_to_node_list[first_node], tmp_cell_to_node_list[first_node + 1]); + } + } else { + if (not cell_face_is_reversed(cell_id, i_face_in_cell)) { + // In 3D the basis of the pyramid is described in the + // indirect way IF the face is not reversed. In other words + // the "topological normal" must point to the "top" of the + // pyramid. + for (size_t i_node = 0; i_node < primal_face_node_list.size() / 2; ++i_node) { + std::swap(tmp_cell_to_node_list[first_node + i_node], + tmp_cell_to_node_list[first_node + primal_face_node_list.size() - 1 - i_node]); + } } - } - } - } else { - Assert(primal_face_cell_list.size() == 2); - diamond_descriptor.cell_to_node_vector[i_diamond_cell].resize(primal_face_node_list.size() + 2); - - const CellId cell0_id = primal_face_cell_list[0]; - const CellId cell1_id = primal_face_cell_list[1]; - const auto i_face_in_cell0 = primal_face_local_number_in_their_cells(face_id, 0); - - if constexpr (Dimension == 2) { - Assert(primal_face_node_list.size() == 2); - diamond_descriptor.cell_to_node_vector[i_diamond_cell][0] = primal_number_of_nodes + cell0_id; - diamond_descriptor.cell_to_node_vector[i_diamond_cell][1] = primal_face_node_list[0]; - diamond_descriptor.cell_to_node_vector[i_diamond_cell][2] = primal_number_of_nodes + cell1_id; - diamond_descriptor.cell_to_node_vector[i_diamond_cell][3] = primal_face_node_list[1]; - - if (cell_face_is_reversed(cell0_id, i_face_in_cell0)) { - std::swap(diamond_descriptor.cell_to_node_vector[i_diamond_cell][1], - diamond_descriptor.cell_to_node_vector[i_diamond_cell][3]); } } else { - diamond_descriptor.cell_to_node_vector[i_diamond_cell][0] = primal_number_of_nodes + cell0_id; - for (size_t i_node = 0; i_node < primal_face_node_list.size(); ++i_node) { - diamond_descriptor.cell_to_node_vector[i_diamond_cell][i_node + 1] = primal_face_node_list[i_node]; - } - diamond_descriptor.cell_to_node_vector[i_diamond_cell][primal_face_node_list.size() + 1] = - primal_number_of_nodes + cell1_id; + Assert(primal_face_cell_list.size() == 2); - if (cell_face_is_reversed(cell0_id, i_face_in_cell0)) { - std::swap(diamond_descriptor.cell_to_node_vector[i_diamond_cell][0], - diamond_descriptor.cell_to_node_vector[i_diamond_cell][primal_face_node_list.size() + 1]); + const CellId cell0_id = primal_face_cell_list[0]; + const CellId cell1_id = primal_face_cell_list[1]; + const auto i_face_in_cell0 = primal_face_local_number_in_their_cells(face_id, 0); + + if constexpr (Dimension == 2) { + Assert(primal_face_node_list.size() == 2); + + tmp_cell_to_node_list[first_node + 0] = primal_number_of_nodes + cell0_id; + tmp_cell_to_node_list[first_node + 1] = primal_face_node_list[0]; + tmp_cell_to_node_list[first_node + 2] = primal_number_of_nodes + cell1_id; + tmp_cell_to_node_list[first_node + 3] = primal_face_node_list[1]; + + if (cell_face_is_reversed(cell0_id, i_face_in_cell0)) { + std::swap(tmp_cell_to_node_list[first_node + 1], tmp_cell_to_node_list[first_node + 3]); + } + } else { + tmp_cell_to_node_list[first_node + 0] = primal_number_of_nodes + cell0_id; + for (size_t i_node = 0; i_node < primal_face_node_list.size(); ++i_node) { + tmp_cell_to_node_list[first_node + i_node + 1] = primal_face_node_list[i_node]; + } + tmp_cell_to_node_list[first_node + primal_face_node_list.size() + 1] = primal_number_of_nodes + cell1_id; + + if (cell_face_is_reversed(cell0_id, i_face_in_cell0)) { + std::swap(tmp_cell_to_node_list[first_node], + tmp_cell_to_node_list[first_node + primal_face_node_list.size() + 1]); + } } } - } - }); + }); + + return tmp_cell_to_node_list; + }(); + + diamond_descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list)); } template <size_t Dimension> @@ -198,11 +213,12 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities<Dimension>(diamond_descriptor); } + const auto& node_number_vector = diamond_descriptor.nodeNumberVector(); { const std::unordered_map<unsigned int, NodeId> node_to_id_map = [&] { std::unordered_map<unsigned int, NodeId> node_to_id_map; - for (size_t i_node = 0; i_node < diamond_descriptor.node_number_vector.size(); ++i_node) { - node_to_id_map[diamond_descriptor.node_number_vector[i_node]] = i_node; + for (size_t i_node = 0; i_node < node_number_vector.size(); ++i_node) { + node_to_id_map[node_number_vector[i_node]] = i_node; } return node_to_id_map; }(); @@ -238,20 +254,32 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit } { - const auto& primal_face_to_node_matrix = primal_connectivity.faceToNodeMatrix(); - - using Face = ConnectivityFace<Dimension>; - - const std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map = [&] { - std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map; - for (FaceId l = 0; l < diamond_descriptor.face_to_node_vector.size(); ++l) { - const auto& node_vector = diamond_descriptor.face_to_node_vector[l]; - - face_to_id_map[Face(node_vector, diamond_descriptor.node_number_vector)] = l; + const auto& primal_face_to_node_matrix = primal_connectivity.faceToNodeMatrix(); + const auto& diamond_node_to_face_matrix = diamond_descriptor.nodeToFaceMatrix(); + const auto& diamond_face_to_node_matrix = diamond_descriptor.faceToNodeMatrix(); + + const auto find_face = [&](std::vector<uint32_t> node_list) -> std::optional<FaceId> { + // The node list of already sorted correctly + const auto& face_id_vector = diamond_node_to_face_matrix[node_list[0]]; + + for (size_t i_face = 0; i_face < face_id_vector.size(); ++i_face) { + const FaceId face_id = face_id_vector[i_face]; + const auto& face_node_id_list = diamond_face_to_node_matrix[face_id]; + if (face_node_id_list.size() == node_list.size()) { + bool is_same = true; + for (size_t i_node = 1; i_node < face_node_id_list.size(); ++i_node) { + is_same &= (face_node_id_list[i_node] == node_list[i_node]); + } + if (is_same) { + return face_id; + } + } } - return face_to_id_map; - }(); + return std::nullopt; + }; + + std::vector<unsigned int> face_node_list; for (size_t i_face_list = 0; i_face_list < primal_connectivity.template numberOfRefItemList<ItemType::face>(); ++i_face_list) { const auto& primal_ref_face_list = primal_connectivity.template refItemList<ItemType::face>(i_face_list); @@ -265,16 +293,15 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit const auto& primal_face_node_list = primal_face_to_node_matrix[primal_face_id]; - const auto i_diamond_face = [&]() { - std::vector<unsigned int> node_list(primal_face_node_list.size()); - for (size_t i = 0; i < primal_face_node_list.size(); ++i) { - node_list[i] = primal_face_node_list[i]; - } - return face_to_id_map.find(Face(node_list, diamond_descriptor.node_number_vector)); - }(); + face_node_list.clear(); + + for (size_t i = 0; i < primal_face_node_list.size(); ++i) { + face_node_list.push_back(primal_face_node_list[i]); + } - if (i_diamond_face != face_to_id_map.end()) { - diamond_face_list.push_back(i_diamond_face->second); + auto face_id = find_face(face_node_list); + if (face_id.has_value()) { + diamond_face_list.push_back(face_id.value()); } } return diamond_face_list; @@ -293,29 +320,40 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit if constexpr (Dimension == 3) { const auto& primal_edge_to_node_matrix = primal_connectivity.edgeToNodeMatrix(); - using Edge = ConnectivityFace<2>; - - const std::unordered_map<Edge, EdgeId, typename Edge::Hash> edge_to_id_map = [&] { - std::unordered_map<Edge, EdgeId, typename Edge::Hash> edge_to_id_map; - for (EdgeId l = 0; l < diamond_descriptor.edge_to_node_vector.size(); ++l) { - const auto& node_vector = diamond_descriptor.edge_to_node_vector[l]; - edge_to_id_map[Edge(node_vector, diamond_descriptor.node_number_vector)] = l; - } - return edge_to_id_map; - }(); { - const size_t number_of_edges = diamond_descriptor.edge_to_node_vector.size(); - diamond_descriptor.edge_number_vector.resize(number_of_edges); - for (size_t i_edge = 0; i_edge < number_of_edges; ++i_edge) { - diamond_descriptor.edge_number_vector[i_edge] = i_edge; - } + const size_t number_of_edges = diamond_descriptor.edgeToNodeMatrix().numberOfRows(); + diamond_descriptor.setEdgeNumberVector([&] { + Array<int> edge_number_vector(number_of_edges); + parallel_for( + number_of_edges, PUGS_LAMBDA(size_t i_edge) { edge_number_vector[i_edge] = i_edge; }); + return edge_number_vector; + }()); + // LCOV_EXCL_START if (parallel::size() > 1) { throw NotImplementedError("parallel edge numbering is undefined"); } // LCOV_EXCL_STOP } + const auto& diamond_node_to_edge_matrix = diamond_descriptor.nodeToEdgeMatrix(); + const auto& diamond_edge_to_node_matrix = diamond_descriptor.edgeToNodeMatrix(); + + const auto find_edge = [&](uint32_t node0, uint32_t node1) -> std::optional<EdgeId> { + if (node_number_vector[node0] > node_number_vector[node1]) { + std::swap(node0, node1); + } + const auto& edge_id_vector = diamond_node_to_edge_matrix[node0]; + + for (size_t i_edge = 0; i_edge < edge_id_vector.size(); ++i_edge) { + const EdgeId edge_id = edge_id_vector[i_edge]; + if (diamond_edge_to_node_matrix[edge_id][1] == node1) { + return edge_id; + } + } + + return std::nullopt; + }; for (size_t i_edge_list = 0; i_edge_list < primal_connectivity.template numberOfRefItemList<ItemType::edge>(); ++i_edge_list) { @@ -330,16 +368,10 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit const auto& primal_edge_node_list = primal_edge_to_node_matrix[primal_edge_id]; - const auto i_diamond_edge = [&]() { - std::vector<unsigned int> node_list(primal_edge_node_list.size()); - for (size_t i = 0; i < primal_edge_node_list.size(); ++i) { - node_list[i] = primal_edge_node_list[i]; - } - return edge_to_id_map.find(Edge(node_list, diamond_descriptor.node_number_vector)); - }(); + const auto diamond_edge_id = find_edge(primal_edge_node_list[0], primal_edge_node_list[1]); - if (i_diamond_edge != edge_to_id_map.end()) { - diamond_edge_list.push_back(i_diamond_edge->second); + if (diamond_edge_id.has_value()) { + diamond_edge_list.push_back(diamond_edge_id.value()); } } return diamond_edge_list; @@ -359,62 +391,64 @@ DiamondDualConnectivityBuilder::_buildDiamondConnectivityFrom(const IConnectivit const size_t primal_number_of_nodes = primal_connectivity.numberOfNodes(); const size_t primal_number_of_cells = primal_connectivity.numberOfCells(); - diamond_descriptor.node_owner_vector.resize(diamond_descriptor.node_number_vector.size()); - - { + diamond_descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector(node_number_vector.size()); const auto& primal_node_owner = primal_connectivity.nodeOwner(); for (NodeId primal_node_id = 0; primal_node_id < primal_connectivity.numberOfNodes(); ++primal_node_id) { - diamond_descriptor.node_owner_vector[primal_node_id] = primal_node_owner[primal_node_id]; + node_owner_vector[primal_node_id] = primal_node_owner[primal_node_id]; } const auto& primal_cell_owner = primal_connectivity.cellOwner(); for (CellId primal_cell_id = 0; primal_cell_id < primal_number_of_cells; ++primal_cell_id) { - diamond_descriptor.node_owner_vector[primal_number_of_nodes + primal_cell_id] = primal_cell_owner[primal_cell_id]; + node_owner_vector[primal_number_of_nodes + primal_cell_id] = primal_cell_owner[primal_cell_id]; } - } + return node_owner_vector; + }()); - { - diamond_descriptor.cell_owner_vector.resize(diamond_descriptor.cell_number_vector.size()); + diamond_descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector(diamond_descriptor.cellNumberVector().size()); const size_t primal_number_of_faces = primal_connectivity.numberOfFaces(); const auto& primal_face_owner = primal_connectivity.faceOwner(); - for (FaceId primal_face_id = 0; primal_face_id < primal_number_of_faces; ++primal_face_id) { - diamond_descriptor.cell_owner_vector[primal_face_id] = primal_face_owner[primal_face_id]; - } - } - - { - std::vector<int> face_cell_owner(diamond_descriptor.face_number_vector.size()); - std::fill(std::begin(face_cell_owner), std::end(face_cell_owner), parallel::size()); - - for (size_t i_cell = 0; i_cell < diamond_descriptor.cell_to_face_vector.size(); ++i_cell) { - const auto& cell_face_list = diamond_descriptor.cell_to_face_vector[i_cell]; + parallel_for( + primal_number_of_faces, PUGS_LAMBDA(const FaceId primal_face_id) { + cell_owner_vector[primal_face_id] = primal_face_owner[primal_face_id]; + }); + return cell_owner_vector; + }()); + + const auto& diamond_cell_owner_vector = diamond_descriptor.cellOwnerVector(); + const auto& diamond_cell_to_face_matrix = diamond_descriptor.cellToFaceMatrix(); + + diamond_descriptor.setFaceOwnerVector([&] { + Array<int> face_owner_vector(diamond_descriptor.faceNumberVector().size()); + face_owner_vector.fill(parallel::rank()); + + for (size_t i_cell = 0; i_cell < diamond_cell_to_face_matrix.numberOfRows(); ++i_cell) { + const auto& cell_face_list = diamond_cell_to_face_matrix[i_cell]; for (size_t i_face = 0; i_face < cell_face_list.size(); ++i_face) { - const size_t face_id = cell_face_list[i_face]; - face_cell_owner[face_id] = std::min(face_cell_owner[face_id], diamond_descriptor.cell_number_vector[i_cell]); + const size_t face_id = cell_face_list[i_face]; + face_owner_vector[face_id] = std::min(face_owner_vector[face_id], diamond_cell_owner_vector[i_cell]); } } - - diamond_descriptor.face_owner_vector.resize(face_cell_owner.size()); - for (size_t i_face = 0; i_face < face_cell_owner.size(); ++i_face) { - diamond_descriptor.face_owner_vector[i_face] = diamond_descriptor.cell_owner_vector[face_cell_owner[i_face]]; - } - } + return face_owner_vector; + }()); if constexpr (Dimension == 3) { - std::vector<int> edge_cell_owner(diamond_descriptor.edge_number_vector.size()); - std::fill(std::begin(edge_cell_owner), std::end(edge_cell_owner), parallel::size()); - - for (size_t i_cell = 0; i_cell < diamond_descriptor.cell_to_face_vector.size(); ++i_cell) { - const auto& cell_edge_list = diamond_descriptor.cell_to_edge_vector[i_cell]; - for (size_t i_edge = 0; i_edge < cell_edge_list.size(); ++i_edge) { - const size_t edge_id = cell_edge_list[i_edge]; - edge_cell_owner[edge_id] = std::min(edge_cell_owner[edge_id], diamond_descriptor.cell_number_vector[i_cell]); + const auto& diamond_cell_to_edge_matrix = diamond_descriptor.cellToEdgeMatrix(); + + diamond_descriptor.setEdgeOwnerVector([&] { + Array<int> edge_owner_vector(diamond_descriptor.edgeNumberVector().size()); + edge_owner_vector.fill(parallel::rank()); + + for (size_t i_cell = 0; i_cell < diamond_cell_to_edge_matrix.numberOfRows(); ++i_cell) { + const auto& cell_edge_list = diamond_cell_to_edge_matrix[i_cell]; + for (size_t i_edge = 0; i_edge < cell_edge_list.size(); ++i_edge) { + const size_t edge_id = cell_edge_list[i_edge]; + edge_owner_vector[edge_id] = std::min(edge_owner_vector[edge_id], diamond_cell_owner_vector[i_cell]); + } } - } - diamond_descriptor.edge_owner_vector.resize(edge_cell_owner.size()); - for (size_t i_edge = 0; i_edge < edge_cell_owner.size(); ++i_edge) { - diamond_descriptor.edge_owner_vector[i_edge] = diamond_descriptor.cell_owner_vector[edge_cell_owner[i_edge]]; - } + return edge_owner_vector; + }()); } m_connectivity = ConnectivityType::build(diamond_descriptor); diff --git a/src/mesh/DiamondDualMeshBuilder.cpp b/src/mesh/DiamondDualMeshBuilder.cpp index 21e413ff4e94519b79fbc26e87d742e67c0436c2..64711edc72055effd9e5608bc01b71ea184ee1fc 100644 --- a/src/mesh/DiamondDualMeshBuilder.cpp +++ b/src/mesh/DiamondDualMeshBuilder.cpp @@ -43,8 +43,6 @@ DiamondDualMeshBuilder::_buildDualDiamondMeshFrom(const IMesh& i_mesh) DiamondDualMeshBuilder::DiamondDualMeshBuilder(const IMesh& i_mesh) { - std::cout << "building DiamondDualMesh\n"; - switch (i_mesh.dimension()) { case 2: { this->_buildDualDiamondMeshFrom<2>(i_mesh); diff --git a/src/mesh/Dual1DConnectivityBuilder.cpp b/src/mesh/Dual1DConnectivityBuilder.cpp index 30c465b8b07375fce9f82fb76a26ac24848f3c67..52f3ddc977adc531496bf02b10e2b3ef36dfa5f1 100644 --- a/src/mesh/Dual1DConnectivityBuilder.cpp +++ b/src/mesh/Dual1DConnectivityBuilder.cpp @@ -28,14 +28,14 @@ Dual1DConnectivityBuilder::_buildConnectivityDescriptor(const Connectivity<1>& p const auto& primal_node_to_cell_matrix = primal_connectivity.nodeToCellMatrix(); size_t next_kept_node_id = 0; - dual_descriptor.node_number_vector.resize(dual_number_of_nodes); + Array<int> node_number_vector(dual_number_of_nodes); const auto& primal_node_number = primal_connectivity.nodeNumber(); for (NodeId primal_node_id = 0; primal_node_id < primal_connectivity.numberOfNodes(); ++primal_node_id) { const auto& primal_node_cell_list = primal_node_to_cell_matrix[primal_node_id]; if (primal_node_cell_list.size() == 1) { - dual_descriptor.node_number_vector[next_kept_node_id++] = primal_node_number[primal_node_id]; + node_number_vector[next_kept_node_id++] = primal_node_number[primal_node_id]; } } @@ -46,43 +46,56 @@ Dual1DConnectivityBuilder::_buildConnectivityDescriptor(const Connectivity<1>& p const size_t cell_number_shift = max(primal_node_number) + 1; for (CellId primal_cell_id = 0; primal_cell_id < primal_number_of_cells; ++primal_cell_id) { - dual_descriptor.node_number_vector[primal_number_of_kept_nodes + primal_cell_id] = + node_number_vector[primal_number_of_kept_nodes + primal_cell_id] = primal_cell_number[primal_cell_id] + cell_number_shift; } + dual_descriptor.setNodeNumberVector(node_number_vector); Assert(number_of_kept_nodes == next_kept_node_id, "unexpected number of kept nodes"); - dual_descriptor.cell_number_vector.resize(dual_number_of_cells); - for (NodeId primal_node_id = 0; primal_node_id < primal_number_of_nodes; ++primal_node_id) { - dual_descriptor.cell_number_vector[primal_node_id] = primal_node_number[primal_node_id]; - } - - dual_descriptor.cell_type_vector = std::vector<CellType>(dual_number_of_cells, CellType::Line); + dual_descriptor.setCellNumberVector([&] { + Array<int> cell_number_vector(dual_number_of_cells); + parallel_for( + primal_number_of_nodes, PUGS_LAMBDA(const NodeId primal_node_id) { + cell_number_vector[primal_node_id] = primal_node_number[primal_node_id]; + }); + return cell_number_vector; + }()); - dual_descriptor.cell_to_node_vector.resize(dual_number_of_cells); + Array<CellType> cell_type_vector(dual_number_of_cells); + cell_type_vector.fill(CellType::Line); + dual_descriptor.setCellTypeVector(cell_type_vector); const auto& primal_node_local_number_in_their_cells = primal_connectivity.nodeLocalNumbersInTheirCells(); + Array<unsigned int> cell_to_node_row(dual_number_of_cells + 1); + parallel_for( + cell_to_node_row.size(), PUGS_LAMBDA(const CellId cell_id) { cell_to_node_row[cell_id] = 2 * cell_id; }); + + Array<unsigned int> cell_to_node_list(cell_to_node_row[cell_to_node_row.size() - 1]); { size_t next_kept_node_id = 0; + size_t i_cell_node = 0; for (NodeId i_node = 0; i_node < primal_connectivity.numberOfNodes(); ++i_node) { - const size_t& i_dual_cell = i_node; const auto& primal_node_cell_list = primal_node_to_cell_matrix[i_node]; - dual_descriptor.cell_to_node_vector[i_dual_cell].resize(2); if (primal_node_cell_list.size() == 1) { const auto i_node_in_cell = primal_node_local_number_in_their_cells(i_node, 0); - dual_descriptor.cell_to_node_vector[i_dual_cell][i_node_in_cell] = next_kept_node_id++; - dual_descriptor.cell_to_node_vector[i_dual_cell][1 - i_node_in_cell] = - number_of_kept_nodes + primal_node_cell_list[0]; + cell_to_node_list[i_cell_node + i_node_in_cell] = next_kept_node_id++; + cell_to_node_list[i_cell_node + 1 - i_node_in_cell] = number_of_kept_nodes + primal_node_cell_list[0]; + + i_cell_node += 2; + } else { const auto i0 = primal_node_local_number_in_their_cells(i_node, 0); - dual_descriptor.cell_to_node_vector[i_dual_cell][0] = number_of_kept_nodes + primal_node_cell_list[1 - i0]; - dual_descriptor.cell_to_node_vector[i_dual_cell][1] = number_of_kept_nodes + primal_node_cell_list[i0]; + cell_to_node_list[i_cell_node++] = number_of_kept_nodes + primal_node_cell_list[1 - i0]; + cell_to_node_list[i_cell_node++] = number_of_kept_nodes + primal_node_cell_list[i0]; } } } + + dual_descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list)); } void @@ -97,10 +110,12 @@ Dual1DConnectivityBuilder::_buildConnectivityFrom(const IConnectivity& i_primal_ this->_buildConnectivityDescriptor(primal_connectivity, dual_descriptor); { + const auto& dual_node_number_vector = dual_descriptor.nodeNumberVector(); + const std::unordered_map<unsigned int, NodeId> node_to_id_map = [&] { std::unordered_map<unsigned int, NodeId> node_to_id_map; - for (size_t i_node = 0; i_node < dual_descriptor.node_number_vector.size(); ++i_node) { - node_to_id_map[dual_descriptor.node_number_vector[i_node]] = i_node; + for (size_t i_node = 0; i_node < dual_node_number_vector.size(); ++i_node) { + node_to_id_map[dual_node_number_vector[i_node]] = i_node; } return node_to_id_map; }(); @@ -138,31 +153,33 @@ Dual1DConnectivityBuilder::_buildConnectivityFrom(const IConnectivity& i_primal_ const size_t primal_number_of_nodes = primal_connectivity.numberOfNodes(); const size_t primal_number_of_cells = primal_connectivity.numberOfCells(); - dual_descriptor.node_owner_vector.resize(dual_descriptor.node_number_vector.size()); - - { + dual_descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector(dual_descriptor.nodeNumberVector().size()); const auto& node_to_cell_matrix = primal_connectivity.nodeToCellMatrix(); const auto& primal_node_owner = primal_connectivity.nodeOwner(); size_t next_kept_node_id = 0; for (NodeId primal_node_id = 0; primal_node_id < primal_connectivity.numberOfNodes(); ++primal_node_id) { if (node_to_cell_matrix[primal_node_id].size() == 1) { - dual_descriptor.node_owner_vector[next_kept_node_id++] = primal_node_owner[primal_node_id]; + node_owner_vector[next_kept_node_id++] = primal_node_owner[primal_node_id]; } } const size_t number_of_kept_nodes = next_kept_node_id; const auto& primal_cell_owner = primal_connectivity.cellOwner(); for (CellId primal_cell_id = 0; primal_cell_id < primal_number_of_cells; ++primal_cell_id) { - dual_descriptor.node_owner_vector[number_of_kept_nodes + primal_cell_id] = primal_cell_owner[primal_cell_id]; + node_owner_vector[number_of_kept_nodes + primal_cell_id] = primal_cell_owner[primal_cell_id]; } - } - { - dual_descriptor.cell_owner_vector.resize(dual_descriptor.cell_number_vector.size()); + return node_owner_vector; + }()); + + dual_descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector(dual_descriptor.cellNumberVector().size()); const auto& primal_node_owner = primal_connectivity.nodeOwner(); - for (NodeId primal_node_id = 0; primal_node_id < primal_number_of_nodes; ++primal_node_id) { - dual_descriptor.cell_owner_vector[primal_node_id] = primal_node_owner[primal_node_id]; - } - } + parallel_for( + primal_number_of_nodes, + PUGS_LAMBDA(NodeId primal_node_id) { cell_owner_vector[primal_node_id] = primal_node_owner[primal_node_id]; }); + return cell_owner_vector; + }()); m_connectivity = ConnectivityType::build(dual_descriptor); diff --git a/src/mesh/GmshReader.cpp b/src/mesh/GmshReader.cpp index e555ca224c1d02f11e11696542774f2e470b6432..e4ae59ea7cbb6fa2ec3f622c0868ff79ff9f8bbf 100644 --- a/src/mesh/GmshReader.cpp +++ b/src/mesh/GmshReader.cpp @@ -35,19 +35,29 @@ GmshConnectivityBuilder<1>::GmshConnectivityBuilder(const GmshReader::GmshData& { ConnectivityDescriptor descriptor; - descriptor.node_number_vector = gmsh_data.__verticesNumbers; - descriptor.cell_type_vector.resize(nb_cells); - descriptor.cell_number_vector.resize(nb_cells); - descriptor.cell_to_node_vector.resize(nb_cells); + descriptor.setNodeNumberVector(convert_to_array(gmsh_data.__verticesNumbers)); + Array<CellType> cell_type_vector(nb_cells); + Array<int> cell_number_vector(nb_cells); - for (size_t j = 0; j < nb_cells; ++j) { - descriptor.cell_to_node_vector[j].resize(2); - for (int r = 0; r < 2; ++r) { - descriptor.cell_to_node_vector[j][r] = gmsh_data.__edges[j][r]; + Array<unsigned int> cell_to_node_row(nb_cells + 1); + parallel_for( + cell_to_node_row.size(), PUGS_LAMBDA(const CellId cell_id) { cell_to_node_row[cell_id] = 2 * cell_id; }); + + Array<unsigned int> cell_to_node_list(cell_to_node_row[cell_to_node_row.size() - 1]); + for (CellId cell_id = 0; cell_id < nb_cells; ++cell_id) { + for (int i_node = 0; i_node < 2; ++i_node) { + cell_to_node_list[2 * cell_id + i_node] = gmsh_data.__edges[cell_id][i_node]; } - descriptor.cell_type_vector[j] = CellType::Line; - descriptor.cell_number_vector[j] = gmsh_data.__edges_number[j]; } + descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list)); + + cell_type_vector.fill(CellType::Line); + descriptor.setCellTypeVector(cell_type_vector); + + for (size_t j = 0; j < nb_cells; ++j) { + cell_number_vector[j] = gmsh_data.__edges_number[j]; + } + descriptor.setCellNumberVector(cell_number_vector); std::map<unsigned int, std::vector<unsigned int>> ref_points_map; for (unsigned int r = 0; r < gmsh_data.__points.size(); ++r) { @@ -56,12 +66,14 @@ GmshConnectivityBuilder<1>::GmshConnectivityBuilder(const GmshReader::GmshData& ref_points_map[ref].push_back(point_number); } - Array<size_t> node_nb_cell(descriptor.node_number_vector.size()); + Array<size_t> node_nb_cell(descriptor.nodeNumberVector().size()); node_nb_cell.fill(0); + const auto& cell_to_node_matrix = descriptor.cellToNodeMatrix(); for (size_t j = 0; j < nb_cells; ++j) { + const auto& cell_node_list = cell_to_node_matrix[j]; for (int r = 0; r < 2; ++r) { - node_nb_cell[descriptor.cell_to_node_vector[j][r]] += 1; + node_nb_cell[cell_node_list[r]] += 1; } } @@ -116,12 +128,18 @@ GmshConnectivityBuilder<1>::GmshConnectivityBuilder(const GmshReader::GmshData& descriptor.addRefItemList(RefCellList(ref_id, cell_list, false)); } - descriptor.cell_owner_vector.resize(nb_cells); - std::fill(descriptor.cell_owner_vector.begin(), descriptor.cell_owner_vector.end(), parallel::rank()); - - descriptor.node_owner_vector.resize(descriptor.node_number_vector.size()); - std::fill(descriptor.node_owner_vector.begin(), descriptor.node_owner_vector.end(), parallel::rank()); - + descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector(nb_cells); + cell_owner_vector.fill(parallel::rank()); + return cell_owner_vector; + }()); + + descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector(descriptor.nodeNumberVector().size()); + node_owner_vector.fill(parallel::rank()); + return node_owner_vector; + }()); + ; m_connectivity = Connectivity1D::build(descriptor); } @@ -130,32 +148,56 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData& { ConnectivityDescriptor descriptor; - descriptor.node_number_vector = gmsh_data.__verticesNumbers; - descriptor.cell_type_vector.resize(nb_cells); - descriptor.cell_number_vector.resize(nb_cells); - descriptor.cell_to_node_vector.resize(nb_cells); + descriptor.setNodeNumberVector(convert_to_array(gmsh_data.__verticesNumbers)); + Array<CellType> cell_type_vector(nb_cells); + Array<int> cell_number_vector(nb_cells); - const size_t nb_triangles = gmsh_data.__triangles.size(); - for (size_t j = 0; j < nb_triangles; ++j) { - descriptor.cell_to_node_vector[j].resize(3); - for (int r = 0; r < 3; ++r) { - descriptor.cell_to_node_vector[j][r] = gmsh_data.__triangles[j][r]; + Array<unsigned int> cell_to_node_row(gmsh_data.__triangles.size() + gmsh_data.__quadrangles.size() + 1); + { + cell_to_node_row[0] = 0; + size_t i_cell = 0; + for (size_t i_triangle = 0; i_triangle < gmsh_data.__triangles.size(); ++i_triangle, ++i_cell) { + cell_to_node_row[i_cell + 1] = cell_to_node_row[i_cell] + 3; + } + for (size_t i_quadrangle = 0; i_quadrangle < gmsh_data.__quadrangles.size(); ++i_quadrangle, ++i_cell) { + cell_to_node_row[i_cell + 1] = cell_to_node_row[i_cell] + 4; } - descriptor.cell_type_vector[j] = CellType::Triangle; - descriptor.cell_number_vector[j] = gmsh_data.__triangles_number[j]; + } + + Array<unsigned int> cell_to_node_list(cell_to_node_row[cell_to_node_row.size() - 1]); + { + size_t i_cell_node = 0; + for (size_t i_triangle = 0; i_triangle < gmsh_data.__triangles.size(); ++i_triangle) { + cell_to_node_list[i_cell_node++] = gmsh_data.__triangles[i_triangle][0]; + cell_to_node_list[i_cell_node++] = gmsh_data.__triangles[i_triangle][1]; + cell_to_node_list[i_cell_node++] = gmsh_data.__triangles[i_triangle][2]; + } + for (size_t i_quadrangle = 0; i_quadrangle < gmsh_data.__quadrangles.size(); ++i_quadrangle) { + cell_to_node_list[i_cell_node++] = gmsh_data.__quadrangles[i_quadrangle][0]; + cell_to_node_list[i_cell_node++] = gmsh_data.__quadrangles[i_quadrangle][1]; + cell_to_node_list[i_cell_node++] = gmsh_data.__quadrangles[i_quadrangle][2]; + cell_to_node_list[i_cell_node++] = gmsh_data.__quadrangles[i_quadrangle][3]; + } + } + descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list)); + + const size_t nb_triangles = gmsh_data.__triangles.size(); + for (size_t i_triangle = 0; i_triangle < nb_triangles; ++i_triangle) { + cell_type_vector[i_triangle] = CellType::Triangle; + cell_number_vector[i_triangle] = gmsh_data.__triangles_number[i_triangle]; } const size_t nb_quadrangles = gmsh_data.__quadrangles.size(); - for (size_t j = 0; j < nb_quadrangles; ++j) { - const size_t jq = j + nb_triangles; - descriptor.cell_to_node_vector[jq].resize(4); - for (int r = 0; r < 4; ++r) { - descriptor.cell_to_node_vector[jq][r] = gmsh_data.__quadrangles[j][r]; - } - descriptor.cell_type_vector[jq] = CellType::Quadrangle; - descriptor.cell_number_vector[jq] = gmsh_data.__quadrangles_number[j]; + for (size_t i_quadrangle = 0; i_quadrangle < nb_quadrangles; ++i_quadrangle) { + const size_t i_cell = i_quadrangle + nb_triangles; + + cell_type_vector[i_cell] = CellType::Quadrangle; + cell_number_vector[i_cell] = gmsh_data.__quadrangles_number[i_quadrangle]; } + descriptor.setCellNumberVector(cell_number_vector); + descriptor.setCellTypeVector(cell_type_vector); + std::map<unsigned int, std::vector<unsigned int>> ref_cells_map; for (unsigned int j = 0; j < gmsh_data.__triangles_ref.size(); ++j) { const unsigned int elem_number = j; @@ -189,64 +231,73 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData& ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities<2>(descriptor); - using Face = ConnectivityFace<2>; - const auto& node_number_vector = descriptor.node_number_vector; - const std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map = [&] { - std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map; - for (FaceId l = 0; l < descriptor.face_to_node_vector.size(); ++l) { - const auto& node_vector = descriptor.face_to_node_vector[l]; - face_to_id_map[Face(node_vector, node_number_vector)] = l; - } - return face_to_id_map; - }(); - std::unordered_map<int, FaceId> face_number_id_map = [&] { + const auto& face_number_vector = descriptor.faceNumberVector(); std::unordered_map<int, FaceId> face_number_id_map; - for (size_t l = 0; l < descriptor.face_number_vector.size(); ++l) { - face_number_id_map[descriptor.face_number_vector[l]] = l; + for (size_t l = 0; l < face_number_vector.size(); ++l) { + face_number_id_map[face_number_vector[l]] = l; } - Assert(face_number_id_map.size() == descriptor.face_number_vector.size()); + Assert(face_number_id_map.size() == face_number_vector.size()); return face_number_id_map; }(); + const auto& node_number_vector = descriptor.nodeNumberVector(); + const auto& node_to_face_matrix = descriptor.nodeToFaceMatrix(); + const auto& face_to_node_matrix = descriptor.faceToNodeMatrix(); + + const auto find_face = [&](uint32_t node0, uint32_t node1) { + if (node_number_vector[node0] > node_number_vector[node1]) { + std::swap(node0, node1); + } + const auto& face_id_vector = node_to_face_matrix[node0]; + + for (size_t i_face = 0; i_face < face_id_vector.size(); ++i_face) { + const FaceId face_id = face_id_vector[i_face]; + if (face_to_node_matrix[face_id][1] == node1) { + return face_id; + } + } + + std::stringstream error_msg; + error_msg << "face (" << node0 << ',' << node1 << ") not found"; + throw NormalError(error_msg.str()); + }; + + Array<int> face_number_vector = copy(descriptor.faceNumberVector()); std::map<unsigned int, std::vector<unsigned int>> ref_faces_map; for (unsigned int e = 0; e < gmsh_data.__edges.size(); ++e) { - const unsigned int edge_id = [&] { - auto i = face_to_id_map.find(Face({gmsh_data.__edges[e][0], gmsh_data.__edges[e][1]}, node_number_vector)); - if (i == face_to_id_map.end()) { - std::stringstream error_msg; - error_msg << "face " << gmsh_data.__edges[e][0] << " not found"; - throw NormalError(error_msg.str()); - } - return i->second; - }(); + const unsigned int edge_id = find_face(gmsh_data.__edges[e][0], gmsh_data.__edges[e][1]); + const unsigned int& ref = gmsh_data.__edges_ref[e]; ref_faces_map[ref].push_back(edge_id); - if (descriptor.face_number_vector[edge_id] != gmsh_data.__edges_number[e]) { + if (face_number_vector[edge_id] != gmsh_data.__edges_number[e]) { if (auto i_face = face_number_id_map.find(gmsh_data.__edges_number[e]); i_face != face_number_id_map.end()) { const int other_edge_id = i_face->second; - std::swap(descriptor.face_number_vector[edge_id], descriptor.face_number_vector[other_edge_id]); + std::swap(face_number_vector[edge_id], face_number_vector[other_edge_id]); - face_number_id_map.erase(descriptor.face_number_vector[edge_id]); - face_number_id_map.erase(descriptor.face_number_vector[other_edge_id]); + face_number_id_map.erase(face_number_vector[edge_id]); + face_number_id_map.erase(face_number_vector[other_edge_id]); - face_number_id_map[descriptor.face_number_vector[edge_id]] = edge_id; - face_number_id_map[descriptor.face_number_vector[other_edge_id]] = other_edge_id; + face_number_id_map[face_number_vector[edge_id]] = edge_id; + face_number_id_map[face_number_vector[other_edge_id]] = other_edge_id; } else { - face_number_id_map.erase(descriptor.face_number_vector[edge_id]); - descriptor.face_number_vector[edge_id] = gmsh_data.__edges_number[e]; - face_number_id_map[descriptor.face_number_vector[edge_id]] = edge_id; + face_number_id_map.erase(face_number_vector[edge_id]); + face_number_vector[edge_id] = gmsh_data.__edges_number[e]; + face_number_id_map[face_number_vector[edge_id]] = edge_id; } } } + descriptor.setFaceNumberVector(face_number_vector); - Array<size_t> face_nb_cell(descriptor.face_number_vector.size()); + Array<size_t> face_nb_cell(descriptor.faceNumberVector().size()); face_nb_cell.fill(0); - for (size_t j = 0; j < descriptor.cell_to_face_vector.size(); ++j) { - for (size_t l = 0; l < descriptor.cell_to_face_vector[j].size(); ++l) { - face_nb_cell[descriptor.cell_to_face_vector[j][l]] += 1; + const auto& cell_to_face_matrix = descriptor.cellToFaceMatrix(); + for (size_t j = 0; j < cell_to_face_matrix.numberOfRows(); ++j) { + const auto& cell_face_list = cell_to_face_matrix[j]; + for (size_t l = 0; l < cell_face_list.size(); ++l) { + face_nb_cell[cell_face_list[l]] += 1; } } @@ -276,13 +327,14 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData& descriptor.addRefItemList(RefFaceList{ref_id, face_list, is_boundary}); } - Array<bool> is_boundary_node(descriptor.node_number_vector.size()); + Array<bool> is_boundary_node(node_number_vector.size()); is_boundary_node.fill(false); for (size_t i_face = 0; i_face < face_nb_cell.size(); ++i_face) { if (face_nb_cell[i_face] == 1) { - for (size_t node_id : descriptor.face_to_node_vector[i_face]) { - is_boundary_node[node_id] = true; + const auto& face_node_list = face_to_node_matrix[i_face]; + for (size_t i_node = 0; i_node < face_node_list.size(); ++i_node) { + is_boundary_node[face_node_list[i_node]] = true; } } } @@ -319,14 +371,23 @@ GmshConnectivityBuilder<2>::GmshConnectivityBuilder(const GmshReader::GmshData& descriptor.addRefItemList(RefNodeList(ref_id, point_list, is_boundary)); } - descriptor.cell_owner_vector.resize(nb_cells); - std::fill(descriptor.cell_owner_vector.begin(), descriptor.cell_owner_vector.end(), parallel::rank()); + descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector(nb_cells); + cell_owner_vector.fill(parallel::rank()); + return cell_owner_vector; + }()); - descriptor.face_owner_vector.resize(descriptor.face_number_vector.size()); - std::fill(descriptor.face_owner_vector.begin(), descriptor.face_owner_vector.end(), parallel::rank()); + descriptor.setFaceOwnerVector([&] { + Array<int> face_owner_vector(descriptor.faceNumberVector().size()); + face_owner_vector.fill(parallel::rank()); + return face_owner_vector; + }()); - descriptor.node_owner_vector.resize(descriptor.node_number_vector.size()); - std::fill(descriptor.node_owner_vector.begin(), descriptor.node_owner_vector.end(), parallel::rank()); + descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector(node_number_vector.size()); + node_owner_vector.fill(parallel::rank()); + return node_owner_vector; + }()); m_connectivity = Connectivity2D::build(descriptor); } @@ -336,54 +397,99 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData& { ConnectivityDescriptor descriptor; - descriptor.node_number_vector = gmsh_data.__verticesNumbers; - descriptor.cell_type_vector.resize(nb_cells); - descriptor.cell_number_vector.resize(nb_cells); - descriptor.cell_to_node_vector.resize(nb_cells); + descriptor.setNodeNumberVector(convert_to_array(gmsh_data.__verticesNumbers)); + Array<CellType> cell_type_vector(nb_cells); + Array<int> cell_number_vector(nb_cells); const size_t nb_tetrahedra = gmsh_data.__tetrahedra.size(); - for (size_t j = 0; j < nb_tetrahedra; ++j) { - descriptor.cell_to_node_vector[j].resize(4); - for (int r = 0; r < 4; ++r) { - descriptor.cell_to_node_vector[j][r] = gmsh_data.__tetrahedra[j][r]; + const size_t nb_hexahedra = gmsh_data.__hexahedra.size(); + const size_t nb_prisms = gmsh_data.__prisms.size(); + const size_t nb_pyramids = gmsh_data.__pyramids.size(); + + Array<unsigned int> cell_to_node_row(nb_cells + 1); + { + cell_to_node_row[0] = 0; + size_t i_cell = 0; + for (size_t i_tetrahedron = 0; i_tetrahedron < nb_tetrahedra; ++i_tetrahedron, ++i_cell) { + cell_to_node_row[i_cell + 1] = cell_to_node_row[i_cell] + 4; + } + for (size_t i_hexahedron = 0; i_hexahedron < nb_hexahedra; ++i_hexahedron, ++i_cell) { + cell_to_node_row[i_cell + 1] = cell_to_node_row[i_cell] + 8; + } + for (size_t i_prism = 0; i_prism < nb_prisms; ++i_prism, ++i_cell) { + cell_to_node_row[i_cell + 1] = cell_to_node_row[i_cell] + 6; + } + for (size_t i_pyramid = 0; i_pyramid < nb_pyramids; ++i_pyramid, ++i_cell) { + cell_to_node_row[i_cell + 1] = cell_to_node_row[i_cell] + 5; + } + } + + Array<unsigned int> cell_to_node_list(cell_to_node_row[cell_to_node_row.size() - 1]); + { + size_t i_cell_node = 0; + for (size_t i_tetrahedron = 0; i_tetrahedron < nb_tetrahedra; ++i_tetrahedron) { + cell_to_node_list[i_cell_node++] = gmsh_data.__tetrahedra[i_tetrahedron][0]; + cell_to_node_list[i_cell_node++] = gmsh_data.__tetrahedra[i_tetrahedron][1]; + cell_to_node_list[i_cell_node++] = gmsh_data.__tetrahedra[i_tetrahedron][2]; + cell_to_node_list[i_cell_node++] = gmsh_data.__tetrahedra[i_tetrahedron][3]; + } + for (size_t i_hexahedron = 0; i_hexahedron < nb_hexahedra; ++i_hexahedron) { + cell_to_node_list[i_cell_node++] = gmsh_data.__hexahedra[i_hexahedron][0]; + cell_to_node_list[i_cell_node++] = gmsh_data.__hexahedra[i_hexahedron][1]; + cell_to_node_list[i_cell_node++] = gmsh_data.__hexahedra[i_hexahedron][2]; + cell_to_node_list[i_cell_node++] = gmsh_data.__hexahedra[i_hexahedron][3]; + cell_to_node_list[i_cell_node++] = gmsh_data.__hexahedra[i_hexahedron][4]; + cell_to_node_list[i_cell_node++] = gmsh_data.__hexahedra[i_hexahedron][5]; + cell_to_node_list[i_cell_node++] = gmsh_data.__hexahedra[i_hexahedron][6]; + cell_to_node_list[i_cell_node++] = gmsh_data.__hexahedra[i_hexahedron][7]; + } + for (size_t i_prism = 0; i_prism < nb_prisms; ++i_prism) { + cell_to_node_list[i_cell_node++] = gmsh_data.__prisms[i_prism][0]; + cell_to_node_list[i_cell_node++] = gmsh_data.__prisms[i_prism][1]; + cell_to_node_list[i_cell_node++] = gmsh_data.__prisms[i_prism][2]; + cell_to_node_list[i_cell_node++] = gmsh_data.__prisms[i_prism][3]; + cell_to_node_list[i_cell_node++] = gmsh_data.__prisms[i_prism][4]; + cell_to_node_list[i_cell_node++] = gmsh_data.__prisms[i_prism][5]; + } + for (size_t i_pyramid = 0; i_pyramid < nb_pyramids; ++i_pyramid) { + cell_to_node_list[i_cell_node++] = gmsh_data.__pyramids[i_pyramid][0]; + cell_to_node_list[i_cell_node++] = gmsh_data.__pyramids[i_pyramid][1]; + cell_to_node_list[i_cell_node++] = gmsh_data.__pyramids[i_pyramid][2]; + cell_to_node_list[i_cell_node++] = gmsh_data.__pyramids[i_pyramid][3]; + cell_to_node_list[i_cell_node++] = gmsh_data.__pyramids[i_pyramid][4]; } - descriptor.cell_type_vector[j] = CellType::Tetrahedron; - descriptor.cell_number_vector[j] = gmsh_data.__tetrahedra_number[j]; } - const size_t nb_hexahedra = gmsh_data.__hexahedra.size(); + for (size_t j = 0; j < nb_tetrahedra; ++j) { + cell_type_vector[j] = CellType::Tetrahedron; + cell_number_vector[j] = gmsh_data.__tetrahedra_number[j]; + } + for (size_t j = 0; j < nb_hexahedra; ++j) { const size_t jh = nb_tetrahedra + j; - descriptor.cell_to_node_vector[jh].resize(8); - for (int r = 0; r < 8; ++r) { - descriptor.cell_to_node_vector[jh][r] = gmsh_data.__hexahedra[j][r]; - } - descriptor.cell_type_vector[jh] = CellType::Hexahedron; - descriptor.cell_number_vector[jh] = gmsh_data.__hexahedra_number[j]; + + cell_type_vector[jh] = CellType::Hexahedron; + cell_number_vector[jh] = gmsh_data.__hexahedra_number[j]; } - const size_t nb_prisms = gmsh_data.__prisms.size(); for (size_t j = 0; j < nb_prisms; ++j) { const size_t jp = nb_tetrahedra + nb_hexahedra + j; - descriptor.cell_to_node_vector[jp].resize(6); - for (int r = 0; r < 6; ++r) { - descriptor.cell_to_node_vector[jp][r] = gmsh_data.__prisms[j][r]; - } - descriptor.cell_type_vector[jp] = CellType::Prism; - descriptor.cell_number_vector[jp] = gmsh_data.__prisms_number[j]; + + cell_type_vector[jp] = CellType::Prism; + cell_number_vector[jp] = gmsh_data.__prisms_number[j]; } - const size_t nb_pyramids = gmsh_data.__pyramids.size(); for (size_t j = 0; j < nb_pyramids; ++j) { const size_t jh = nb_tetrahedra + nb_hexahedra + nb_prisms + j; - descriptor.cell_to_node_vector[jh].resize(5); - for (int r = 0; r < 5; ++r) { - descriptor.cell_to_node_vector[jh][r] = gmsh_data.__pyramids[j][r]; - } - descriptor.cell_type_vector[jh] = CellType::Pyramid; - descriptor.cell_number_vector[jh] = gmsh_data.__pyramids_number[j]; + + cell_type_vector[jh] = CellType::Pyramid; + cell_number_vector[jh] = gmsh_data.__pyramids_number[j]; } + descriptor.setCellNumberVector(cell_number_vector); + descriptor.setCellTypeVector(cell_type_vector); + descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list)); + std::map<unsigned int, std::vector<unsigned int>> ref_cells_map; for (unsigned int j = 0; j < gmsh_data.__tetrahedra_ref.size(); ++j) { const unsigned int elem_number = j; @@ -429,103 +535,140 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData& ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities<3>(descriptor); - const auto& node_number_vector = descriptor.node_number_vector; + const auto& node_number_vector = descriptor.nodeNumberVector(); - Array<size_t> face_nb_cell(descriptor.face_number_vector.size()); + Array<size_t> face_nb_cell(descriptor.faceNumberVector().size()); face_nb_cell.fill(0); - for (size_t j = 0; j < descriptor.cell_to_face_vector.size(); ++j) { - for (size_t l = 0; l < descriptor.cell_to_face_vector[j].size(); ++l) { - face_nb_cell[descriptor.cell_to_face_vector[j][l]] += 1; + const auto& cell_to_face_matrix = descriptor.cellToFaceMatrix(); + + for (size_t j = 0; j < cell_to_face_matrix.numberOfRows(); ++j) { + const auto& cell_face_list = cell_to_face_matrix[j]; + for (size_t l = 0; l < cell_face_list.size(); ++l) { + face_nb_cell[cell_face_list[l]] += 1; } } + const auto& face_number_vector = descriptor.faceNumberVector(); { - using Face = ConnectivityFace<3>; - const std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map = [&] { - std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map; - for (FaceId l = 0; l < descriptor.face_to_node_vector.size(); ++l) { - const auto& node_vector = descriptor.face_to_node_vector[l]; - face_to_id_map[Face(node_vector, node_number_vector)] = l; - } - return face_to_id_map; - }(); - std::unordered_map<int, FaceId> face_number_id_map = [&] { std::unordered_map<int, FaceId> face_number_id_map; - for (size_t l = 0; l < descriptor.face_number_vector.size(); ++l) { - face_number_id_map[descriptor.face_number_vector[l]] = l; + for (size_t l = 0; l < face_number_vector.size(); ++l) { + face_number_id_map[face_number_vector[l]] = l; } - Assert(face_number_id_map.size() == descriptor.face_number_vector.size()); + Assert(face_number_id_map.size() == face_number_vector.size()); return face_number_id_map; }(); + const auto& node_to_face_matrix = descriptor.nodeToFaceMatrix(); + const auto& face_to_node_matrix = descriptor.faceToNodeMatrix(); + + const auto find_face = [&](std::vector<uint32_t> node_list) { + size_t i_node_smallest_number = 0; + for (size_t i_node = 1; i_node < node_list.size(); ++i_node) { + if (node_number_vector[node_list[i_node]] < node_number_vector[node_list[i_node_smallest_number]]) { + i_node_smallest_number = i_node; + } + } + + if (i_node_smallest_number != 0) { + std::vector<uint64_t> buffer(node_list.size()); + for (size_t i_node = i_node_smallest_number; i_node < buffer.size(); ++i_node) { + buffer[i_node - i_node_smallest_number] = node_list[i_node]; + } + for (size_t i_node = 0; i_node < i_node_smallest_number; ++i_node) { + buffer[i_node + node_list.size() - i_node_smallest_number] = node_list[i_node]; + } + + for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { + node_list[i_node] = buffer[i_node]; + } + } + + if (node_number_vector[node_list[1]] > node_number_vector[node_list[node_list.size() - 1]]) { + for (size_t i_node = 1; i_node <= (node_list.size() + 1) / 2 - 1; ++i_node) { + std::swap(node_list[i_node], node_list[node_list.size() - i_node]); + } + } + + const auto& face_id_vector = node_to_face_matrix[node_list[0]]; + + for (size_t i_face = 0; i_face < face_id_vector.size(); ++i_face) { + const FaceId face_id = face_id_vector[i_face]; + const auto& face_node_id_list = face_to_node_matrix[face_id]; + if (face_node_id_list.size() == node_list.size()) { + bool is_same = true; + for (size_t i_node = 1; i_node < face_node_id_list.size(); ++i_node) { + is_same &= (face_node_id_list[i_node] == node_list[i_node]); + } + if (is_same) { + return face_id; + } + } + } + + std::stringstream error_msg; + error_msg << "face (" << node_list[0]; + for (size_t i = 1; i < node_list.size(); ++i) { + error_msg << ',' << node_list[i]; + } + error_msg << ") not found"; + throw NormalError(error_msg.str()); + }; + + Array<int> face_number_vector = copy(descriptor.faceNumberVector()); std::map<unsigned int, std::vector<unsigned int>> ref_faces_map; for (unsigned int f = 0; f < gmsh_data.__triangles.size(); ++f) { - const unsigned int face_id = [&] { - auto i = face_to_id_map.find( - Face({gmsh_data.__triangles[f][0], gmsh_data.__triangles[f][1], gmsh_data.__triangles[f][2]}, - node_number_vector)); - if (i == face_to_id_map.end()) { - throw NormalError("face not found"); - } - return i->second; - }(); + const unsigned int face_id = + find_face({gmsh_data.__triangles[f][0], gmsh_data.__triangles[f][1], gmsh_data.__triangles[f][2]}); const unsigned int& ref = gmsh_data.__triangles_ref[f]; ref_faces_map[ref].push_back(face_id); - if (descriptor.face_number_vector[face_id] != gmsh_data.__triangles_number[f]) { + if (face_number_vector[face_id] != gmsh_data.__triangles_number[f]) { if (auto i_face = face_number_id_map.find(gmsh_data.__triangles_number[f]); i_face != face_number_id_map.end()) { const int other_face_id = i_face->second; - std::swap(descriptor.face_number_vector[face_id], descriptor.face_number_vector[other_face_id]); + std::swap(face_number_vector[face_id], face_number_vector[other_face_id]); - face_number_id_map.erase(descriptor.face_number_vector[face_id]); - face_number_id_map.erase(descriptor.face_number_vector[other_face_id]); + face_number_id_map.erase(face_number_vector[face_id]); + face_number_id_map.erase(face_number_vector[other_face_id]); - face_number_id_map[descriptor.face_number_vector[face_id]] = face_id; - face_number_id_map[descriptor.face_number_vector[other_face_id]] = other_face_id; + face_number_id_map[face_number_vector[face_id]] = face_id; + face_number_id_map[face_number_vector[other_face_id]] = other_face_id; } else { - face_number_id_map.erase(descriptor.face_number_vector[face_id]); - descriptor.face_number_vector[face_id] = gmsh_data.__triangles_number[f]; - face_number_id_map[descriptor.face_number_vector[face_id]] = face_id; + face_number_id_map.erase(face_number_vector[face_id]); + face_number_vector[face_id] = gmsh_data.__triangles_number[f]; + face_number_id_map[face_number_vector[face_id]] = face_id; } } } for (unsigned int f = 0; f < gmsh_data.__quadrangles.size(); ++f) { - const unsigned int face_id = [&] { - auto i = face_to_id_map.find(Face({gmsh_data.__quadrangles[f][0], gmsh_data.__quadrangles[f][1], - gmsh_data.__quadrangles[f][2], gmsh_data.__quadrangles[f][3]}, - node_number_vector)); - if (i == face_to_id_map.end()) { - throw NormalError("face not found"); - } - return i->second; - }(); + const unsigned int face_id = find_face({gmsh_data.__quadrangles[f][0], gmsh_data.__quadrangles[f][1], + gmsh_data.__quadrangles[f][2], gmsh_data.__quadrangles[f][3]}); const unsigned int& ref = gmsh_data.__quadrangles_ref[f]; ref_faces_map[ref].push_back(face_id); - - if (descriptor.face_number_vector[face_id] != gmsh_data.__quadrangles_number[f]) { + if (face_number_vector[face_id] != gmsh_data.__quadrangles_number[f]) { if (auto i_face = face_number_id_map.find(gmsh_data.__quadrangles_number[f]); i_face != face_number_id_map.end()) { const int other_face_id = i_face->second; - std::swap(descriptor.face_number_vector[face_id], descriptor.face_number_vector[other_face_id]); + std::swap(face_number_vector[face_id], face_number_vector[other_face_id]); - face_number_id_map.erase(descriptor.face_number_vector[face_id]); - face_number_id_map.erase(descriptor.face_number_vector[other_face_id]); + face_number_id_map.erase(face_number_vector[face_id]); + face_number_id_map.erase(face_number_vector[other_face_id]); - face_number_id_map[descriptor.face_number_vector[face_id]] = face_id; - face_number_id_map[descriptor.face_number_vector[other_face_id]] = other_face_id; + face_number_id_map[face_number_vector[face_id]] = face_id; + face_number_id_map[face_number_vector[other_face_id]] = other_face_id; } else { - face_number_id_map.erase(descriptor.face_number_vector[face_id]); - descriptor.face_number_vector[face_id] = gmsh_data.__quadrangles_number[f]; - face_number_id_map[descriptor.face_number_vector[face_id]] = face_id; + face_number_id_map.erase(face_number_vector[face_id]); + face_number_vector[face_id] = gmsh_data.__quadrangles_number[f]; + face_number_id_map[face_number_vector[face_id]] = face_id; } } } + descriptor.setFaceNumberVector(face_number_vector); for (const auto& ref_face_list : ref_faces_map) { Array<FaceId> face_list(ref_face_list.second.size()); @@ -556,68 +699,76 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData& ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities<3>(descriptor); { - Array<bool> is_boundary_edge(descriptor.edge_number_vector.size()); + Array<bool> is_boundary_edge(descriptor.edgeNumberVector().size()); is_boundary_edge.fill(false); + const auto& face_to_edge_matrix = descriptor.faceToEdgeMatrix(); + for (size_t i_face = 0; i_face < face_nb_cell.size(); ++i_face) { if (face_nb_cell[i_face] == 1) { - for (size_t node_id : descriptor.face_to_edge_vector[i_face]) { - is_boundary_edge[node_id] = true; + auto face_edge_list = face_to_edge_matrix[i_face]; + for (size_t i_edge = 0; i_edge < face_edge_list.size(); ++i_edge) { + is_boundary_edge[face_edge_list[i_edge]] = true; } } } - using Edge = ConnectivityFace<2>; - const auto& node_number_vector = descriptor.node_number_vector; - const std::unordered_map<Edge, EdgeId, typename Edge::Hash> edge_to_id_map = [&] { - std::unordered_map<Edge, EdgeId, typename Edge::Hash> edge_to_id_map; - for (EdgeId l = 0; l < descriptor.edge_to_node_vector.size(); ++l) { - const auto& node_vector = descriptor.edge_to_node_vector[l]; - edge_to_id_map[Edge(node_vector, node_number_vector)] = l; + const auto& node_to_edge_matrix = descriptor.nodeToEdgeMatrix(); + const auto& edge_to_node_matrix = descriptor.edgeToNodeMatrix(); + + const auto find_edge = [&](uint32_t node0, uint32_t node1) { + if (node_number_vector[node0] > node_number_vector[node1]) { + std::swap(node0, node1); } - return edge_to_id_map; - }(); + const auto& edge_id_vector = node_to_edge_matrix[node0]; + + for (size_t i_edge = 0; i_edge < edge_id_vector.size(); ++i_edge) { + const EdgeId edge_id = edge_id_vector[i_edge]; + if (edge_to_node_matrix[edge_id][1] == node1) { + return edge_id; + } + } + + std::stringstream error_msg; + error_msg << "edge (" << node0 << ',' << node1 << ") not found"; + throw NormalError(error_msg.str()); + }; std::unordered_map<int, EdgeId> edge_number_id_map = [&] { + const auto& edge_number_vector = descriptor.edgeNumberVector(); std::unordered_map<int, EdgeId> edge_number_id_map; - for (size_t l = 0; l < descriptor.edge_number_vector.size(); ++l) { - edge_number_id_map[descriptor.edge_number_vector[l]] = l; + for (size_t l = 0; l < edge_number_vector.size(); ++l) { + edge_number_id_map[edge_number_vector[l]] = l; } - Assert(edge_number_id_map.size() == descriptor.edge_number_vector.size()); + Assert(edge_number_id_map.size() == edge_number_vector.size()); return edge_number_id_map; }(); + Array<int> edge_number_vector = copy(descriptor.edgeNumberVector()); std::map<unsigned int, std::vector<unsigned int>> ref_edges_map; for (unsigned int e = 0; e < gmsh_data.__edges.size(); ++e) { - const unsigned int edge_id = [&] { - auto i = edge_to_id_map.find(Edge({gmsh_data.__edges[e][0], gmsh_data.__edges[e][1]}, node_number_vector)); - if (i == edge_to_id_map.end()) { - std::stringstream error_msg; - error_msg << "edge " << gmsh_data.__edges[e][0] << " not found"; - throw NormalError(error_msg.str()); - } - return i->second; - }(); - const unsigned int& ref = gmsh_data.__edges_ref[e]; + const unsigned int edge_id = find_edge(gmsh_data.__edges[e][0], gmsh_data.__edges[e][1]); + const unsigned int& ref = gmsh_data.__edges_ref[e]; ref_edges_map[ref].push_back(edge_id); - if (descriptor.edge_number_vector[edge_id] != gmsh_data.__edges_number[e]) { + if (edge_number_vector[edge_id] != gmsh_data.__edges_number[e]) { if (auto i_edge = edge_number_id_map.find(gmsh_data.__edges_number[e]); i_edge != edge_number_id_map.end()) { const int other_edge_id = i_edge->second; - std::swap(descriptor.edge_number_vector[edge_id], descriptor.edge_number_vector[other_edge_id]); + std::swap(edge_number_vector[edge_id], edge_number_vector[other_edge_id]); - edge_number_id_map.erase(descriptor.edge_number_vector[edge_id]); - edge_number_id_map.erase(descriptor.edge_number_vector[other_edge_id]); + edge_number_id_map.erase(edge_number_vector[edge_id]); + edge_number_id_map.erase(edge_number_vector[other_edge_id]); - edge_number_id_map[descriptor.edge_number_vector[edge_id]] = edge_id; - edge_number_id_map[descriptor.edge_number_vector[other_edge_id]] = other_edge_id; + edge_number_id_map[edge_number_vector[edge_id]] = edge_id; + edge_number_id_map[edge_number_vector[other_edge_id]] = other_edge_id; } else { - edge_number_id_map.erase(descriptor.edge_number_vector[edge_id]); - descriptor.edge_number_vector[edge_id] = gmsh_data.__edges_number[e]; - edge_number_id_map[descriptor.edge_number_vector[edge_id]] = edge_id; + edge_number_id_map.erase(edge_number_vector[edge_id]); + edge_number_vector[edge_id] = gmsh_data.__edges_number[e]; + edge_number_id_map[edge_number_vector[edge_id]] = edge_id; } } } + descriptor.setEdgeNumberVector(edge_number_vector); for (const auto& ref_edge_list : ref_edges_map) { Array<EdgeId> edge_list(ref_edge_list.second.size()); @@ -645,12 +796,16 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData& } } - Array<bool> is_boundary_node(descriptor.node_number_vector.size()); + Array<bool> is_boundary_node(node_number_vector.size()); is_boundary_node.fill(false); + const auto& face_to_node_matrix = descriptor.faceToNodeMatrix(); + for (size_t i_face = 0; i_face < face_nb_cell.size(); ++i_face) { if (face_nb_cell[i_face] == 1) { - for (size_t node_id : descriptor.face_to_node_vector[i_face]) { + const auto& face_node_list = face_to_node_matrix[i_face]; + for (size_t i_node = 0; i_node < face_node_list.size(); ++i_node) { + const NodeId node_id = face_node_list[i_node]; is_boundary_node[node_id] = true; } } @@ -688,17 +843,29 @@ GmshConnectivityBuilder<3>::GmshConnectivityBuilder(const GmshReader::GmshData& descriptor.addRefItemList(RefNodeList(ref_id, point_list, is_boundary)); } - descriptor.cell_owner_vector.resize(nb_cells); - std::fill(descriptor.cell_owner_vector.begin(), descriptor.cell_owner_vector.end(), parallel::rank()); - - descriptor.face_owner_vector.resize(descriptor.face_number_vector.size()); - std::fill(descriptor.face_owner_vector.begin(), descriptor.face_owner_vector.end(), parallel::rank()); - - descriptor.edge_owner_vector.resize(descriptor.edge_number_vector.size()); - std::fill(descriptor.edge_owner_vector.begin(), descriptor.edge_owner_vector.end(), parallel::rank()); - - descriptor.node_owner_vector.resize(descriptor.node_number_vector.size()); - std::fill(descriptor.node_owner_vector.begin(), descriptor.node_owner_vector.end(), parallel::rank()); + descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector(nb_cells); + cell_owner_vector.fill(parallel::rank()); + return cell_owner_vector; + }()); + + descriptor.setFaceOwnerVector([&] { + Array<int> face_owner_vector(descriptor.faceNumberVector().size()); + face_owner_vector.fill(parallel::rank()); + return face_owner_vector; + }()); + + descriptor.setEdgeOwnerVector([&] { + Array<int> edge_owner_vector(descriptor.edgeNumberVector().size()); + edge_owner_vector.fill(parallel::rank()); + return edge_owner_vector; + }()); + + descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector(node_number_vector.size()); + node_owner_vector.fill(parallel::rank()); + return node_owner_vector; + }()); m_connectivity = Connectivity3D::build(descriptor); } @@ -958,255 +1125,6 @@ GmshReader::__readPeriodic2_2() } } -// std::shared_ptr<IConnectivity> -// GmshReader::_buildConnectivity3D(const size_t nb_cells) -// { -// ConnectivityDescriptor descriptor; - -// descriptor.node_number_vector = m_mesh_data.__verticesNumbers; -// descriptor.cell_type_vector.resize(nb_cells); -// descriptor.cell_number_vector.resize(nb_cells); -// descriptor.cell_to_node_vector.resize(nb_cells); - -// const size_t nb_tetrahedra = m_mesh_data.__tetrahedra.size(); -// for (size_t j = 0; j < nb_tetrahedra; ++j) { -// descriptor.cell_to_node_vector[j].resize(4); -// for (int r = 0; r < 4; ++r) { -// descriptor.cell_to_node_vector[j][r] = m_mesh_data.__tetrahedra[j][r]; -// } -// descriptor.cell_type_vector[j] = CellType::Tetrahedron; -// descriptor.cell_number_vector[j] = m_mesh_data.__tetrahedra_number[j]; -// } -// const size_t nb_hexahedra = m_mesh_data.__hexahedra.size(); -// for (size_t j = 0; j < nb_hexahedra; ++j) { -// const size_t jh = nb_tetrahedra + j; -// descriptor.cell_to_node_vector[jh].resize(8); -// for (int r = 0; r < 8; ++r) { -// descriptor.cell_to_node_vector[jh][r] = m_mesh_data.__hexahedra[j][r]; -// } -// descriptor.cell_type_vector[jh] = CellType::Hexahedron; -// descriptor.cell_number_vector[jh] = m_mesh_data.__hexahedra_number[j]; -// } - -// std::map<unsigned int, std::vector<unsigned int>> ref_cells_map; -// for (unsigned int r = 0; r < m_mesh_data.__tetrahedra_ref.size(); ++r) { -// const unsigned int elem_number = m_mesh_data.__tetrahedra_ref[r]; -// const unsigned int& ref = m_mesh_data.__tetrahedra_ref[r]; -// ref_cells_map[ref].push_back(elem_number); -// } - -// for (unsigned int j = 0; j < m_mesh_data.__hexahedra_ref.size(); ++j) { -// const size_t elem_number = nb_tetrahedra + j; -// const unsigned int& ref = m_mesh_data.__hexahedra_ref[j]; -// ref_cells_map[ref].push_back(elem_number); -// } - -// for (const auto& ref_cell_list : ref_cells_map) { -// Array<CellId> cell_list(ref_cell_list.second.size()); -// for (size_t j = 0; j < ref_cell_list.second.size(); ++j) { -// cell_list[j] = ref_cell_list.second[j]; -// } -// const PhysicalRefId& physical_ref_id = m_mesh_data.m_physical_ref_map.at(ref_cell_list.first); -// descriptor.addRefItemList(RefCellList(physical_ref_id.refId(), cell_list)); -// } - -// ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities<3>(descriptor); - -// const auto& node_number_vector = descriptor.node_number_vector; - -// { -// using Face = ConnectivityFace<3>; -// const std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map = [&] { -// std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map; -// for (FaceId l = 0; l < descriptor.face_to_node_vector.size(); ++l) { -// const auto& node_vector = descriptor.face_to_node_vector[l]; -// face_to_id_map[Face(node_vector, node_number_vector)] = l; -// } -// return face_to_id_map; -// }(); - -// std::unordered_map<int, FaceId> face_number_id_map = [&] { -// std::unordered_map<int, FaceId> face_number_id_map; -// for (size_t l = 0; l < descriptor.face_number_vector.size(); ++l) { -// face_number_id_map[descriptor.face_number_vector[l]] = l; -// } -// Assert(face_number_id_map.size() == descriptor.face_number_vector.size()); -// return face_number_id_map; -// }(); - -// std::map<unsigned int, std::vector<unsigned int>> ref_faces_map; -// for (unsigned int f = 0; f < m_mesh_data.__triangles.size(); ++f) { -// const unsigned int face_id = [&] { -// auto i = face_to_id_map.find( -// Face({m_mesh_data.__triangles[f][0], m_mesh_data.__triangles[f][1], m_mesh_data.__triangles[f][2]}, -// node_number_vector)); -// if (i == face_to_id_map.end()) { -// throw NormalError("face not found"); -// } -// return i->second; -// }(); - -// const unsigned int& ref = m_mesh_data.__triangles_ref[f]; -// ref_faces_map[ref].push_back(face_id); - -// if (descriptor.face_number_vector[face_id] != m_mesh_data.__quadrangles_number[f]) { -// if (auto i_face = face_number_id_map.find(m_mesh_data.__quadrangles_number[f]); -// i_face != face_number_id_map.end()) { -// const int other_face_id = i_face->second; -// std::swap(descriptor.face_number_vector[face_id], descriptor.face_number_vector[other_face_id]); - -// face_number_id_map.erase(descriptor.face_number_vector[face_id]); -// face_number_id_map.erase(descriptor.face_number_vector[other_face_id]); - -// face_number_id_map[descriptor.face_number_vector[face_id]] = face_id; -// face_number_id_map[descriptor.face_number_vector[other_face_id]] = other_face_id; -// } else { -// face_number_id_map.erase(descriptor.face_number_vector[face_id]); -// descriptor.face_number_vector[face_id] = m_mesh_data.__quadrangles_number[f]; -// face_number_id_map[descriptor.face_number_vector[face_id]] = face_id; -// } -// } -// } - -// for (unsigned int f = 0; f < m_mesh_data.__quadrangles.size(); ++f) { -// const unsigned int face_id = [&] { -// auto i = face_to_id_map.find(Face({m_mesh_data.__quadrangles[f][0], m_mesh_data.__quadrangles[f][1], -// m_mesh_data.__quadrangles[f][2], m_mesh_data.__quadrangles[f][3]}, -// node_number_vector)); -// if (i == face_to_id_map.end()) { -// throw NormalError("face not found"); -// } -// return i->second; -// }(); - -// const unsigned int& ref = m_mesh_data.__quadrangles_ref[f]; -// ref_faces_map[ref].push_back(face_id); - -// if (descriptor.face_number_vector[face_id] != m_mesh_data.__quadrangles_number[f]) { -// if (auto i_face = face_number_id_map.find(m_mesh_data.__quadrangles_number[f]); -// i_face != face_number_id_map.end()) { -// const int other_face_id = i_face->second; -// std::swap(descriptor.face_number_vector[face_id], descriptor.face_number_vector[other_face_id]); - -// face_number_id_map.erase(descriptor.face_number_vector[face_id]); -// face_number_id_map.erase(descriptor.face_number_vector[other_face_id]); - -// face_number_id_map[descriptor.face_number_vector[face_id]] = face_id; -// face_number_id_map[descriptor.face_number_vector[other_face_id]] = other_face_id; -// } else { -// face_number_id_map.erase(descriptor.face_number_vector[face_id]); -// descriptor.face_number_vector[face_id] = m_mesh_data.__quadrangles_number[f]; -// face_number_id_map[descriptor.face_number_vector[face_id]] = face_id; -// } -// } -// } - -// for (const auto& ref_face_list : ref_faces_map) { -// Array<FaceId> face_list(ref_face_list.second.size()); -// for (size_t j = 0; j < ref_face_list.second.size(); ++j) { -// face_list[j] = ref_face_list.second[j]; -// } -// const PhysicalRefId& physical_ref_id = m_mesh_data.m_physical_ref_map.at(ref_face_list.first); -// descriptor.addRefItemList(RefFaceList{physical_ref_id.refId(), face_list}); -// } -// } - -// ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities<3>(descriptor); - -// { -// using Edge = ConnectivityFace<2>; -// const auto& node_number_vector = descriptor.node_number_vector; -// const std::unordered_map<Edge, EdgeId, typename Edge::Hash> edge_to_id_map = [&] { -// std::unordered_map<Edge, EdgeId, typename Edge::Hash> edge_to_id_map; -// for (EdgeId l = 0; l < descriptor.edge_to_node_vector.size(); ++l) { -// const auto& node_vector = descriptor.edge_to_node_vector[l]; -// edge_to_id_map[Edge(node_vector, node_number_vector)] = l; -// } -// return edge_to_id_map; -// }(); - -// std::unordered_map<int, EdgeId> edge_number_id_map = [&] { -// std::unordered_map<int, EdgeId> edge_number_id_map; -// for (size_t l = 0; l < descriptor.edge_number_vector.size(); ++l) { -// edge_number_id_map[descriptor.edge_number_vector[l]] = l; -// } -// Assert(edge_number_id_map.size() == descriptor.edge_number_vector.size()); -// return edge_number_id_map; -// }(); - -// std::map<unsigned int, std::vector<unsigned int>> ref_edges_map; -// for (unsigned int e = 0; e < m_mesh_data.__edges.size(); ++e) { -// const unsigned int edge_id = [&] { -// auto i = edge_to_id_map.find(Edge({m_mesh_data.__edges[e][0], m_mesh_data.__edges[e][1]}, -// node_number_vector)); if (i == edge_to_id_map.end()) { -// std::stringstream error_msg; -// error_msg << "edge " << m_mesh_data.__edges[e][0] << " not found"; -// throw NormalError(error_msg.str()); -// } -// return i->second; -// }(); -// const unsigned int& ref = m_mesh_data.__edges_ref[e]; -// ref_edges_map[ref].push_back(edge_id); - -// if (descriptor.edge_number_vector[edge_id] != m_mesh_data.__edges_number[e]) { -// if (auto i_edge = edge_number_id_map.find(m_mesh_data.__edges_number[e]); i_edge != edge_number_id_map.end()) -// { -// const int other_edge_id = i_edge->second; -// std::swap(descriptor.edge_number_vector[edge_id], descriptor.edge_number_vector[other_edge_id]); - -// edge_number_id_map.erase(descriptor.edge_number_vector[edge_id]); -// edge_number_id_map.erase(descriptor.edge_number_vector[other_edge_id]); - -// edge_number_id_map[descriptor.edge_number_vector[edge_id]] = edge_id; -// edge_number_id_map[descriptor.edge_number_vector[other_edge_id]] = other_edge_id; -// } else { -// edge_number_id_map.erase(descriptor.edge_number_vector[edge_id]); -// descriptor.edge_number_vector[edge_id] = m_mesh_data.__edges_number[e]; -// edge_number_id_map[descriptor.edge_number_vector[edge_id]] = edge_id; -// } -// } -// } - -// for (const auto& ref_edge_list : ref_edges_map) { -// Array<EdgeId> edge_list(ref_edge_list.second.size()); -// for (size_t j = 0; j < ref_edge_list.second.size(); ++j) { -// edge_list[j] = ref_edge_list.second[j]; -// } -// const PhysicalRefId& physical_ref_id = m_mesh_data.m_physical_ref_map.at(ref_edge_list.first); -// descriptor.addRefItemList(RefEdgeList{physical_ref_id.refId(), edge_list}); -// } -// } - -// std::map<unsigned int, std::vector<unsigned int>> ref_points_map; -// for (unsigned int r = 0; r < m_mesh_data.__points.size(); ++r) { -// const unsigned int point_number = m_mesh_data.__points[r]; -// const unsigned int& ref = m_mesh_data.__points_ref[r]; -// ref_points_map[ref].push_back(point_number); -// } - -// for (const auto& ref_point_list : ref_points_map) { -// Array<NodeId> point_list(ref_point_list.second.size()); -// for (size_t j = 0; j < ref_point_list.second.size(); ++j) { -// point_list[j] = ref_point_list.second[j]; -// } -// const PhysicalRefId& physical_ref_id = m_mesh_data.m_physical_ref_map.at(ref_point_list.first); -// descriptor.addRefItemList(RefNodeList(physical_ref_id.refId(), point_list)); -// } - -// descriptor.cell_owner_vector.resize(nb_cells); -// std::fill(descriptor.cell_owner_vector.begin(), descriptor.cell_owner_vector.end(), parallel::rank()); - -// descriptor.face_owner_vector.resize(descriptor.face_number_vector.size()); -// std::fill(descriptor.face_owner_vector.begin(), descriptor.face_owner_vector.end(), parallel::rank());// -// descriptor.edge_owner_vector.resize(descriptor.edge_number_vector.size()); -// std::fill(descriptor.edge_owner_vector.begin(), descriptor.edge_owner_vector.end(), parallel::rank()); - -// descriptor.node_owner_vector.resize(descriptor.node_number_vector.size()); -// std::fill(descriptor.node_owner_vector.begin(), descriptor.node_owner_vector.end(), parallel::rank()); - -// return Connectivity3D::build(descriptor); -// } - void GmshReader::__proceedData() { diff --git a/src/mesh/LogicalConnectivityBuilder.cpp b/src/mesh/LogicalConnectivityBuilder.cpp index 41092faaf90a9a3f9a24ac1c561304373ba748d0..dbc41d0681e9ceda822a5896af97ace2e3572f03 100644 --- a/src/mesh/LogicalConnectivityBuilder.cpp +++ b/src/mesh/LogicalConnectivityBuilder.cpp @@ -141,28 +141,27 @@ void LogicalConnectivityBuilder::_buildBoundaryEdgeList(const TinyVector<3, uint64_t>& cell_size, ConnectivityDescriptor& descriptor) { - using Edge = ConnectivityFace<2>; - const auto& node_number_vector = descriptor.node_number_vector; - const std::unordered_map<Edge, EdgeId, typename Edge::Hash> edge_to_id_map = [&] { - std::unordered_map<Edge, EdgeId, typename Edge::Hash> edge_to_id_map; - for (EdgeId l = 0; l < descriptor.edge_to_node_vector.size(); ++l) { - const auto& node_vector = descriptor.edge_to_node_vector[l]; - edge_to_id_map[Edge(node_vector, node_number_vector)] = l; + const auto& node_number_vector = descriptor.nodeNumberVector(); + const auto& node_to_edge_matrix = descriptor.nodeToEdgeMatrix(); + const auto& edge_to_node_matrix = descriptor.edgeToNodeMatrix(); + + const auto find_edge = [&](uint32_t node0, uint32_t node1) { + if (node_number_vector[node0] > node_number_vector[node1]) { + std::swap(node0, node1); } - return edge_to_id_map; - }(); + const auto& node_edge_list = node_to_edge_matrix[node0]; - std::unordered_map<int, EdgeId> edge_number_id_map = [&] { - std::unordered_map<int, EdgeId> edge_number_id_map; - for (size_t l = 0; l < descriptor.edge_number_vector.size(); ++l) { - edge_number_id_map[descriptor.edge_number_vector[l]] = l; + for (size_t i_edge = 0; i_edge < node_edge_list.size(); ++i_edge) { + const EdgeId edge_id = node_edge_list[i_edge]; + if (edge_to_node_matrix[edge_id][1] == node1) { + return edge_id; + } } - Assert(edge_number_id_map.size() == descriptor.edge_number_vector.size()); - return edge_number_id_map; - }(); + throw UnexpectedError("Cannot find edge"); + }; const TinyVector<3, uint64_t> node_size{cell_size[0] + 1, cell_size[1] + 1, cell_size[2] + 1}; - const auto node_number = [&](const TinyVector<3, uint64_t>& node_logic_id) { + const auto get_node_id = [&](const TinyVector<3, uint64_t>& node_logic_id) { return (node_logic_id[0] * node_size[1] + node_logic_id[1]) * node_size[2] + node_logic_id[2]; }; @@ -172,13 +171,10 @@ LogicalConnectivityBuilder::_buildBoundaryEdgeList(const TinyVector<3, uint64_t> Array<EdgeId> boundary_edges(cell_size[2]); size_t l = 0; for (size_t k = 0; k < cell_size[2]; ++k) { - const uint32_t node_0_id = node_number(TinyVector<3, uint64_t>{i, j, k}); - const uint32_t node_1_id = node_number(TinyVector<3, uint64_t>{i, j, k + 1}); - - auto i_edge = edge_to_id_map.find(Edge{{node_0_id, node_1_id}, descriptor.node_number_vector}); - Assert(i_edge != edge_to_id_map.end()); + const uint32_t node_0_id = get_node_id(TinyVector<3, uint64_t>{i, j, k}); + const uint32_t node_1_id = get_node_id(TinyVector<3, uint64_t>{i, j, k + 1}); - boundary_edges[l++] = i_edge->second; + boundary_edges[l++] = find_edge(node_0_id, node_1_id); } Assert(l == cell_size[2]); descriptor.addRefItemList(RefEdgeList{RefId{ref_id, ref_name}, boundary_edges, true}); @@ -196,13 +192,10 @@ LogicalConnectivityBuilder::_buildBoundaryEdgeList(const TinyVector<3, uint64_t> Array<EdgeId> boundary_edges(cell_size[1]); size_t l = 0; for (size_t j = 0; j < cell_size[1]; ++j) { - const uint32_t node_0_id = node_number(TinyVector<3, uint64_t>{i, j, k}); - const uint32_t node_1_id = node_number(TinyVector<3, uint64_t>{i, j + 1, k}); - - auto i_edge = edge_to_id_map.find(Edge{{node_0_id, node_1_id}, descriptor.node_number_vector}); - Assert(i_edge != edge_to_id_map.end()); + const uint32_t node_0_id = get_node_id(TinyVector<3, uint64_t>{i, j, k}); + const uint32_t node_1_id = get_node_id(TinyVector<3, uint64_t>{i, j + 1, k}); - boundary_edges[l++] = i_edge->second; + boundary_edges[l++] = find_edge(node_0_id, node_1_id); } Assert(l == cell_size[1]); descriptor.addRefItemList(RefEdgeList{RefId{ref_id, ref_name}, boundary_edges, true}); @@ -220,13 +213,10 @@ LogicalConnectivityBuilder::_buildBoundaryEdgeList(const TinyVector<3, uint64_t> Array<EdgeId> boundary_edges(cell_size[0]); size_t l = 0; for (size_t i = 0; i < cell_size[0]; ++i) { - const uint32_t node_0_id = node_number(TinyVector<3, uint64_t>{i, j, k}); - const uint32_t node_1_id = node_number(TinyVector<3, uint64_t>{i + 1, j, k}); + const uint32_t node_0_id = get_node_id(TinyVector<3, uint64_t>{i, j, k}); + const uint32_t node_1_id = get_node_id(TinyVector<3, uint64_t>{i + 1, j, k}); - auto i_edge = edge_to_id_map.find(Edge{{node_0_id, node_1_id}, descriptor.node_number_vector}); - Assert(i_edge != edge_to_id_map.end()); - - boundary_edges[l++] = i_edge->second; + boundary_edges[l++] = find_edge(node_0_id, node_1_id); } Assert(l == cell_size[0]); descriptor.addRefItemList(RefEdgeList{RefId{ref_id, ref_name}, boundary_edges, true}); @@ -256,6 +246,8 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList( return cell_logic_id[0] * cell_size[1] + cell_logic_id[1]; }; + const auto& cell_to_face_matrix = descriptor.cellToFaceMatrix(); + { // xmin const size_t i = 0; Array<FaceId> boundary_faces(cell_size[1]); @@ -263,7 +255,7 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList( constexpr size_t left_face = 3; const size_t cell_id = cell_number(TinyVector<2, uint64_t>{i, j}); - const size_t face_id = descriptor.cell_to_face_vector[cell_id][left_face]; + const size_t face_id = cell_to_face_matrix[cell_id][left_face]; boundary_faces[j] = face_id; } @@ -277,7 +269,7 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList( constexpr size_t right_face = 1; const size_t cell_id = cell_number(TinyVector<2, uint64_t>{i, j}); - const size_t face_id = descriptor.cell_to_face_vector[cell_id][right_face]; + const size_t face_id = cell_to_face_matrix[cell_id][right_face]; boundary_faces[j] = face_id; } @@ -291,7 +283,7 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList( constexpr size_t bottom_face = 0; const size_t cell_id = cell_number(TinyVector<2, uint64_t>{i, j}); - const size_t face_id = descriptor.cell_to_face_vector[cell_id][bottom_face]; + const size_t face_id = cell_to_face_matrix[cell_id][bottom_face]; boundary_faces[i] = face_id; } @@ -305,7 +297,7 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList( constexpr size_t top_face = 2; const size_t cell_id = cell_number(TinyVector<2, uint64_t>{i, j}); - const size_t face_id = descriptor.cell_to_face_vector[cell_id][top_face]; + const size_t face_id = cell_to_face_matrix[cell_id][top_face]; boundary_faces[i] = face_id; } @@ -318,28 +310,53 @@ void LogicalConnectivityBuilder::_buildBoundaryFaceList(const TinyVector<3, uint64_t>& cell_size, ConnectivityDescriptor& descriptor) { - using Face = ConnectivityFace<3>; + const auto& node_number_vector = descriptor.nodeNumberVector(); + const auto& face_to_node_matrix = descriptor.faceToNodeMatrix(); + const auto& node_to_face_matrix = descriptor.nodeToFaceMatrix(); + + const auto find_face = [&](std::array<uint32_t, 4> node_list) { + size_t i_node_smallest_number = 0; + for (size_t i_node = 1; i_node < node_list.size(); ++i_node) { + if (node_number_vector[node_list[i_node]] < node_number_vector[node_list[i_node_smallest_number]]) { + i_node_smallest_number = i_node; + } + } + + if (i_node_smallest_number != 0) { + std::array<uint64_t, 4> buffer; + for (size_t i_node = i_node_smallest_number; i_node < buffer.size(); ++i_node) { + buffer[i_node - i_node_smallest_number] = node_list[i_node]; + } + for (size_t i_node = 0; i_node < i_node_smallest_number; ++i_node) { + buffer[i_node + node_list.size() - i_node_smallest_number] = node_list[i_node]; + } - const std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map = [&] { - std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map; - for (FaceId l = 0; l < descriptor.face_to_node_vector.size(); ++l) { - const auto& node_vector = descriptor.face_to_node_vector[l]; - face_to_id_map[Face(node_vector, descriptor.node_number_vector)] = l; + for (size_t i_node = 0; i_node < node_list.size(); ++i_node) { + node_list[i_node] = buffer[i_node]; + } } - return face_to_id_map; - }(); - const std::unordered_map<int, FaceId> face_number_id_map = [&] { - std::unordered_map<int, FaceId> face_number_id_map; - for (size_t l = 0; l < descriptor.face_number_vector.size(); ++l) { - face_number_id_map[descriptor.face_number_vector[l]] = l; + if (node_number_vector[node_list[1]] > node_number_vector[node_list[node_list.size() - 1]]) { + for (size_t i_node = 1; i_node <= (node_list.size() + 1) / 2 - 1; ++i_node) { + std::swap(node_list[i_node], node_list[node_list.size() - i_node]); + } } - Assert(face_number_id_map.size() == descriptor.face_number_vector.size()); - return face_number_id_map; - }(); + + const auto& node_face_list = node_to_face_matrix[node_list[0]]; + + for (size_t i_face = 0; i_face < node_face_list.size(); ++i_face) { + const FaceId face_id = node_face_list[i_face]; + const auto& face_node_list = face_to_node_matrix[face_id]; + if ((face_node_list[1] == node_list[1]) and (face_node_list[2] == node_list[2]) and + (face_node_list[3] == node_list[3])) { + return face_id; + } + } + throw UnexpectedError("Cannot find edge"); + }; const TinyVector<3, uint64_t> node_size{cell_size[0] + 1, cell_size[1] + 1, cell_size[2] + 1}; - const auto node_number = [&](const TinyVector<3, uint64_t>& node_logic_id) { + const auto get_node_id = [&](const TinyVector<3, uint64_t>& node_logic_id) { return (node_logic_id[0] * node_size[1] + node_logic_id[1]) * node_size[2] + node_logic_id[2]; }; @@ -349,16 +366,12 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList(const TinyVector<3, uint64_t> size_t l = 0; for (size_t j = 0; j < cell_size[1]; ++j) { for (size_t k = 0; k < cell_size[2]; ++k) { - const uint32_t node_0_id = node_number(TinyVector<3, uint64_t>{i, j, k}); - const uint32_t node_1_id = node_number(TinyVector<3, uint64_t>{i, j + 1, k}); - const uint32_t node_2_id = node_number(TinyVector<3, uint64_t>{i, j + 1, k + 1}); - const uint32_t node_3_id = node_number(TinyVector<3, uint64_t>{i, j, k + 1}); + const uint32_t node_0_id = get_node_id(TinyVector<3, uint64_t>{i, j, k}); + const uint32_t node_1_id = get_node_id(TinyVector<3, uint64_t>{i, j + 1, k}); + const uint32_t node_2_id = get_node_id(TinyVector<3, uint64_t>{i, j + 1, k + 1}); + const uint32_t node_3_id = get_node_id(TinyVector<3, uint64_t>{i, j, k + 1}); - auto i_face = - face_to_id_map.find(Face{{node_0_id, node_1_id, node_2_id, node_3_id}, descriptor.node_number_vector}); - Assert(i_face != face_to_id_map.end()); - - boundary_faces[l++] = i_face->second; + boundary_faces[l++] = find_face({node_0_id, node_1_id, node_2_id, node_3_id}); } } Assert(l == cell_size[1] * cell_size[2]); @@ -375,16 +388,12 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList(const TinyVector<3, uint64_t> size_t l = 0; for (size_t i = 0; i < cell_size[0]; ++i) { for (size_t k = 0; k < cell_size[2]; ++k) { - const uint32_t node_0_id = node_number(TinyVector<3, uint64_t>{i, j, k}); - const uint32_t node_1_id = node_number(TinyVector<3, uint64_t>{i + 1, j, k}); - const uint32_t node_2_id = node_number(TinyVector<3, uint64_t>{i + 1, j, k + 1}); - const uint32_t node_3_id = node_number(TinyVector<3, uint64_t>{i, j, k + 1}); - - auto i_face = - face_to_id_map.find(Face{{node_0_id, node_1_id, node_2_id, node_3_id}, descriptor.node_number_vector}); - Assert(i_face != face_to_id_map.end()); + const uint32_t node_0_id = get_node_id(TinyVector<3, uint64_t>{i, j, k}); + const uint32_t node_1_id = get_node_id(TinyVector<3, uint64_t>{i + 1, j, k}); + const uint32_t node_2_id = get_node_id(TinyVector<3, uint64_t>{i + 1, j, k + 1}); + const uint32_t node_3_id = get_node_id(TinyVector<3, uint64_t>{i, j, k + 1}); - boundary_faces[l++] = i_face->second; + boundary_faces[l++] = find_face({node_0_id, node_1_id, node_2_id, node_3_id}); } } Assert(l == cell_size[0] * cell_size[2]); @@ -401,16 +410,12 @@ LogicalConnectivityBuilder::_buildBoundaryFaceList(const TinyVector<3, uint64_t> size_t l = 0; for (size_t i = 0; i < cell_size[0]; ++i) { for (size_t j = 0; j < cell_size[1]; ++j) { - const uint32_t node_0_id = node_number(TinyVector<3, uint64_t>{i, j, k}); - const uint32_t node_1_id = node_number(TinyVector<3, uint64_t>{i + 1, j, k}); - const uint32_t node_2_id = node_number(TinyVector<3, uint64_t>{i + 1, j + 1, k}); - const uint32_t node_3_id = node_number(TinyVector<3, uint64_t>{i, j + 1, k}); + const uint32_t node_0_id = get_node_id(TinyVector<3, uint64_t>{i, j, k}); + const uint32_t node_1_id = get_node_id(TinyVector<3, uint64_t>{i + 1, j, k}); + const uint32_t node_2_id = get_node_id(TinyVector<3, uint64_t>{i + 1, j + 1, k}); + const uint32_t node_3_id = get_node_id(TinyVector<3, uint64_t>{i, j + 1, k}); - auto i_face = - face_to_id_map.find(Face{{node_0_id, node_1_id, node_2_id, node_3_id}, descriptor.node_number_vector}); - Assert(i_face != face_to_id_map.end()); - - boundary_faces[l++] = i_face->second; + boundary_faces[l++] = find_face({node_0_id, node_1_id, node_2_id, node_3_id}); } } Assert(l == cell_size[0] * cell_size[1]); @@ -431,36 +436,50 @@ LogicalConnectivityBuilder::_buildConnectivity( const size_t number_of_nodes = cell_size[0] + 1; ConnectivityDescriptor descriptor; - descriptor.node_number_vector.resize(number_of_nodes); - for (size_t i = 0; i < number_of_nodes; ++i) { - descriptor.node_number_vector[i] = i; - } + descriptor.setNodeNumberVector([&] { + Array<int> node_number_vector(number_of_nodes); + parallel_for( + number_of_nodes, PUGS_LAMBDA(const size_t i) { node_number_vector[i] = i; }); + return node_number_vector; + }()); + + descriptor.setCellNumberVector([&] { + Array<int> cell_number_vector(number_of_cells); + for (size_t i = 0; i < number_of_cells; ++i) { + cell_number_vector[i] = i; + } + return cell_number_vector; + }()); - descriptor.cell_number_vector.resize(number_of_cells); + Array<CellType> cell_type_vector(number_of_cells); + cell_type_vector.fill(CellType::Line); + descriptor.setCellTypeVector(cell_type_vector); + + Array<unsigned int> cell_to_node_row_map(number_of_cells + 1); + for (size_t i = 0; i < cell_to_node_row_map.size(); ++i) { + cell_to_node_row_map[i] = 2 * i; + } + Array<unsigned int> cell_to_node_list(2 * number_of_cells); for (size_t i = 0; i < number_of_cells; ++i) { - descriptor.cell_number_vector[i] = i; + cell_to_node_list[2 * i] = i; + cell_to_node_list[2 * i + 1] = i + 1; } - descriptor.cell_type_vector.resize(number_of_cells); - std::fill(descriptor.cell_type_vector.begin(), descriptor.cell_type_vector.end(), CellType::Line); - - descriptor.cell_to_node_vector.resize(number_of_cells); - constexpr size_t nb_node_per_cell = 2; - for (size_t j = 0; j < number_of_cells; ++j) { - descriptor.cell_to_node_vector[j].resize(nb_node_per_cell); - for (size_t r = 0; r < nb_node_per_cell; ++r) { - descriptor.cell_to_node_vector[j][0] = j; - descriptor.cell_to_node_vector[j][1] = j + 1; - } - } + descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row_map, cell_to_node_list)); this->_buildBoundaryNodeList(cell_size, descriptor); - descriptor.cell_owner_vector.resize(number_of_cells); - std::fill(descriptor.cell_owner_vector.begin(), descriptor.cell_owner_vector.end(), parallel::rank()); + descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector(number_of_cells); + cell_owner_vector.fill(parallel::rank()); + return cell_owner_vector; + }()); - descriptor.node_owner_vector.resize(descriptor.node_number_vector.size()); - std::fill(descriptor.node_owner_vector.begin(), descriptor.node_owner_vector.end(), parallel::rank()); + descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector(number_of_nodes); + node_owner_vector.fill(parallel::rank()); + return node_owner_vector; + }()); m_connectivity = Connectivity1D::build(descriptor); } @@ -478,18 +497,23 @@ LogicalConnectivityBuilder::_buildConnectivity( const size_t number_of_nodes = node_size[0] * node_size[1]; ConnectivityDescriptor descriptor; - descriptor.node_number_vector.resize(number_of_nodes); - for (size_t i = 0; i < number_of_nodes; ++i) { - descriptor.node_number_vector[i] = i; - } - - descriptor.cell_number_vector.resize(number_of_cells); - for (size_t i = 0; i < number_of_cells; ++i) { - descriptor.cell_number_vector[i] = i; - } - - descriptor.cell_type_vector.resize(number_of_cells); - std::fill(descriptor.cell_type_vector.begin(), descriptor.cell_type_vector.end(), CellType::Quadrangle); + descriptor.setNodeNumberVector([&] { + Array<int> node_number_vector(number_of_nodes); + parallel_for( + number_of_nodes, PUGS_LAMBDA(const size_t i) { node_number_vector[i] = i; }); + return node_number_vector; + }()); + + descriptor.setCellNumberVector([&] { + Array<int> cell_number_vector(number_of_cells); + parallel_for( + number_of_cells, PUGS_LAMBDA(size_t i) { cell_number_vector[i] = i; }); + return cell_number_vector; + }()); + + Array<CellType> cell_type_vector(number_of_cells); + cell_type_vector.fill(CellType::Quadrangle); + descriptor.setCellTypeVector(cell_type_vector); const auto node_number = [&](const TinyVector<Dimension, uint64_t> node_logic_id) { return node_logic_id[0] * node_size[1] + node_logic_id[1]; @@ -501,32 +525,44 @@ LogicalConnectivityBuilder::_buildConnectivity( return TinyVector<Dimension, uint64_t>{j0, j1}; }; - descriptor.cell_to_node_vector.resize(number_of_cells); - constexpr size_t nb_node_per_cell = 1 << Dimension; + Array<unsigned int> cell_to_node_row_map(number_of_cells + 1); + for (size_t i = 0; i < cell_to_node_row_map.size(); ++i) { + cell_to_node_row_map[i] = 4 * i; + } + Array<unsigned int> cell_to_node_list(4 * number_of_cells); for (size_t j = 0; j < number_of_cells; ++j) { TinyVector<Dimension, size_t> cell_index = cell_logic_id(j); - descriptor.cell_to_node_vector[j].resize(nb_node_per_cell); - for (size_t r = 0; r < nb_node_per_cell; ++r) { - descriptor.cell_to_node_vector[j][0] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 0}); - descriptor.cell_to_node_vector[j][1] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 0}); - descriptor.cell_to_node_vector[j][2] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 1}); - descriptor.cell_to_node_vector[j][3] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 1}); - } + + cell_to_node_list[4 * j] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 0}); + cell_to_node_list[4 * j + 1] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 0}); + cell_to_node_list[4 * j + 2] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 1}); + cell_to_node_list[4 * j + 3] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 1}); } + descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row_map, cell_to_node_list)); + ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities<Dimension>(descriptor); this->_buildBoundaryNodeList(cell_size, descriptor); this->_buildBoundaryFaceList(cell_size, descriptor); - descriptor.cell_owner_vector.resize(number_of_cells); - std::fill(descriptor.cell_owner_vector.begin(), descriptor.cell_owner_vector.end(), parallel::rank()); + descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector(number_of_cells); + cell_owner_vector.fill(parallel::rank()); + return cell_owner_vector; + }()); - descriptor.face_owner_vector.resize(descriptor.face_number_vector.size()); - std::fill(descriptor.face_owner_vector.begin(), descriptor.face_owner_vector.end(), parallel::rank()); + descriptor.setFaceOwnerVector([&] { + Array<int> face_owner_vector(descriptor.faceNumberVector().size()); + face_owner_vector.fill(parallel::rank()); + return face_owner_vector; + }()); - descriptor.node_owner_vector.resize(descriptor.node_number_vector.size()); - std::fill(descriptor.node_owner_vector.begin(), descriptor.node_owner_vector.end(), parallel::rank()); + descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector(descriptor.nodeNumberVector().size()); + node_owner_vector.fill(parallel::rank()); + return node_owner_vector; + }()); m_connectivity = Connectivity<Dimension>::build(descriptor); } @@ -560,18 +596,23 @@ LogicalConnectivityBuilder::_buildConnectivity(const TinyVector<3, uint64_t>& ce const size_t number_of_nodes = count_items(node_size); ConnectivityDescriptor descriptor; - descriptor.node_number_vector.resize(number_of_nodes); - for (size_t i = 0; i < number_of_nodes; ++i) { - descriptor.node_number_vector[i] = i; - } - - descriptor.cell_number_vector.resize(number_of_cells); - for (size_t i = 0; i < number_of_cells; ++i) { - descriptor.cell_number_vector[i] = i; - } - - descriptor.cell_type_vector.resize(number_of_cells); - std::fill(descriptor.cell_type_vector.begin(), descriptor.cell_type_vector.end(), CellType::Hexahedron); + descriptor.setNodeNumberVector([&] { + Array<int> node_number_vector(number_of_nodes); + parallel_for( + number_of_nodes, PUGS_LAMBDA(const size_t i) { node_number_vector[i] = i; }); + return node_number_vector; + }()); + + descriptor.setCellNumberVector([&] { + Array<int> cell_number_vector(number_of_cells); + parallel_for( + number_of_cells, PUGS_LAMBDA(size_t i) { cell_number_vector[i] = i; }); + return cell_number_vector; + }()); + + Array<CellType> cell_type_vector(number_of_cells); + cell_type_vector.fill(CellType::Hexahedron); + descriptor.setCellTypeVector(cell_type_vector); const auto cell_logic_id = [&](size_t j) { const size_t slice1 = cell_size[1] * cell_size[2]; @@ -586,24 +627,26 @@ LogicalConnectivityBuilder::_buildConnectivity(const TinyVector<3, uint64_t>& ce return (node_logic_id[0] * node_size[1] + node_logic_id[1]) * node_size[2] + node_logic_id[2]; }; - descriptor.cell_to_node_vector.resize(number_of_cells); - constexpr size_t nb_node_per_cell = 1 << Dimension; + Array<unsigned int> cell_to_node_row_map(number_of_cells + 1); + for (size_t i = 0; i < cell_to_node_row_map.size(); ++i) { + cell_to_node_row_map[i] = 8 * i; + } + Array<unsigned int> cell_to_node_list(8 * number_of_cells); for (size_t j = 0; j < number_of_cells; ++j) { TinyVector<Dimension, size_t> cell_index = cell_logic_id(j); - descriptor.cell_to_node_vector[j].resize(nb_node_per_cell); - for (size_t r = 0; r < nb_node_per_cell; ++r) { - static_assert(Dimension == 3, "unexpected dimension"); - descriptor.cell_to_node_vector[j][0] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 0, 0}); - descriptor.cell_to_node_vector[j][1] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 0, 0}); - descriptor.cell_to_node_vector[j][2] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 1, 0}); - descriptor.cell_to_node_vector[j][3] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 1, 0}); - descriptor.cell_to_node_vector[j][4] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 0, 1}); - descriptor.cell_to_node_vector[j][5] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 0, 1}); - descriptor.cell_to_node_vector[j][6] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 1, 1}); - descriptor.cell_to_node_vector[j][7] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 1, 1}); - } + + cell_to_node_list[8 * j] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 0, 0}); + cell_to_node_list[8 * j + 1] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 0, 0}); + cell_to_node_list[8 * j + 2] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 1, 0}); + cell_to_node_list[8 * j + 3] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 1, 0}); + cell_to_node_list[8 * j + 4] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 0, 1}); + cell_to_node_list[8 * j + 5] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 0, 1}); + cell_to_node_list[8 * j + 6] = node_number(cell_index + TinyVector<Dimension, uint64_t>{1, 1, 1}); + cell_to_node_list[8 * j + 7] = node_number(cell_index + TinyVector<Dimension, uint64_t>{0, 1, 1}); } + descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row_map, cell_to_node_list)); + ConnectivityBuilderBase::_computeCellFaceAndFaceNodeConnectivities<Dimension>(descriptor); ConnectivityBuilderBase::_computeFaceEdgeAndEdgeNodeAndCellEdgeConnectivities<Dimension>(descriptor); @@ -611,17 +654,29 @@ LogicalConnectivityBuilder::_buildConnectivity(const TinyVector<3, uint64_t>& ce this->_buildBoundaryEdgeList(cell_size, descriptor); this->_buildBoundaryFaceList(cell_size, descriptor); - descriptor.cell_owner_vector.resize(number_of_cells); - std::fill(descriptor.cell_owner_vector.begin(), descriptor.cell_owner_vector.end(), parallel::rank()); - - descriptor.face_owner_vector.resize(descriptor.face_number_vector.size()); - std::fill(descriptor.face_owner_vector.begin(), descriptor.face_owner_vector.end(), parallel::rank()); - - descriptor.edge_owner_vector.resize(descriptor.edge_number_vector.size()); - std::fill(descriptor.edge_owner_vector.begin(), descriptor.edge_owner_vector.end(), parallel::rank()); - - descriptor.node_owner_vector.resize(descriptor.node_number_vector.size()); - std::fill(descriptor.node_owner_vector.begin(), descriptor.node_owner_vector.end(), parallel::rank()); + descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector(number_of_cells); + cell_owner_vector.fill(parallel::rank()); + return cell_owner_vector; + }()); + + descriptor.setFaceOwnerVector([&] { + Array<int> face_owner_vector(descriptor.faceNumberVector().size()); + face_owner_vector.fill(parallel::rank()); + return face_owner_vector; + }()); + + descriptor.setEdgeOwnerVector([&] { + Array<int> edge_owner_vector(descriptor.edgeNumberVector().size()); + edge_owner_vector.fill(parallel::rank()); + return edge_owner_vector; + }()); + + descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector(descriptor.nodeNumberVector().size()); + node_owner_vector.fill(parallel::rank()); + return node_owner_vector; + }()); m_connectivity = Connectivity<Dimension>::build(descriptor); } diff --git a/src/mesh/MedianDualConnectivityBuilder.cpp b/src/mesh/MedianDualConnectivityBuilder.cpp index c6770d05ee1d93891d560bd1b1373fd2e68da5eb..1986c4a826a0a3ba2754e6204dafb4f9151bd5f7 100644 --- a/src/mesh/MedianDualConnectivityBuilder.cpp +++ b/src/mesh/MedianDualConnectivityBuilder.cpp @@ -92,33 +92,37 @@ MedianDualConnectivityBuilder::_buildConnectivityDescriptor<2>(const Connectivit Assert(i_boundary_node == primal_number_of_boundary_nodes); } - dual_descriptor.node_number_vector.resize(dual_number_of_nodes); + Array<int> node_number_vector(dual_number_of_nodes); { parallel_for(m_primal_cell_to_dual_node_map.size(), [&](size_t i) { - const auto [primal_cell_id, dual_node_id] = m_primal_cell_to_dual_node_map[i]; - dual_descriptor.node_number_vector[dual_node_id] = primal_cell_number[primal_cell_id]; + const auto [primal_cell_id, dual_node_id] = m_primal_cell_to_dual_node_map[i]; + node_number_vector[dual_node_id] = primal_cell_number[primal_cell_id]; }); const size_t face_number_shift = max(primal_cell_number) + 1; parallel_for(primal_number_of_faces, [&](size_t i) { - const auto [primal_face_id, dual_node_id] = m_primal_face_to_dual_node_map[i]; - dual_descriptor.node_number_vector[dual_node_id] = primal_face_number[primal_face_id] + face_number_shift; + const auto [primal_face_id, dual_node_id] = m_primal_face_to_dual_node_map[i]; + node_number_vector[dual_node_id] = primal_face_number[primal_face_id] + face_number_shift; }); const size_t node_number_shift = face_number_shift + max(primal_face_number) + 1; parallel_for(m_primal_boundary_node_to_dual_node_map.size(), [&](size_t i) { - const auto [primal_node_id, dual_node_id] = m_primal_boundary_node_to_dual_node_map[i]; - dual_descriptor.node_number_vector[dual_node_id] = primal_node_number[primal_node_id] + node_number_shift; + const auto [primal_node_id, dual_node_id] = m_primal_boundary_node_to_dual_node_map[i]; + node_number_vector[dual_node_id] = primal_node_number[primal_node_id] + node_number_shift; }); } + dual_descriptor.setNodeNumberVector(node_number_vector); - dual_descriptor.cell_number_vector.resize(dual_number_of_cells); - parallel_for(dual_number_of_cells, [&](size_t i) { - const auto [primal_node_id, dual_cell_id] = m_primal_node_to_dual_cell_map[i]; - dual_descriptor.cell_number_vector[dual_cell_id] = primal_node_number[primal_node_id]; - }); + { + Array<int> cell_number_vector(dual_number_of_cells); + parallel_for(dual_number_of_cells, [&](size_t i) { + const auto [primal_node_id, dual_cell_id] = m_primal_node_to_dual_cell_map[i]; + cell_number_vector[dual_cell_id] = primal_node_number[primal_node_id]; + }); + dual_descriptor.setCellNumberVector(cell_number_vector); + } - dual_descriptor.cell_type_vector.resize(dual_number_of_cells); + Array<CellType> cell_type_vector(dual_number_of_cells); const auto& primal_node_to_cell_matrix = primal_connectivity.nodeToCellMatrix(); @@ -127,13 +131,13 @@ MedianDualConnectivityBuilder::_buildConnectivityDescriptor<2>(const Connectivit const auto& primal_node_cell_list = primal_node_to_cell_matrix[node_id]; if (primal_node_cell_list.size() == 1) { - dual_descriptor.cell_type_vector[i_dual_cell] = CellType::Quadrangle; + cell_type_vector[i_dual_cell] = CellType::Quadrangle; } else { - dual_descriptor.cell_type_vector[i_dual_cell] = CellType::Polygon; + cell_type_vector[i_dual_cell] = CellType::Polygon; } }); + dual_descriptor.setCellTypeVector(cell_type_vector); - dual_descriptor.cell_to_node_vector.resize(dual_number_of_cells); const auto& primal_cell_to_face_matrix = primal_connectivity.cellToFaceMatrix(); const auto& primal_node_to_face_matrix = primal_connectivity.nodeToFaceMatrix(); const auto& primal_face_to_cell_matrix = primal_connectivity.faceToCellMatrix(); @@ -170,16 +174,35 @@ MedianDualConnectivityBuilder::_buildConnectivityDescriptor<2>(const Connectivit // LCOV_EXCL_STOP }; + Array<unsigned int> cell_to_node_row(dual_number_of_cells + 1); + cell_to_node_row[0] = 0; + { + for (NodeId node_id = 0; node_id < primal_number_of_nodes; ++node_id) { + // const size_t i_dual_cell = node_id; + const auto& primal_node_to_cell_list = primal_node_to_cell_matrix[node_id]; + const auto& primal_node_to_face_list = primal_node_to_face_matrix[node_id]; + + if (primal_node_to_cell_list.size() != primal_node_to_face_list.size()) { + // boundary cell + cell_to_node_row[node_id + 1] = + cell_to_node_row[node_id] + 1 + primal_node_to_cell_list.size() + primal_node_to_face_list.size(); + } else { + // inner cell + cell_to_node_row[node_id + 1] = + cell_to_node_row[node_id] + primal_node_to_cell_list.size() + primal_node_to_face_list.size(); + } + } + } + + Array<unsigned int> cell_to_node_list(cell_to_node_row[cell_to_node_row.size() - 1]); parallel_for(primal_number_of_nodes, [&](NodeId node_id) { - const size_t i_dual_cell = node_id; const auto& primal_node_to_cell_list = primal_node_to_cell_matrix[node_id]; const auto& primal_node_to_face_list = primal_node_to_face_matrix[node_id]; - auto& dual_cell_node_list = dual_descriptor.cell_to_node_vector[i_dual_cell]; + size_t i_dual_cell_node = cell_to_node_row[node_id]; if (primal_node_to_cell_list.size() != primal_node_to_face_list.size()) { // boundary cell - dual_cell_node_list.reserve(1 + primal_node_to_cell_list.size() + primal_node_to_face_list.size()); auto [face_id, cell_id] = [&]() -> std::pair<FaceId, CellId> { for (size_t i_face = 0; i_face < primal_node_to_face_list.size(); ++i_face) { @@ -200,24 +223,24 @@ MedianDualConnectivityBuilder::_buildConnectivityDescriptor<2>(const Connectivit // LCOV_EXCL_STOP }(); - dual_cell_node_list.push_back(m_primal_face_to_dual_node_map[face_id].second); - dual_cell_node_list.push_back(m_primal_cell_to_dual_node_map[cell_id].second); + cell_to_node_list[i_dual_cell_node++] = m_primal_face_to_dual_node_map[face_id].second; + cell_to_node_list[i_dual_cell_node++] = m_primal_cell_to_dual_node_map[cell_id].second; face_id = next_face(cell_id, face_id, node_id); while (primal_face_to_cell_matrix[face_id].size() > 1) { - dual_cell_node_list.push_back(m_primal_face_to_dual_node_map[face_id].second); - cell_id = next_cell(cell_id, face_id); - dual_cell_node_list.push_back(m_primal_cell_to_dual_node_map[cell_id].second); + cell_to_node_list[i_dual_cell_node++] = m_primal_face_to_dual_node_map[face_id].second; + + cell_id = next_cell(cell_id, face_id); + cell_to_node_list[i_dual_cell_node++] = m_primal_cell_to_dual_node_map[cell_id].second; + face_id = next_face(cell_id, face_id, node_id); } - dual_cell_node_list.push_back(m_primal_face_to_dual_node_map[face_id].second); - dual_cell_node_list.push_back(node_to_dual_node_correpondance[node_id]); + cell_to_node_list[i_dual_cell_node++] = m_primal_face_to_dual_node_map[face_id].second; + cell_to_node_list[i_dual_cell_node++] = node_to_dual_node_correpondance[node_id]; - Assert(dual_cell_node_list.size() == 1 + primal_node_to_cell_list.size() + primal_node_to_face_list.size()); } else { // inner cell - dual_cell_node_list.reserve(primal_node_to_cell_list.size() + primal_node_to_face_list.size()); auto [face_id, cell_id] = [&]() -> std::pair<FaceId, CellId> { const FaceId face_id = primal_node_to_face_list[0]; @@ -237,14 +260,16 @@ MedianDualConnectivityBuilder::_buildConnectivityDescriptor<2>(const Connectivit const FaceId first_face_id = face_id; do { - dual_cell_node_list.push_back(m_primal_face_to_dual_node_map[face_id].second); - dual_cell_node_list.push_back(m_primal_cell_to_dual_node_map[cell_id].second); + cell_to_node_list[i_dual_cell_node++] = m_primal_face_to_dual_node_map[face_id].second; + cell_to_node_list[i_dual_cell_node++] = m_primal_cell_to_dual_node_map[cell_id].second; face_id = next_face(cell_id, face_id, node_id); cell_id = next_cell(cell_id, face_id); } while (face_id != first_face_id); } }); + + dual_descriptor.setCellToNodeMatrix(ConnectivityMatrix(cell_to_node_row, cell_to_node_list)); } template <> @@ -277,39 +302,28 @@ MedianDualConnectivityBuilder::_buildConnectivityFrom<2>(const IConnectivity& i_ const auto& primal_node_list = primal_ref_node_list.list(); const std::vector<NodeId> dual_node_list = [&]() { - std::vector<NodeId> dual_node_list; + std::vector<NodeId> tmp_dual_node_list; for (size_t i_primal_node = 0; i_primal_node < primal_node_list.size(); ++i_primal_node) { auto primal_node_id = primal_node_list[i_primal_node]; const auto i_dual_node = primal_boundary_node_id_to_dual_node_id_map.find(primal_connectivity.nodeNumber()[primal_node_id]); if (i_dual_node != primal_boundary_node_id_to_dual_node_id_map.end()) { - dual_node_list.push_back(i_dual_node->second); + tmp_dual_node_list.push_back(i_dual_node->second); } } - return dual_node_list; + return tmp_dual_node_list; }(); if (parallel::allReduceOr(dual_node_list.size() > 0)) { - dual_descriptor.addRefItemList(RefNodeList{primal_ref_node_list.refId(), convert_to_array(dual_node_list), - primal_ref_node_list.isBoundary()}); + auto dual_node_array = convert_to_array(dual_node_list); + dual_descriptor.addRefItemList( + RefNodeList{primal_ref_node_list.refId(), dual_node_array, primal_ref_node_list.isBoundary()}); } } } - using Face = ConnectivityFace<2>; - - const std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map = [&] { - std::unordered_map<Face, FaceId, typename Face::Hash> face_to_id_map; - for (FaceId l = 0; l < dual_descriptor.face_to_node_vector.size(); ++l) { - const auto& node_vector = dual_descriptor.face_to_node_vector[l]; - - face_to_id_map[Face(node_vector, dual_descriptor.node_number_vector)] = l; - } - return face_to_id_map; - }(); - for (size_t i_face_list = 0; i_face_list < primal_connectivity.template numberOfRefItemList<ItemType::face>(); ++i_face_list) { const auto& primal_ref_face_list = primal_connectivity.template refItemList<ItemType::face>(i_face_list); @@ -321,21 +335,23 @@ MedianDualConnectivityBuilder::_buildConnectivityFrom<2>(const IConnectivity& i_ bounday_face_dual_node_id_list[i_face] = m_primal_face_to_dual_node_map[primal_face_list[i_face]].second; } - std::vector<bool> is_dual_node_from_boundary_face(dual_descriptor.node_number_vector.size(), false); + std::vector<bool> is_dual_node_from_boundary_face(dual_descriptor.nodeNumberVector().size(), false); for (size_t i_face = 0; i_face < bounday_face_dual_node_id_list.size(); ++i_face) { is_dual_node_from_boundary_face[bounday_face_dual_node_id_list[i_face]] = true; } - std::vector<bool> is_dual_node_from_boundary_node(dual_descriptor.node_number_vector.size(), false); + std::vector<bool> is_dual_node_from_boundary_node(dual_descriptor.nodeNumberVector().size(), false); for (size_t i_node = 0; i_node < m_primal_boundary_node_to_dual_node_map.size(); ++i_node) { is_dual_node_from_boundary_node[m_primal_boundary_node_to_dual_node_map[i_node].second] = true; } + const auto& dual_face_to_node_matrix = dual_descriptor.faceToNodeMatrix(); + std::vector<FaceId> dual_face_list; dual_face_list.reserve(2 * primal_face_list.size()); - for (size_t i_dual_face = 0; i_dual_face < dual_descriptor.face_to_node_vector.size(); ++i_dual_face) { - const NodeId dual_node_0 = dual_descriptor.face_to_node_vector[i_dual_face][0]; - const NodeId dual_node_1 = dual_descriptor.face_to_node_vector[i_dual_face][1]; + for (size_t i_dual_face = 0; i_dual_face < dual_face_to_node_matrix.numberOfRows(); ++i_dual_face) { + const NodeId dual_node_0 = dual_face_to_node_matrix[i_dual_face][0]; + const NodeId dual_node_1 = dual_face_to_node_matrix[i_dual_face][1]; if ((is_dual_node_from_boundary_face[dual_node_0] and is_dual_node_from_boundary_node[dual_node_1]) or (is_dual_node_from_boundary_node[dual_node_0] and is_dual_node_from_boundary_face[dual_node_1])) { @@ -352,42 +368,61 @@ MedianDualConnectivityBuilder::_buildConnectivityFrom<2>(const IConnectivity& i_ } } - const size_t primal_number_of_nodes = primal_connectivity.numberOfNodes(); - const size_t primal_number_of_cells = primal_connectivity.numberOfCells(); + const auto& primal_node_owner = primal_connectivity.nodeOwner(); - dual_descriptor.node_owner_vector.resize(dual_descriptor.node_number_vector.size()); + dual_descriptor.setNodeOwnerVector([&] { + Array<int> node_owner_vector(dual_descriptor.nodeNumberVector().size()); - const auto& primal_node_owner = primal_connectivity.nodeOwner(); - for (NodeId primal_node_id = 0; primal_node_id < primal_connectivity.numberOfNodes(); ++primal_node_id) { - dual_descriptor.node_owner_vector[primal_node_id] = primal_node_owner[primal_node_id]; - } - const auto& primal_cell_owner = primal_connectivity.cellOwner(); - for (CellId primal_cell_id = 0; primal_cell_id < primal_number_of_cells; ++primal_cell_id) { - dual_descriptor.node_owner_vector[primal_number_of_nodes + primal_cell_id] = primal_cell_owner[primal_cell_id]; - } + node_owner_vector.fill(-1); + for (size_t i_primal_node_to_dual_node = 0; + i_primal_node_to_dual_node < m_primal_boundary_node_to_dual_node_map.size(); ++i_primal_node_to_dual_node) { + const auto& [primal_node_id, dual_node_id] = m_primal_boundary_node_to_dual_node_map[i_primal_node_to_dual_node]; + node_owner_vector[dual_node_id] = primal_node_owner[primal_node_id]; + } - dual_descriptor.cell_owner_vector.resize(dual_descriptor.cell_number_vector.size()); - for (NodeId primal_node_id = 0; primal_node_id < primal_number_of_nodes; ++primal_node_id) { - dual_descriptor.cell_owner_vector[primal_node_id] = primal_node_owner[primal_node_id]; - } + const auto& primal_face_owner = primal_connectivity.faceOwner(); + for (size_t i_primal_face_to_dual_node = 0; i_primal_face_to_dual_node < m_primal_face_to_dual_node_map.size(); + ++i_primal_face_to_dual_node) { + const auto& [primal_face_id, dual_node_id] = m_primal_face_to_dual_node_map[i_primal_face_to_dual_node]; + node_owner_vector[dual_node_id] = primal_face_owner[primal_face_id]; + } - { - std::vector<int> face_cell_owner(dual_descriptor.face_number_vector.size()); - std::fill(std::begin(face_cell_owner), std::end(face_cell_owner), parallel::size()); + const auto& primal_cell_owner = primal_connectivity.cellOwner(); + for (size_t i_primal_cell_to_dual_node = 0; i_primal_cell_to_dual_node < m_primal_cell_to_dual_node_map.size(); + ++i_primal_cell_to_dual_node) { + const auto& [primal_cell_id, dual_node_id] = m_primal_cell_to_dual_node_map[i_primal_cell_to_dual_node]; + node_owner_vector[dual_node_id] = primal_cell_owner[primal_cell_id]; + } - for (size_t i_cell = 0; i_cell < dual_descriptor.cell_to_face_vector.size(); ++i_cell) { - const auto& cell_face_list = dual_descriptor.cell_to_face_vector[i_cell]; - for (size_t i_face = 0; i_face < cell_face_list.size(); ++i_face) { - const size_t face_id = cell_face_list[i_face]; - face_cell_owner[face_id] = std::min(face_cell_owner[face_id], dual_descriptor.cell_number_vector[i_cell]); - } + return node_owner_vector; + }()); + + dual_descriptor.setCellOwnerVector([&] { + Array<int> cell_owner_vector(dual_descriptor.cellNumberVector().size()); + cell_owner_vector.fill(-1); + for (size_t i_primal_cell_to_dual_node = 0; i_primal_cell_to_dual_node < m_primal_node_to_dual_cell_map.size(); + ++i_primal_cell_to_dual_node) { + const auto& [primal_node_id, dual_cell_id] = m_primal_node_to_dual_cell_map[i_primal_cell_to_dual_node]; + cell_owner_vector[dual_cell_id] = primal_node_owner[primal_node_id]; } + return cell_owner_vector; + }()); - dual_descriptor.face_owner_vector.resize(face_cell_owner.size()); - for (size_t i_face = 0; i_face < face_cell_owner.size(); ++i_face) { - dual_descriptor.face_owner_vector[i_face] = dual_descriptor.cell_owner_vector[face_cell_owner[i_face]]; + dual_descriptor.setFaceOwnerVector([&] { + const auto& dual_cell_to_face_matrix = dual_descriptor.cellToFaceMatrix(); + const auto& dual_cell_owner_vector = dual_descriptor.cellOwnerVector(); + + Array<int> face_owner_vector(dual_descriptor.faceNumberVector().size()); + face_owner_vector.fill(parallel::size()); + for (size_t i_cell = 0; i_cell < dual_cell_to_face_matrix.numberOfRows(); ++i_cell) { + const auto& cell_face_list = dual_cell_to_face_matrix[i_cell]; + for (size_t i_face = 0; i_face < cell_face_list.size(); ++i_face) { + const size_t face_id = cell_face_list[i_face]; + face_owner_vector[face_id] = std::min(face_owner_vector[face_id], dual_cell_owner_vector[i_cell]); + } } - } + return face_owner_vector; + }()); m_connectivity = ConnectivityType::build(dual_descriptor); diff --git a/src/mesh/MeshBuilderBase.cpp b/src/mesh/MeshBuilderBase.cpp index a3a8440bd25499d8aea34a08e7c836b66a4c3a32..973a6099afb49595d02403c697bbb927d2a7ba63 100644 --- a/src/mesh/MeshBuilderBase.cpp +++ b/src/mesh/MeshBuilderBase.cpp @@ -132,8 +132,14 @@ MeshBuilderBase::_checkMesh() const if (intersection.size() > 1) { std::ostringstream error_msg; error_msg << "invalid mesh.\n\tFollowing faces\n"; - for (FaceId face_id : intersection) { - error_msg << "\t - id=" << face_id << " number=" << connectivity.faceNumber()[face_id] << '\n'; + for (FaceId intersection_face_id : intersection) { + error_msg << "\t - id=" << intersection_face_id + << " number=" << connectivity.faceNumber()[intersection_face_id] << '\n'; + error_msg << "\t nodes:"; + for (size_t i = 0; i < face_to_node_matrix[intersection_face_id].size(); ++i) { + error_msg << ' ' << face_to_node_matrix[intersection_face_id][i]; + } + error_msg << '\n'; } error_msg << "\tare duplicated"; throw NormalError(error_msg.str()); diff --git a/src/output/NamedDiscreteFunction.hpp b/src/output/NamedDiscreteFunction.hpp index d56d44369bb2e5492c078a35a0cf0a01e5524d42..305db7be68d5a2ca6a4790c1d4bde525297e8999 100644 --- a/src/output/NamedDiscreteFunction.hpp +++ b/src/output/NamedDiscreteFunction.hpp @@ -6,12 +6,12 @@ #include <memory> #include <string> -class IDiscreteFunction; +class DiscreteFunctionVariant; class NamedDiscreteFunction final : public INamedDiscreteData { private: - std::shared_ptr<const IDiscreteFunction> m_discrete_function; + std::shared_ptr<const DiscreteFunctionVariant> m_discrete_function_variant; std::string m_name; public: @@ -27,14 +27,15 @@ class NamedDiscreteFunction final : public INamedDiscreteData return m_name; } - const std::shared_ptr<const IDiscreteFunction> - discreteFunction() const + const std::shared_ptr<const DiscreteFunctionVariant> + discreteFunctionVariant() const { - return m_discrete_function; + return m_discrete_function_variant; } - NamedDiscreteFunction(const std::shared_ptr<const IDiscreteFunction>& discrete_function, const std::string& name) - : m_discrete_function{discrete_function}, m_name{name} + NamedDiscreteFunction(const std::shared_ptr<const DiscreteFunctionVariant>& discrete_function, + const std::string& name) + : m_discrete_function_variant{discrete_function}, m_name{name} {} NamedDiscreteFunction(const NamedDiscreteFunction&) = default; diff --git a/src/output/WriterBase.cpp b/src/output/WriterBase.cpp index fcb2cf78f21f3bebc878b0343826c3abab4636c1..83d890c2ab8bf31e60d7ed09e4e2da7770ebbfb8 100644 --- a/src/output/WriterBase.cpp +++ b/src/output/WriterBase.cpp @@ -7,7 +7,7 @@ #include <output/OutputNamedItemValueSet.hpp> #include <scheme/DiscreteFunctionP0.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> -#include <scheme/IDiscreteFunction.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> #include <utils/Exceptions.hpp> @@ -17,142 +17,14 @@ WriterBase::_registerDiscreteFunction(const std::string& name, const DiscreteFunctionType& discrete_function, OutputNamedItemDataSet& named_item_data_set) { - if constexpr (DiscreteFunctionType::handled_data_type == IDiscreteFunction::HandledItemDataType::value) { + if constexpr (is_discrete_function_P0_v<DiscreteFunctionType>) { named_item_data_set.add(NamedItemData{name, discrete_function.cellValues()}); } else { + static_assert(is_discrete_function_P0_vector_v<DiscreteFunctionType>, "unexpected discrete function type"); named_item_data_set.add(NamedItemData{name, discrete_function.cellArrays()}); } } -template <size_t Dimension, template <size_t DimensionT, typename DataTypeT> typename DiscreteFunctionType> -void -WriterBase::_registerDiscreteFunction(const std::string& name, - const IDiscreteFunction& i_discrete_function, - OutputNamedItemDataSet& named_item_data_set) -{ - const ASTNodeDataType& data_type = i_discrete_function.dataType(); - switch (data_type) { - case ASTNodeDataType::bool_t: { - _registerDiscreteFunction(name, dynamic_cast<const DiscreteFunctionType<Dimension, bool>&>(i_discrete_function), - named_item_data_set); - break; - } - case ASTNodeDataType::unsigned_int_t: { - _registerDiscreteFunction(name, dynamic_cast<const DiscreteFunctionType<Dimension, uint64_t>&>(i_discrete_function), - named_item_data_set); - break; - } - case ASTNodeDataType::int_t: { - _registerDiscreteFunction(name, dynamic_cast<const DiscreteFunctionType<Dimension, int64_t>&>(i_discrete_function), - named_item_data_set); - break; - } - case ASTNodeDataType::double_t: { - _registerDiscreteFunction(name, dynamic_cast<const DiscreteFunctionType<Dimension, double>&>(i_discrete_function), - named_item_data_set); - break; - } - case ASTNodeDataType::vector_t: { - if constexpr (DiscreteFunctionType<Dimension, double>::handled_data_type == - IDiscreteFunction::HandledItemDataType::vector) { - throw UnexpectedError("invalid data type for vector data"); - } else { - switch (data_type.dimension()) { - case 1: { - _registerDiscreteFunction(name, - dynamic_cast<const DiscreteFunctionType<Dimension, TinyVector<1, double>>&>( - i_discrete_function), - named_item_data_set); - break; - } - case 2: { - _registerDiscreteFunction(name, - dynamic_cast<const DiscreteFunctionType<Dimension, TinyVector<2, double>>&>( - i_discrete_function), - named_item_data_set); - break; - } - case 3: { - _registerDiscreteFunction(name, - dynamic_cast<const DiscreteFunctionType<Dimension, TinyVector<3, double>>&>( - i_discrete_function), - named_item_data_set); - break; - } - default: { - throw UnexpectedError("invalid vector dimension"); - } - } - } - break; - } - case ASTNodeDataType::matrix_t: { - if constexpr (DiscreteFunctionType<Dimension, double>::handled_data_type == - IDiscreteFunction::HandledItemDataType::vector) { - throw UnexpectedError("invalid data type for vector data"); - } else { - Assert(data_type.numberOfRows() == data_type.numberOfColumns(), "invalid matrix dimensions"); - switch (data_type.numberOfRows()) { - case 1: { - _registerDiscreteFunction(name, - dynamic_cast<const DiscreteFunctionType<Dimension, TinyMatrix<1, 1, double>>&>( - i_discrete_function), - named_item_data_set); - break; - } - case 2: { - _registerDiscreteFunction(name, - dynamic_cast<const DiscreteFunctionType<Dimension, TinyMatrix<2, 2, double>>&>( - i_discrete_function), - named_item_data_set); - break; - } - case 3: { - _registerDiscreteFunction(name, - dynamic_cast<const DiscreteFunctionType<Dimension, TinyMatrix<3, 3, double>>&>( - i_discrete_function), - named_item_data_set); - break; - } - default: { - throw UnexpectedError("invalid matrix dimension"); - } - } - } - break; - } - default: { - throw UnexpectedError("invalid data type " + dataTypeName(data_type)); - } - } -} - -template <template <size_t Dimension, typename DataType> typename DiscreteFunctionType> -void -WriterBase::_registerDiscreteFunction(const NamedDiscreteFunction& named_discrete_function, - OutputNamedItemDataSet& named_item_data_set) -{ - const IDiscreteFunction& i_discrete_function = *named_discrete_function.discreteFunction(); - const std::string& name = named_discrete_function.name(); - switch (i_discrete_function.mesh()->dimension()) { - case 1: { - _registerDiscreteFunction<1, DiscreteFunctionType>(name, i_discrete_function, named_item_data_set); - break; - } - case 2: { - _registerDiscreteFunction<2, DiscreteFunctionType>(name, i_discrete_function, named_item_data_set); - break; - } - case 3: { - _registerDiscreteFunction<3, DiscreteFunctionType>(name, i_discrete_function, named_item_data_set); - break; - } - default: { - throw UnexpectedError("invalid mesh dimension"); - } - } -} - void WriterBase::_checkConnectivity( const std::shared_ptr<const IMesh>& mesh, @@ -211,7 +83,11 @@ WriterBase::_checkMesh(const std::shared_ptr<const IMesh>& mesh, const NamedDiscreteFunction& named_discrete_function = dynamic_cast<const NamedDiscreteFunction&>(*named_discrete_data); - if (mesh != named_discrete_function.discreteFunction()->mesh()) { + std::shared_ptr<const IMesh> discrete_function_mesh = + std::visit([](auto&& f) { return f.mesh(); }, + named_discrete_function.discreteFunctionVariant()->discreteFunction()); + + if (mesh != discrete_function_mesh) { std::ostringstream error_msg; error_msg << "The variable " << rang::fgB::yellow << named_discrete_function.name() << rang::fg::reset << " is not defined on the provided mesh\n"; @@ -237,7 +113,8 @@ WriterBase::_getMesh(const std::vector<std::shared_ptr<const INamedDiscreteData> const NamedDiscreteFunction& named_discrete_function = dynamic_cast<const NamedDiscreteFunction&>(*named_discrete_data); - std::shared_ptr mesh = named_discrete_function.discreteFunction()->mesh(); + std::shared_ptr mesh = std::visit([&](auto&& f) { return f.mesh(); }, + named_discrete_function.discreteFunctionVariant()->discreteFunction()); mesh_set[mesh] = named_discrete_function.name(); switch (mesh->dimension()) { @@ -317,24 +194,12 @@ WriterBase::_getOutputNamedItemDataSet( const NamedDiscreteFunction& named_discrete_function = dynamic_cast<const NamedDiscreteFunction&>(*named_discrete_data); - const IDiscreteFunction& i_discrete_function = *named_discrete_function.discreteFunction(); + const std::string& name = named_discrete_function.name(); - switch (i_discrete_function.descriptor().type()) { - case DiscreteFunctionType::P0: { - WriterBase::_registerDiscreteFunction<DiscreteFunctionP0>(named_discrete_function, named_item_data_set); - break; - } - case DiscreteFunctionType::P0Vector: { - WriterBase::_registerDiscreteFunction<DiscreteFunctionP0Vector>(named_discrete_function, named_item_data_set); - break; - } - default: { - std::ostringstream error_msg; - error_msg << "the type of discrete function of " << rang::fgB::blue << named_discrete_data->name() - << rang::style::reset << " is not supported"; - throw NormalError(error_msg.str()); - } - } + const DiscreteFunctionVariant& discrete_function_variant = *named_discrete_function.discreteFunctionVariant(); + + std::visit([&](auto&& f) { WriterBase::_registerDiscreteFunction(name, f, named_item_data_set); }, + discrete_function_variant.discreteFunction()); break; } case INamedDiscreteData::Type::item_value: { diff --git a/src/output/WriterBase.hpp b/src/output/WriterBase.hpp index 339cd7645c8cbdc903357cee6000d1c6ab45dda3..7fae994d78ed0e97be8f10d63097464280c739fc 100644 --- a/src/output/WriterBase.hpp +++ b/src/output/WriterBase.hpp @@ -10,7 +10,6 @@ class IMesh; class OutputNamedItemDataSet; -class IDiscreteFunction; class NamedDiscreteFunction; class WriterBase : public IWriter @@ -90,12 +89,6 @@ class WriterBase : public IWriter template <typename DiscreteFunctionType> static void _registerDiscreteFunction(const std::string& name, const DiscreteFunctionType&, OutputNamedItemDataSet&); - template <size_t Dimension, template <size_t DimensionT, typename DataTypeT> typename DiscreteFunctionType> - static void _registerDiscreteFunction(const std::string& name, const IDiscreteFunction&, OutputNamedItemDataSet&); - - template <template <size_t DimensionT, typename DataTypeT> typename DiscreteFunctionType> - static void _registerDiscreteFunction(const NamedDiscreteFunction&, OutputNamedItemDataSet&); - protected: void _checkConnectivity(const std::shared_ptr<const IMesh>& mesh, const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const; diff --git a/src/scheme/AcousticSolver.cpp b/src/scheme/AcousticSolver.cpp index 589b1d380d6ba1fbac10a61290552fe85ab1d193..f61f27cb46c4ed9dbee0481c433e6f9aa3ea4da0 100644 --- a/src/scheme/AcousticSolver.cpp +++ b/src/scheme/AcousticSolver.cpp @@ -13,7 +13,6 @@ #include <scheme/ExternalBoundaryConditionDescriptor.hpp> #include <scheme/FixedBoundaryConditionDescriptor.hpp> #include <scheme/IBoundaryConditionDescriptor.hpp> -#include <scheme/IDiscreteFunction.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> #include <scheme/SymmetryBoundaryConditionDescriptor.hpp> #include <utils/Socket.hpp> @@ -23,7 +22,7 @@ template <size_t Dimension> double -acoustic_dt(const DiscreteFunctionP0<Dimension, double>& c) +acoustic_dt(const DiscreteFunctionP0<Dimension, const double>& c) { const Mesh<Connectivity<Dimension>>& mesh = dynamic_cast<const Mesh<Connectivity<Dimension>>&>(*c.mesh()); @@ -38,23 +37,19 @@ acoustic_dt(const DiscreteFunctionP0<Dimension, double>& c) } double -acoustic_dt(const std::shared_ptr<const IDiscreteFunction>& c) +acoustic_dt(const std::shared_ptr<const DiscreteFunctionVariant>& c) { - if ((c->descriptor().type() != DiscreteFunctionType::P0) or (c->dataType() != ASTNodeDataType::double_t)) { - throw NormalError("invalid discrete function type"); - } - - std::shared_ptr mesh = c->mesh(); + std::shared_ptr mesh = getCommonMesh({c}); switch (mesh->dimension()) { case 1: { - return acoustic_dt(dynamic_cast<const DiscreteFunctionP0<1, double>&>(*c)); + return acoustic_dt(c->get<DiscreteFunctionP0<1, const double>>()); } case 2: { - return acoustic_dt(dynamic_cast<const DiscreteFunctionP0<2, double>&>(*c)); + return acoustic_dt(c->get<DiscreteFunctionP0<2, const double>>()); } case 3: { - return acoustic_dt(dynamic_cast<const DiscreteFunctionP0<3, double>&>(*c)); + return acoustic_dt(c->get<DiscreteFunctionP0<3, const double>>()); } default: { throw UnexpectedError("invalid mesh dimension"); @@ -72,8 +67,8 @@ class AcousticSolverHandler::AcousticSolver final : public AcousticSolverHandler using MeshType = Mesh<Connectivity<Dimension>>; using MeshDataType = MeshData<Dimension>; - using DiscreteScalarFunction = DiscreteFunctionP0<Dimension, double>; - using DiscreteVectorFunction = DiscreteFunctionP0<Dimension, Rd>; + using DiscreteScalarFunction = DiscreteFunctionP0<Dimension, const double>; + using DiscreteVectorFunction = DiscreteFunctionP0<Dimension, const Rd>; class FixedBoundaryCondition; class PressureBoundaryCondition; @@ -381,26 +376,26 @@ class AcousticSolverHandler::AcousticSolver final : public AcousticSolverHandler public: std::tuple<const std::shared_ptr<const ItemValueVariant>, const std::shared_ptr<const SubItemValuePerItemVariant>> compute_fluxes(const SolverType& solver_type, - const std::shared_ptr<const IDiscreteFunction>& i_rho, - const std::shared_ptr<const IDiscreteFunction>& i_c, - const std::shared_ptr<const IDiscreteFunction>& i_u, - const std::shared_ptr<const IDiscreteFunction>& i_p, + const std::shared_ptr<const DiscreteFunctionVariant>& rho_v, + const std::shared_ptr<const DiscreteFunctionVariant>& c_v, + const std::shared_ptr<const DiscreteFunctionVariant>& u_v, + const std::shared_ptr<const DiscreteFunctionVariant>& p_v, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const { - std::shared_ptr i_mesh = getCommonMesh({i_rho, i_c, i_u, i_p}); + std::shared_ptr i_mesh = getCommonMesh({rho_v, c_v, u_v, p_v}); if (not i_mesh) { throw NormalError("discrete functions are not defined on the same mesh"); } - if (not checkDiscretizationType({i_rho, i_c, i_u, i_p}, DiscreteFunctionType::P0)) { + if (not checkDiscretizationType({rho_v, c_v, u_v, p_v}, DiscreteFunctionType::P0)) { throw NormalError("acoustic solver expects P0 functions"); } const MeshType& mesh = dynamic_cast<const MeshType&>(*i_mesh); - const DiscreteScalarFunction& rho = dynamic_cast<const DiscreteScalarFunction&>(*i_rho); - const DiscreteScalarFunction& c = dynamic_cast<const DiscreteScalarFunction&>(*i_c); - const DiscreteVectorFunction& u = dynamic_cast<const DiscreteVectorFunction&>(*i_u); - const DiscreteScalarFunction& p = dynamic_cast<const DiscreteScalarFunction&>(*i_p); + const DiscreteScalarFunction& rho = rho_v->get<DiscreteScalarFunction>(); + const DiscreteScalarFunction& c = c_v->get<DiscreteScalarFunction>(); + const DiscreteVectorFunction& u = u_v->get<DiscreteVectorFunction>(); + const DiscreteScalarFunction& p = p_v->get<DiscreteScalarFunction>(); NodeValuePerCell<const Rdxd> Ajr = this->_computeAjr(solver_type, mesh, rho * c); @@ -422,14 +417,14 @@ class AcousticSolverHandler::AcousticSolver final : public AcousticSolverHandler } std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const DiscreteFunctionP0<Dimension, double>>, - std::shared_ptr<const DiscreteFunctionP0<Dimension, Rd>>, - std::shared_ptr<const DiscreteFunctionP0<Dimension, double>>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply_fluxes(const double& dt, const MeshType& mesh, - const DiscreteFunctionP0<Dimension, double>& rho, - const DiscreteFunctionP0<Dimension, Rd>& u, - const DiscreteFunctionP0<Dimension, double>& E, + const DiscreteScalarFunction& rho, + const DiscreteVectorFunction& u, + const DiscreteScalarFunction& E, const NodeValue<const Rd>& ur, const NodeValuePerCell<const Rd>& Fjr) const { @@ -473,51 +468,51 @@ class AcousticSolverHandler::AcousticSolver final : public AcousticSolverHandler parallel_for( mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { new_rho[j] *= Vj[j] / new_Vj[j]; }); - return {new_mesh, std::make_shared<DiscreteScalarFunction>(new_mesh, new_rho), - std::make_shared<DiscreteVectorFunction>(new_mesh, new_u), - std::make_shared<DiscreteScalarFunction>(new_mesh, new_E)}; + return {new_mesh, std::make_shared<DiscreteFunctionVariant>(DiscreteScalarFunction(new_mesh, new_rho)), + std::make_shared<DiscreteFunctionVariant>(DiscreteVectorFunction(new_mesh, new_u)), + std::make_shared<DiscreteFunctionVariant>(DiscreteScalarFunction(new_mesh, new_E))}; } std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply_fluxes(const double& dt, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& rho_v, + const std::shared_ptr<const DiscreteFunctionVariant>& u_v, + const std::shared_ptr<const DiscreteFunctionVariant>& E_v, const std::shared_ptr<const ItemValueVariant>& ur, const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr) const { - std::shared_ptr i_mesh = getCommonMesh({rho, u, E}); + std::shared_ptr i_mesh = getCommonMesh({rho_v, u_v, E_v}); if (not i_mesh) { throw NormalError("discrete functions are not defined on the same mesh"); } - if (not checkDiscretizationType({rho, u, E}, DiscreteFunctionType::P0)) { + if (not checkDiscretizationType({rho_v, u_v, E_v}, DiscreteFunctionType::P0)) { throw NormalError("acoustic solver expects P0 functions"); } - return this->apply_fluxes(dt, // - dynamic_cast<const MeshType&>(*i_mesh), // - dynamic_cast<const DiscreteScalarFunction&>(*rho), // - dynamic_cast<const DiscreteVectorFunction&>(*u), // - dynamic_cast<const DiscreteScalarFunction&>(*E), // - ur->get<NodeValue<const Rd>>(), // + return this->apply_fluxes(dt, // + dynamic_cast<const MeshType&>(*i_mesh), // + rho_v->get<DiscreteScalarFunction>(), // + u_v->get<DiscreteVectorFunction>(), // + E_v->get<DiscreteScalarFunction>(), // + ur->get<NodeValue<const Rd>>(), // Fjr->get<NodeValuePerCell<const Rd>>()); } std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply(const SolverType& solver_type, const double& dt, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& c, - const std::shared_ptr<const IDiscreteFunction>& p, + const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& c, + const std::shared_ptr<const DiscreteFunctionVariant>& p, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const { auto [ur, Fjr] = compute_fluxes(solver_type, rho, c, u, p, bc_descriptor_list); diff --git a/src/scheme/AcousticSolver.hpp b/src/scheme/AcousticSolver.hpp index 489b8e795d843f9677daf562214bd0266f803baa..36b62a32a1442b18cbe014a9e90ee28ffad08c8a 100644 --- a/src/scheme/AcousticSolver.hpp +++ b/src/scheme/AcousticSolver.hpp @@ -5,13 +5,13 @@ #include <tuple> #include <vector> -class IDiscreteFunction; +class DiscreteFunctionVariant; class IBoundaryConditionDescriptor; class IMesh; class ItemValueVariant; class SubItemValuePerItemVariant; -double acoustic_dt(const std::shared_ptr<const IDiscreteFunction>& c); +double acoustic_dt(const std::shared_ptr<const DiscreteFunctionVariant>& c); class AcousticSolverHandler { @@ -29,34 +29,34 @@ class AcousticSolverHandler const std::shared_ptr<const SubItemValuePerItemVariant>> compute_fluxes( const SolverType& solver_type, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& c, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& p, + const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& c, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& p, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const = 0; virtual std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply_fluxes(const double& dt, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, const std::shared_ptr<const ItemValueVariant>& ur, const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr) const = 0; virtual std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply(const SolverType& solver_type, const double& dt, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& c, - const std::shared_ptr<const IDiscreteFunction>& p, + const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& c, + const std::shared_ptr<const DiscreteFunctionVariant>& p, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const = 0; IAcousticSolver() = default; diff --git a/src/scheme/DiscreteFunctionIntegrator.cpp b/src/scheme/DiscreteFunctionIntegrator.cpp index 93c836461ce14ae05b51b879cf90525f73a793eb..c77f7a2c87ece74da4f48902855e9f3a5f6742bc 100644 --- a/src/scheme/DiscreteFunctionIntegrator.cpp +++ b/src/scheme/DiscreteFunctionIntegrator.cpp @@ -3,10 +3,11 @@ #include <language/utils/IntegrateCellValue.hpp> #include <mesh/MeshCellZone.hpp> #include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <utils/Exceptions.hpp> template <size_t Dimension, typename DataType, typename ValueType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionIntegrator::_integrateOnZoneList() const { static_assert(std::is_convertible_v<DataType, ValueType>); @@ -61,11 +62,11 @@ DiscreteFunctionIntegrator::_integrateOnZoneList() const parallel_for( zone_cell_list.size(), PUGS_LAMBDA(const size_t i_cell) { cell_value[zone_cell_list[i_cell]] = array[i_cell]; }); - return std::make_shared<DiscreteFunctionP0<Dimension, ValueType>>(p_mesh, cell_value); + return DiscreteFunctionP0<Dimension, ValueType>(p_mesh, cell_value); } template <size_t Dimension, typename DataType, typename ValueType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionIntegrator::_integrateGlobally() const { Assert(m_zone_list.size() == 0, "invalid call when zones are defined"); @@ -75,14 +76,13 @@ DiscreteFunctionIntegrator::_integrateGlobally() const static_assert(std::is_convertible_v<DataType, ValueType>); - return std::make_shared< - DiscreteFunctionP0<Dimension, ValueType>>(mesh, - IntegrateCellValue<ValueType(TinyVector<Dimension>)>::template integrate< - MeshType>(m_function_id, *m_quadrature_descriptor, *mesh)); + return DiscreteFunctionP0<Dimension, + ValueType>(mesh, IntegrateCellValue<ValueType(TinyVector<Dimension>)>::template integrate< + MeshType>(m_function_id, *m_quadrature_descriptor, *mesh)); } template <size_t Dimension, typename DataType, typename ValueType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionIntegrator::_integrate() const { if (m_zone_list.size() == 0) { @@ -93,7 +93,7 @@ DiscreteFunctionIntegrator::_integrate() const } template <size_t Dimension> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionIntegrator::_integrate() const { const auto& function_descriptor = m_function_id.descriptor(); @@ -168,10 +168,9 @@ DiscreteFunctionIntegrator::_integrate() const } } -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionIntegrator::integrate() const { - std::shared_ptr<IDiscreteFunction> discrete_function; switch (m_mesh->dimension()) { case 1: { return this->_integrate<1>(); diff --git a/src/scheme/DiscreteFunctionIntegrator.hpp b/src/scheme/DiscreteFunctionIntegrator.hpp index 21a461d54561d67f1f745d3257ec76ee514d264a..e21beabf704b6ed1a7cd3ef4277f751036d274da 100644 --- a/src/scheme/DiscreteFunctionIntegrator.hpp +++ b/src/scheme/DiscreteFunctionIntegrator.hpp @@ -5,10 +5,11 @@ #include <language/utils/FunctionSymbolId.hpp> #include <mesh/IMesh.hpp> #include <mesh/IZoneDescriptor.hpp> -#include <scheme/IDiscreteFunction.hpp> #include <memory> +class DiscreteFunctionVariant; + class DiscreteFunctionIntegrator { private: @@ -18,19 +19,19 @@ class DiscreteFunctionIntegrator const FunctionSymbolId m_function_id; template <size_t Dimension, typename DataType, typename ValueType = DataType> - std::shared_ptr<IDiscreteFunction> _integrateOnZoneList() const; + DiscreteFunctionVariant _integrateOnZoneList() const; template <size_t Dimension, typename DataType, typename ValueType = DataType> - std::shared_ptr<IDiscreteFunction> _integrateGlobally() const; + DiscreteFunctionVariant _integrateGlobally() const; template <size_t Dimension, typename DataType, typename ValueType = DataType> - std::shared_ptr<IDiscreteFunction> _integrate() const; + DiscreteFunctionVariant _integrate() const; template <size_t Dimension> - std::shared_ptr<IDiscreteFunction> _integrate() const; + DiscreteFunctionVariant _integrate() const; public: - std::shared_ptr<IDiscreteFunction> integrate() const; + DiscreteFunctionVariant integrate() const; DiscreteFunctionIntegrator(const std::shared_ptr<const IMesh>& mesh, const std::shared_ptr<const IQuadratureDescriptor>& quadrature_descriptor, diff --git a/src/scheme/DiscreteFunctionInterpoler.cpp b/src/scheme/DiscreteFunctionInterpoler.cpp index e19073f1e93bd70d649f66f7ca0bd2f49ef8a102..c570e67e5ae9b417a60096e5ccb34a025e7a94a4 100644 --- a/src/scheme/DiscreteFunctionInterpoler.cpp +++ b/src/scheme/DiscreteFunctionInterpoler.cpp @@ -3,10 +3,11 @@ #include <language/utils/InterpolateItemValue.hpp> #include <mesh/MeshCellZone.hpp> #include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <utils/Exceptions.hpp> template <size_t Dimension, typename DataType, typename ValueType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionInterpoler::_interpolateOnZoneList() const { static_assert(std::is_convertible_v<DataType, ValueType>); @@ -61,11 +62,11 @@ DiscreteFunctionInterpoler::_interpolateOnZoneList() const parallel_for( zone_cell_list.size(), PUGS_LAMBDA(const size_t i_cell) { cell_value[zone_cell_list[i_cell]] = array[i_cell]; }); - return std::make_shared<DiscreteFunctionP0<Dimension, ValueType>>(p_mesh, cell_value); + return DiscreteFunctionP0<Dimension, ValueType>(p_mesh, cell_value); } template <size_t Dimension, typename DataType, typename ValueType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionInterpoler::_interpolateGlobally() const { Assert(m_zone_list.size() == 0, "invalid call when zones are defined"); @@ -75,10 +76,9 @@ DiscreteFunctionInterpoler::_interpolateGlobally() const MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*p_mesh); if constexpr (std::is_same_v<DataType, ValueType>) { - return std::make_shared< - DiscreteFunctionP0<Dimension, ValueType>>(p_mesh, - InterpolateItemValue<DataType(TinyVector<Dimension>)>:: - template interpolate<ItemType::cell>(m_function_id, mesh_data.xj())); + return DiscreteFunctionP0<Dimension, ValueType>(p_mesh, InterpolateItemValue<DataType(TinyVector<Dimension>)>:: + template interpolate<ItemType::cell>(m_function_id, + mesh_data.xj())); } else { static_assert(std::is_convertible_v<DataType, ValueType>); @@ -91,12 +91,12 @@ DiscreteFunctionInterpoler::_interpolateGlobally() const parallel_for( p_mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { cell_value[cell_id] = cell_data[cell_id]; }); - return std::make_shared<DiscreteFunctionP0<Dimension, ValueType>>(p_mesh, cell_value); + return DiscreteFunctionP0<Dimension, ValueType>(p_mesh, cell_value); } } template <size_t Dimension, typename DataType, typename ValueType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionInterpoler::_interpolate() const { if (m_zone_list.size() == 0) { @@ -107,7 +107,7 @@ DiscreteFunctionInterpoler::_interpolate() const } template <size_t Dimension> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionInterpoler::_interpolate() const { const auto& function_descriptor = m_function_id.descriptor(); @@ -182,7 +182,7 @@ DiscreteFunctionInterpoler::_interpolate() const } } -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionInterpoler::interpolate() const { switch (m_mesh->dimension()) { diff --git a/src/scheme/DiscreteFunctionInterpoler.hpp b/src/scheme/DiscreteFunctionInterpoler.hpp index 295c2fd9a540269bf484f485716131b1346964e1..0f436d43cf2c347fc437e05016d798bc28aeed77 100644 --- a/src/scheme/DiscreteFunctionInterpoler.hpp +++ b/src/scheme/DiscreteFunctionInterpoler.hpp @@ -4,9 +4,10 @@ #include <language/utils/FunctionSymbolId.hpp> #include <mesh/IMesh.hpp> #include <mesh/IZoneDescriptor.hpp> -#include <scheme/IDiscreteFunction.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> +class DiscreteFunctionVariant; + #include <memory> class DiscreteFunctionInterpoler @@ -18,19 +19,19 @@ class DiscreteFunctionInterpoler const FunctionSymbolId m_function_id; template <size_t Dimension, typename DataType, typename ValueType = DataType> - std::shared_ptr<IDiscreteFunction> _interpolateOnZoneList() const; + DiscreteFunctionVariant _interpolateOnZoneList() const; template <size_t Dimension, typename DataType, typename ValueType = DataType> - std::shared_ptr<IDiscreteFunction> _interpolateGlobally() const; + DiscreteFunctionVariant _interpolateGlobally() const; template <size_t Dimension, typename DataType, typename ValueType = DataType> - std::shared_ptr<IDiscreteFunction> _interpolate() const; + DiscreteFunctionVariant _interpolate() const; template <size_t Dimension> - std::shared_ptr<IDiscreteFunction> _interpolate() const; + DiscreteFunctionVariant _interpolate() const; public: - std::shared_ptr<IDiscreteFunction> interpolate() const; + DiscreteFunctionVariant interpolate() const; DiscreteFunctionInterpoler(const std::shared_ptr<const IMesh>& mesh, const std::shared_ptr<const IDiscreteFunctionDescriptor>& discrete_function_descriptor, diff --git a/src/scheme/DiscreteFunctionP0.hpp b/src/scheme/DiscreteFunctionP0.hpp index d1bd72c3394346db10898cd83f1c609974f17697..1fb2ce14cee3f42e6c27c262e3ba6deefb5b555d 100644 --- a/src/scheme/DiscreteFunctionP0.hpp +++ b/src/scheme/DiscreteFunctionP0.hpp @@ -1,7 +1,7 @@ #ifndef DISCRETE_FUNCTION_P0_HPP #define DISCRETE_FUNCTION_P0_HPP -#include <scheme/IDiscreteFunction.hpp> +#include <language/utils/ASTNodeDataTypeTraits.hpp> #include <mesh/Connectivity.hpp> #include <mesh/ItemValueUtils.hpp> @@ -11,14 +11,12 @@ #include <scheme/DiscreteFunctionDescriptorP0.hpp> template <size_t Dimension, typename DataType> -class DiscreteFunctionP0 : public IDiscreteFunction +class DiscreteFunctionP0 { public: using data_type = DataType; using MeshType = Mesh<Connectivity<Dimension>>; - 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>>; @@ -31,9 +29,9 @@ class DiscreteFunctionP0 : public IDiscreteFunction public: PUGS_INLINE ASTNodeDataType - dataType() const final + dataType() const { - return ast_node_data_type_from<DataType>; + return ast_node_data_type_from<std::remove_const_t<DataType>>; } PUGS_INLINE @@ -52,7 +50,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction PUGS_INLINE const IDiscreteFunctionDescriptor& - descriptor() const final + descriptor() const { return m_discrete_function_descriptor; } @@ -450,7 +448,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> atan2(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) { static_assert(std::is_arithmetic_v<DataType>); @@ -463,7 +461,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> atan2(const double a, const DiscreteFunctionP0& f) { static_assert(std::is_arithmetic_v<DataType>); @@ -475,7 +473,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> atan2(const DiscreteFunctionP0& f, const double a) { static_assert(std::is_arithmetic_v<DataType>); @@ -487,7 +485,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> pow(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) { static_assert(std::is_arithmetic_v<DataType>); @@ -500,7 +498,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> pow(const double a, const DiscreteFunctionP0& f) { static_assert(std::is_arithmetic_v<DataType>); @@ -512,7 +510,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> pow(const DiscreteFunctionP0& f, const double a) { static_assert(std::is_arithmetic_v<DataType>); @@ -527,7 +525,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> det(const DiscreteFunctionP0& A) { - static_assert(is_tiny_matrix_v<DataType>); + static_assert(is_tiny_matrix_v<std::decay_t<DataType>>); Assert(A.m_cell_values.isBuilt()); DiscreteFunctionP0<Dimension, double> result{A.m_mesh}; parallel_for( @@ -539,7 +537,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> trace(const DiscreteFunctionP0& A) { - static_assert(is_tiny_matrix_v<DataType>); + static_assert(is_tiny_matrix_v<std::decay_t<DataType>>); Assert(A.m_cell_values.isBuilt()); DiscreteFunctionP0<Dimension, double> result{A.m_mesh}; parallel_for( @@ -548,26 +546,26 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> inverse(const DiscreteFunctionP0& A) { - static_assert(is_tiny_matrix_v<DataType>); + static_assert(is_tiny_matrix_v<std::decay_t<DataType>>); static_assert(DataType::NumberOfRows == DataType::NumberOfColumns, "cannot compute inverse of non square matrices"); Assert(A.m_cell_values.isBuilt()); - DiscreteFunctionP0 result{A.m_mesh}; + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{A.m_mesh}; parallel_for( A.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = inverse(A[cell_id]); }); return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> transpose(const DiscreteFunctionP0& A) { - static_assert(is_tiny_matrix_v<DataType>); + static_assert(is_tiny_matrix_v<std::decay_t<DataType>>); static_assert(DataType::NumberOfRows == DataType::NumberOfColumns, "cannot compute inverse of non square matrices"); Assert(A.m_cell_values.isBuilt()); - DiscreteFunctionP0 result{A.m_mesh}; + DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> result{A.m_mesh}; parallel_for( A.m_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { result[cell_id] = transpose(A[cell_id]); }); @@ -577,7 +575,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> dot(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) { - static_assert(is_tiny_vector_v<DataType>); + static_assert(is_tiny_vector_v<std::decay_t<DataType>>); Assert(f.m_cell_values.isBuilt() and g.m_cell_values.isBuilt()); Assert(f.m_mesh == g.m_mesh); DiscreteFunctionP0<Dimension, double> result{f.m_mesh}; @@ -590,7 +588,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> dot(const DiscreteFunctionP0& f, const DataType& a) { - static_assert(is_tiny_vector_v<DataType>); + static_assert(is_tiny_vector_v<std::decay_t<DataType>>); Assert(f.m_cell_values.isBuilt()); DiscreteFunctionP0<Dimension, double> result{f.m_mesh}; parallel_for( @@ -602,7 +600,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction PUGS_INLINE friend DiscreteFunctionP0<Dimension, double> dot(const DataType& a, const DiscreteFunctionP0& f) { - static_assert(is_tiny_vector_v<DataType>); + static_assert(is_tiny_vector_v<std::decay_t<DataType>>); Assert(f.m_cell_values.isBuilt()); DiscreteFunctionP0<Dimension, double> result{f.m_mesh}; parallel_for( @@ -620,7 +618,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return min(f.m_cell_values); } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> min(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) { static_assert(std::is_arithmetic_v<DataType>); @@ -633,7 +631,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> min(const double a, const DiscreteFunctionP0& f) { static_assert(std::is_arithmetic_v<DataType>); @@ -645,7 +643,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> min(const DiscreteFunctionP0& f, const double a) { static_assert(std::is_arithmetic_v<DataType>); @@ -666,7 +664,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return max(f.m_cell_values); } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> max(const DiscreteFunctionP0& f, const DiscreteFunctionP0& g) { static_assert(std::is_arithmetic_v<DataType>); @@ -679,7 +677,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> max(const double a, const DiscreteFunctionP0& f) { static_assert(std::is_arithmetic_v<DataType>); @@ -691,7 +689,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction return result; } - PUGS_INLINE friend DiscreteFunctionP0 + PUGS_INLINE friend DiscreteFunctionP0<Dimension, std::remove_const_t<DataType>> max(const DiscreteFunctionP0& f, const double a) { static_assert(std::is_arithmetic_v<DataType>); @@ -720,16 +718,23 @@ class DiscreteFunctionP0 : public IDiscreteFunction public: PUGS_INLINE - operator data_type() + operator std::decay_t<data_type>() { - data_type reduced_value; + std::decay_t<data_type> reduced_value; + if constexpr (std::is_arithmetic_v<std::decay_t<data_type>>) { + reduced_value = 0; + } else { + static_assert(is_tiny_vector_v<std::decay_t<data_type>> or is_tiny_matrix_v<std::decay_t<data_type>>, + "invalid data type"); + reduced_value = zero; + } parallel_reduce(m_cell_volume.numberOfItems(), *this, reduced_value); return reduced_value; } PUGS_INLINE void - operator()(const CellId& cell_id, data_type& data) const + operator()(const CellId& cell_id, std::decay_t<data_type>& data) const { if (m_cell_is_owned[cell_id]) { data += m_cell_volume[cell_id] * m_function[cell_id]; @@ -738,19 +743,20 @@ class DiscreteFunctionP0 : public IDiscreteFunction PUGS_INLINE void - join(volatile data_type& dst, const volatile data_type& src) const + join(volatile std::decay_t<data_type>& dst, const volatile std::decay_t<data_type>& src) const { dst += src; } PUGS_INLINE void - init(data_type& value) const + init(std::decay_t<data_type>& value) const { if constexpr (std::is_arithmetic_v<data_type>) { value = 0; } else { - static_assert(is_tiny_vector_v<data_type> or is_tiny_matrix_v<data_type>, "invalid data type"); + static_assert(is_tiny_vector_v<std::decay_t<data_type>> or is_tiny_matrix_v<std::decay_t<data_type>>, + "invalid data type"); value = zero; } } diff --git a/src/scheme/DiscreteFunctionP0Vector.hpp b/src/scheme/DiscreteFunctionP0Vector.hpp index 97593e1b3c5a9a599fc0c17f7edca7a839f2b5ef..7bd833f344ffd29f6f47f6fa0d0bff13a2407339 100644 --- a/src/scheme/DiscreteFunctionP0Vector.hpp +++ b/src/scheme/DiscreteFunctionP0Vector.hpp @@ -1,8 +1,6 @@ #ifndef DISCRETE_FUNCTION_P0_VECTOR_HPP #define DISCRETE_FUNCTION_P0_VECTOR_HPP -#include <scheme/IDiscreteFunction.hpp> - #include <algebra/Vector.hpp> #include <mesh/Connectivity.hpp> #include <mesh/ItemArray.hpp> @@ -14,14 +12,12 @@ #include <utils/Exceptions.hpp> template <size_t Dimension, typename DataType> -class DiscreteFunctionP0Vector : public IDiscreteFunction +class DiscreteFunctionP0Vector { public: using data_type = DataType; using MeshType = Mesh<Connectivity<Dimension>>; - 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>>; @@ -36,9 +32,9 @@ class DiscreteFunctionP0Vector : public IDiscreteFunction public: PUGS_INLINE ASTNodeDataType - dataType() const final + dataType() const { - return ast_node_data_type_from<data_type>; + return ast_node_data_type_from<std::remove_const_t<data_type>>; } PUGS_INLINE @@ -64,7 +60,7 @@ class DiscreteFunctionP0Vector : public IDiscreteFunction PUGS_INLINE const IDiscreteFunctionDescriptor& - descriptor() const final + descriptor() const { return m_discrete_function_descriptor; } diff --git a/src/scheme/DiscreteFunctionUtils.cpp b/src/scheme/DiscreteFunctionUtils.cpp index fe861c0868b6bf620696cba09d8ac72bcf6aa948..ba2416a9ab08e03e75bb0824f32930c105cd366c 100644 --- a/src/scheme/DiscreteFunctionUtils.cpp +++ b/src/scheme/DiscreteFunctionUtils.cpp @@ -4,128 +4,106 @@ #include <mesh/IMesh.hpp> #include <mesh/Mesh.hpp> #include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <utils/Stringify.hpp> -template <size_t Dimension, typename DataType> -std::shared_ptr<const IDiscreteFunction> -shallowCopy(const std::shared_ptr<const Mesh<Connectivity<Dimension>>>& mesh, - const std::shared_ptr<const DiscreteFunctionP0<Dimension, DataType>>& discrete_function) +std::shared_ptr<const IMesh> +getCommonMesh(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) { - Assert(mesh->shared_connectivity() == - dynamic_cast<const Mesh<Connectivity<Dimension>>&>(*discrete_function->mesh()).shared_connectivity(), - "connectivities should be the same"); + std::shared_ptr<const IMesh> i_mesh; + bool is_same_mesh = true; + for (const auto& discrete_function_variant : discrete_function_variant_list) { + std::visit( + [&](auto&& discrete_function) { + if (not i_mesh.use_count()) { + i_mesh = discrete_function.mesh(); + } else { + if (i_mesh != discrete_function.mesh()) { + is_same_mesh = false; + } + } + }, + discrete_function_variant->discreteFunction()); + } + if (not is_same_mesh) { + i_mesh.reset(); + } + return i_mesh; +} + +bool +hasSameMesh(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) +{ + std::shared_ptr<const IMesh> i_mesh; + bool is_same_mesh = true; + for (const auto& discrete_function_variant : discrete_function_variant_list) { + std::visit( + [&](auto&& discrete_function) { + if (not i_mesh.use_count()) { + i_mesh = discrete_function.mesh(); + } else { + if (i_mesh != discrete_function.mesh()) { + is_same_mesh = false; + } + } + }, + discrete_function_variant->discreteFunction()); + } - return std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh, discrete_function->cellValues()); + return is_same_mesh; } -template <size_t Dimension> -std::shared_ptr<const IDiscreteFunction> -shallowCopy(const std::shared_ptr<const Mesh<Connectivity<Dimension>>>& mesh, - const std::shared_ptr<const IDiscreteFunction>& discrete_function) +template <typename MeshType, typename DiscreteFunctionT> +std::shared_ptr<const DiscreteFunctionVariant> +shallowCopy(const std::shared_ptr<const MeshType>& mesh, const DiscreteFunctionT& f) { - const std::shared_ptr function_mesh = - std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(discrete_function->mesh()); + const std::shared_ptr function_mesh = std::dynamic_pointer_cast<const MeshType>(f.mesh()); if (mesh->shared_connectivity() != function_mesh->shared_connectivity()) { throw NormalError("cannot shallow copy when connectivity changes"); } - switch (discrete_function->descriptor().type()) { - case DiscreteFunctionType::P0: { - switch (discrete_function->dataType()) { - case ASTNodeDataType::double_t: { - return shallowCopy(mesh, - std::dynamic_pointer_cast<const DiscreteFunctionP0<Dimension, double>>(discrete_function)); + if constexpr (std::is_same_v<MeshType, typename DiscreteFunctionT::MeshType>) { + if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) { + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionT(mesh, f.cellValues())); + } else if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionT>) { + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionT(mesh, f.cellArrays())); + } else { + throw UnexpectedError("invalid discrete function type"); } - case ASTNodeDataType::vector_t: { - switch (discrete_function->dataType().dimension()) { - case 1: { - return shallowCopy(mesh, std::dynamic_pointer_cast<const DiscreteFunctionP0<Dimension, TinyVector<1>>>( - discrete_function)); - } - case 2: { - return shallowCopy(mesh, std::dynamic_pointer_cast<const DiscreteFunctionP0<Dimension, TinyVector<2>>>( - discrete_function)); - } - case 3: { - return shallowCopy(mesh, std::dynamic_pointer_cast<const DiscreteFunctionP0<Dimension, TinyVector<3>>>( - discrete_function)); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid data vector dimension: " + stringify(discrete_function->dataType().dimension())); - } - // LCOV_EXCL_STOP - } - } - case ASTNodeDataType::matrix_t: { - if (discrete_function->dataType().numberOfRows() != discrete_function->dataType().numberOfColumns()) { - // LCOV_EXCL_START - throw UnexpectedError( - "invalid data matrix dimensions: " + stringify(discrete_function->dataType().numberOfRows()) + "x" + - stringify(discrete_function->dataType().numberOfColumns())); - // LCOV_EXCL_STOP + } else { + throw UnexpectedError("invalid mesh types"); + } +} + +std::shared_ptr<const DiscreteFunctionVariant> +shallowCopy(const std::shared_ptr<const IMesh>& mesh, + const std::shared_ptr<const DiscreteFunctionVariant>& discrete_function_variant) +{ + return std::visit( + [&](auto&& f) { + if (mesh == f.mesh()) { + return discrete_function_variant; + } else if (mesh->dimension() != f.mesh()->dimension()) { + throw NormalError("incompatible mesh dimensions"); } - switch (discrete_function->dataType().numberOfRows()) { + + switch (mesh->dimension()) { case 1: { - return shallowCopy(mesh, std::dynamic_pointer_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>( - discrete_function)); + return shallowCopy(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), f); } case 2: { - return shallowCopy(mesh, std::dynamic_pointer_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>( - discrete_function)); + return shallowCopy(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(mesh), f); } case 3: { - return shallowCopy(mesh, std::dynamic_pointer_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>( - discrete_function)); + return shallowCopy(std::dynamic_pointer_cast<const Mesh<Connectivity<3>>>(mesh), f); } // LCOV_EXCL_START default: { - throw UnexpectedError( - "invalid data matrix dimensions: " + stringify(discrete_function->dataType().numberOfRows()) + "x" + - stringify(discrete_function->dataType().numberOfColumns())); + throw UnexpectedError("invalid mesh dimension"); } // LCOV_EXCL_STOP } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid kind of P0 function: invalid data type"); - } - // LCOV_EXCL_STOP - } - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid discretization type"); - } - // LCOV_EXCL_STOP - } -} - -std::shared_ptr<const IDiscreteFunction> -shallowCopy(const std::shared_ptr<const IMesh>& mesh, const std::shared_ptr<const IDiscreteFunction>& discrete_function) -{ - if (mesh == discrete_function->mesh()) { - return discrete_function; - } else if (mesh->dimension() != discrete_function->mesh()->dimension()) { - throw NormalError("incompatible mesh dimensions"); - } - - switch (mesh->dimension()) { - case 1: { - return shallowCopy(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), discrete_function); - } - case 2: { - return shallowCopy(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(mesh), discrete_function); - } - case 3: { - return shallowCopy(std::dynamic_pointer_cast<const Mesh<Connectivity<3>>>(mesh), discrete_function); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid mesh dimension"); - } - // LCOV_EXCL_STOP - } + }, + discrete_function_variant->discreteFunction()); } diff --git a/src/scheme/DiscreteFunctionUtils.hpp b/src/scheme/DiscreteFunctionUtils.hpp index e01437f2b0e0d1c7dc9468bea6f63aa0b14aae74..91acbccb7c1444e2adfbc55333b1ee2a0e89d3b9 100644 --- a/src/scheme/DiscreteFunctionUtils.hpp +++ b/src/scheme/DiscreteFunctionUtils.hpp @@ -2,42 +2,32 @@ #define DISCRETE_FUNCTION_UTILS_HPP #include <scheme/DiscreteFunctionType.hpp> -#include <scheme/IDiscreteFunction.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> #include <vector> PUGS_INLINE bool -checkDiscretizationType(const std::vector<std::shared_ptr<const IDiscreteFunction>>& discrete_function_list, +checkDiscretizationType(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_list, const DiscreteFunctionType& discrete_function_type) { - for (const auto& discrete_function : discrete_function_list) { - if (discrete_function->descriptor().type() != discrete_function_type) { + for (const auto& discrete_function_variant : discrete_function_list) { + if (not std::visit([&](auto&& f) { return f.descriptor().type() == discrete_function_type; }, + discrete_function_variant->discreteFunction())) { return false; } } return true; } -PUGS_INLINE -std::shared_ptr<const IMesh> -getCommonMesh(const std::vector<std::shared_ptr<const IDiscreteFunction>>& discrete_function_list) -{ - std::shared_ptr<const IMesh> i_mesh; - for (const auto& discrete_function : discrete_function_list) { - if (not i_mesh.use_count()) { - i_mesh = discrete_function->mesh(); - } else { - if (i_mesh != discrete_function->mesh()) { - return {}; - } - } - } - return i_mesh; -} +std::shared_ptr<const IMesh> getCommonMesh( + const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list); + +bool hasSameMesh(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list); -std::shared_ptr<const IDiscreteFunction> shallowCopy(const std::shared_ptr<const IMesh>& mesh, - const std::shared_ptr<const IDiscreteFunction>& discrete_function); +std::shared_ptr<const DiscreteFunctionVariant> shallowCopy( + const std::shared_ptr<const IMesh>& mesh, + const std::shared_ptr<const DiscreteFunctionVariant>& discrete_function); #endif // DISCRETE_FUNCTION_UTILS_HPP diff --git a/src/scheme/DiscreteFunctionVariant.hpp b/src/scheme/DiscreteFunctionVariant.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6feb86bcbc564898ae7801a0f3ca2bab8d370097 --- /dev/null +++ b/src/scheme/DiscreteFunctionVariant.hpp @@ -0,0 +1,105 @@ +#ifndef DISCRETE_FUNCTION_VARIANT_HPP +#define DISCRETE_FUNCTION_VARIANT_HPP + +#include <algebra/TinyMatrix.hpp> +#include <algebra/TinyVector.hpp> +#include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionP0Vector.hpp> +#include <utils/Demangle.hpp> +#include <utils/Exceptions.hpp> + +class DiscreteFunctionVariant +{ + private: + using Variant = std::variant<DiscreteFunctionP0<1, const double>, + DiscreteFunctionP0<1, const TinyVector<1>>, + DiscreteFunctionP0<1, const TinyVector<2>>, + DiscreteFunctionP0<1, const TinyVector<3>>, + DiscreteFunctionP0<1, const TinyMatrix<1>>, + DiscreteFunctionP0<1, const TinyMatrix<2>>, + DiscreteFunctionP0<1, const TinyMatrix<3>>, + + DiscreteFunctionP0<2, const double>, + DiscreteFunctionP0<2, const TinyVector<1>>, + DiscreteFunctionP0<2, const TinyVector<2>>, + DiscreteFunctionP0<2, const TinyVector<3>>, + DiscreteFunctionP0<2, const TinyMatrix<1>>, + DiscreteFunctionP0<2, const TinyMatrix<2>>, + DiscreteFunctionP0<2, const TinyMatrix<3>>, + + DiscreteFunctionP0<3, const double>, + DiscreteFunctionP0<3, const TinyVector<1>>, + DiscreteFunctionP0<3, const TinyVector<2>>, + DiscreteFunctionP0<3, const TinyVector<3>>, + DiscreteFunctionP0<3, const TinyMatrix<1>>, + DiscreteFunctionP0<3, const TinyMatrix<2>>, + DiscreteFunctionP0<3, const TinyMatrix<3>>, + + DiscreteFunctionP0Vector<1, const double>, + DiscreteFunctionP0Vector<2, const double>, + DiscreteFunctionP0Vector<3, const double>>; + + Variant m_discrete_function; + + public: + PUGS_INLINE + const Variant& + discreteFunction() const + { + return m_discrete_function; + } + + template <typename DiscreteFunctionT> + PUGS_INLINE auto + get() const + { + static_assert(is_discrete_function_v<DiscreteFunctionT>, "invalid template argument"); + using DataType = typename DiscreteFunctionT::data_type; + static_assert(std::is_const_v<DataType>, "data type of extracted discrete function must be const"); + + if (not std::holds_alternative<DiscreteFunctionT>(this->m_discrete_function)) { + std::ostringstream error_msg; + error_msg << "invalid discrete function type\n"; + error_msg << "- required " << rang::fgB::red << demangle<DiscreteFunctionT>() << rang::fg::reset << '\n'; + error_msg << "- contains " << rang::fgB::yellow + << std::visit([](auto&& f) -> std::string { return demangle<decltype(f)>(); }, + this->m_discrete_function) + << rang::fg::reset; + throw NormalError(error_msg.str()); + } + return std::get<DiscreteFunctionT>(this->discreteFunction()); + } + + template <size_t Dimension, typename DataType> + DiscreteFunctionVariant(const DiscreteFunctionP0<Dimension, DataType>& discrete_function) + : m_discrete_function{DiscreteFunctionP0<Dimension, const DataType>{discrete_function}} + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, double> or // + std::is_same_v<std::remove_const_t<DataType>, TinyVector<1, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyVector<2, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyVector<3, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<1, 1, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<2, 2, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<3, 3, double>>, + "DiscreteFunctionP0 with this DataType is not allowed in variant"); + } + + template <size_t Dimension, typename DataType> + DiscreteFunctionVariant(const DiscreteFunctionP0Vector<Dimension, DataType>& discrete_function) + : m_discrete_function{DiscreteFunctionP0Vector<Dimension, const DataType>{discrete_function}} + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, double>, + "DiscreteFunctionP0Vector with this DataType is not allowed in variant"); + } + + DiscreteFunctionVariant& operator=(DiscreteFunctionVariant&&) = default; + DiscreteFunctionVariant& operator=(const DiscreteFunctionVariant&) = default; + + DiscreteFunctionVariant(const DiscreteFunctionVariant&) = default; + DiscreteFunctionVariant(DiscreteFunctionVariant&&) = default; + + DiscreteFunctionVariant() = delete; + ~DiscreteFunctionVariant() = default; +}; + +#endif // DISCRETE_FUNCTION_VARIANT_HPP diff --git a/src/scheme/DiscreteFunctionVectorIntegrator.cpp b/src/scheme/DiscreteFunctionVectorIntegrator.cpp index cfa65b1787090a06c6de0ac6bf774b3771a4a1eb..80b9e711ebfe9e45297e1a01a1d63ad37da72914 100644 --- a/src/scheme/DiscreteFunctionVectorIntegrator.cpp +++ b/src/scheme/DiscreteFunctionVectorIntegrator.cpp @@ -3,10 +3,11 @@ #include <language/utils/IntegrateCellArray.hpp> #include <mesh/MeshCellZone.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <utils/Exceptions.hpp> template <size_t Dimension, typename DataType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorIntegrator::_integrateOnZoneList() const { Assert(m_zone_list.size() > 0, "no zone list provided"); @@ -62,25 +63,24 @@ DiscreteFunctionVectorIntegrator::_integrateOnZoneList() const } }); - return std::make_shared<DiscreteFunctionP0Vector<Dimension, DataType>>(p_mesh, cell_array); + return DiscreteFunctionP0Vector<Dimension, DataType>(p_mesh, cell_array); } template <size_t Dimension, typename DataType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorIntegrator::_integrateGlobally() const { Assert(m_zone_list.size() == 0, "invalid call when zones are defined"); std::shared_ptr mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(m_mesh); - return std::make_shared< - DiscreteFunctionP0Vector<Dimension, DataType>>(mesh, IntegrateCellArray<DataType(TinyVector<Dimension>)>:: - template integrate(m_function_id_list, - *m_quadrature_descriptor, *mesh)); + return DiscreteFunctionP0Vector<Dimension, DataType>(mesh, IntegrateCellArray<DataType(TinyVector<Dimension>)>:: + template integrate(m_function_id_list, + *m_quadrature_descriptor, *mesh)); } template <size_t Dimension, typename DataType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorIntegrator::_integrate() const { if (m_zone_list.size() == 0) { @@ -91,7 +91,7 @@ DiscreteFunctionVectorIntegrator::_integrate() const } template <size_t Dimension> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorIntegrator::_integrate() const { for (const auto& function_id : m_function_id_list) { @@ -117,7 +117,7 @@ DiscreteFunctionVectorIntegrator::_integrate() const return this->_integrate<Dimension, double>(); } -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorIntegrator::integrate() const { if (m_discrete_function_descriptor->type() != DiscreteFunctionType::P0Vector) { diff --git a/src/scheme/DiscreteFunctionVectorIntegrator.hpp b/src/scheme/DiscreteFunctionVectorIntegrator.hpp index 55f5fe3572cbb237e28b9bf86ff7bda19db20a98..44b192bc985888325a691db1433737d5c5a03ca0 100644 --- a/src/scheme/DiscreteFunctionVectorIntegrator.hpp +++ b/src/scheme/DiscreteFunctionVectorIntegrator.hpp @@ -5,12 +5,13 @@ #include <language/utils/FunctionSymbolId.hpp> #include <mesh/IMesh.hpp> #include <mesh/IZoneDescriptor.hpp> -#include <scheme/IDiscreteFunction.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> #include <memory> #include <vector> +class DiscreteFunctionVariant; + class DiscreteFunctionVectorIntegrator { private: @@ -21,19 +22,19 @@ class DiscreteFunctionVectorIntegrator const std::vector<FunctionSymbolId> m_function_id_list; template <size_t Dimension, typename DataType> - std::shared_ptr<IDiscreteFunction> _integrateOnZoneList() const; + DiscreteFunctionVariant _integrateOnZoneList() const; template <size_t Dimension, typename DataType> - std::shared_ptr<IDiscreteFunction> _integrateGlobally() const; + DiscreteFunctionVariant _integrateGlobally() const; template <size_t Dimension, typename DataType> - std::shared_ptr<IDiscreteFunction> _integrate() const; + DiscreteFunctionVariant _integrate() const; template <size_t Dimension> - std::shared_ptr<IDiscreteFunction> _integrate() const; + DiscreteFunctionVariant _integrate() const; public: - std::shared_ptr<IDiscreteFunction> integrate() const; + DiscreteFunctionVariant integrate() const; DiscreteFunctionVectorIntegrator( const std::shared_ptr<const IMesh>& mesh, diff --git a/src/scheme/DiscreteFunctionVectorInterpoler.cpp b/src/scheme/DiscreteFunctionVectorInterpoler.cpp index 128c735e4ae8e158f3dc42bf3d5ed47b17ac3fb5..b416400c65a719614be50a53f167a44d859c9497 100644 --- a/src/scheme/DiscreteFunctionVectorInterpoler.cpp +++ b/src/scheme/DiscreteFunctionVectorInterpoler.cpp @@ -3,10 +3,11 @@ #include <language/utils/InterpolateItemArray.hpp> #include <mesh/MeshCellZone.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <utils/Exceptions.hpp> template <size_t Dimension, typename DataType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorInterpoler::_interpolateOnZoneList() const { Assert(m_zone_list.size() > 0, "no zone list provided"); @@ -60,11 +61,11 @@ DiscreteFunctionVectorInterpoler::_interpolateOnZoneList() const } }); - return std::make_shared<DiscreteFunctionP0Vector<Dimension, DataType>>(p_mesh, cell_array); + return DiscreteFunctionP0Vector<Dimension, DataType>(p_mesh, cell_array); } template <size_t Dimension, typename DataType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorInterpoler::_interpolateGlobally() const { Assert(m_zone_list.size() == 0, "invalid call when zones are defined"); @@ -74,14 +75,14 @@ DiscreteFunctionVectorInterpoler::_interpolateGlobally() const using MeshDataType = MeshData<Dimension>; MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*p_mesh); - return std::make_shared< - DiscreteFunctionP0Vector<Dimension, DataType>>(p_mesh, InterpolateItemArray<DataType(TinyVector<Dimension>)>:: - template interpolate<ItemType::cell>(m_function_id_list, - mesh_data.xj())); + return DiscreteFunctionP0Vector<Dimension, DataType>(p_mesh, + InterpolateItemArray<DataType(TinyVector<Dimension>)>:: + template interpolate<ItemType::cell>(m_function_id_list, + mesh_data.xj())); } template <size_t Dimension, typename DataType> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorInterpoler::_interpolate() const { if (m_zone_list.size() == 0) { @@ -92,7 +93,7 @@ DiscreteFunctionVectorInterpoler::_interpolate() const } template <size_t Dimension> -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorInterpoler::_interpolate() const { for (const auto& function_id : m_function_id_list) { @@ -118,7 +119,7 @@ DiscreteFunctionVectorInterpoler::_interpolate() const return this->_interpolate<Dimension, double>(); } -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionVectorInterpoler::interpolate() const { if (m_discrete_function_descriptor->type() != DiscreteFunctionType::P0Vector) { diff --git a/src/scheme/DiscreteFunctionVectorInterpoler.hpp b/src/scheme/DiscreteFunctionVectorInterpoler.hpp index 4bd917264fcfdb8992d6096db824bc17951c2603..8cec9d09e7f9ce0fd03e98dbdaed0edf6afee900 100644 --- a/src/scheme/DiscreteFunctionVectorInterpoler.hpp +++ b/src/scheme/DiscreteFunctionVectorInterpoler.hpp @@ -4,9 +4,10 @@ #include <language/utils/FunctionSymbolId.hpp> #include <mesh/IMesh.hpp> #include <mesh/IZoneDescriptor.hpp> -#include <scheme/IDiscreteFunction.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> +class DiscreteFunctionVariant; + #include <memory> #include <vector> @@ -19,19 +20,19 @@ class DiscreteFunctionVectorInterpoler const std::vector<FunctionSymbolId> m_function_id_list; template <size_t Dimension, typename DataType> - std::shared_ptr<IDiscreteFunction> _interpolateOnZoneList() const; + DiscreteFunctionVariant _interpolateOnZoneList() const; template <size_t Dimension, typename DataType> - std::shared_ptr<IDiscreteFunction> _interpolateGlobally() const; + DiscreteFunctionVariant _interpolateGlobally() const; template <size_t Dimension, typename DataType> - std::shared_ptr<IDiscreteFunction> _interpolate() const; + DiscreteFunctionVariant _interpolate() const; template <size_t Dimension> - std::shared_ptr<IDiscreteFunction> _interpolate() const; + DiscreteFunctionVariant _interpolate() const; public: - std::shared_ptr<IDiscreteFunction> interpolate() const; + DiscreteFunctionVariant interpolate() const; DiscreteFunctionVectorInterpoler( const std::shared_ptr<const IMesh>& mesh, diff --git a/src/scheme/HyperelasticSolver.cpp b/src/scheme/HyperelasticSolver.cpp index 5850ba1c204319c4a3f278343576f25d1456ecc3..2f683fa805aa2741b003acff8cb5f39040dafd29 100644 --- a/src/scheme/HyperelasticSolver.cpp +++ b/src/scheme/HyperelasticSolver.cpp @@ -10,10 +10,10 @@ #include <scheme/DirichletBoundaryConditionDescriptor.hpp> #include <scheme/DiscreteFunctionP0.hpp> #include <scheme/DiscreteFunctionUtils.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/ExternalBoundaryConditionDescriptor.hpp> #include <scheme/FixedBoundaryConditionDescriptor.hpp> #include <scheme/IBoundaryConditionDescriptor.hpp> -#include <scheme/IDiscreteFunction.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> #include <scheme/SymmetryBoundaryConditionDescriptor.hpp> #include <utils/Socket.hpp> @@ -23,7 +23,7 @@ template <size_t Dimension> double -hyperelastic_dt(const DiscreteFunctionP0<Dimension, double>& c) +hyperelastic_dt(const DiscreteFunctionP0<Dimension, const double>& c) { const Mesh<Connectivity<Dimension>>& mesh = dynamic_cast<const Mesh<Connectivity<Dimension>>&>(*c.mesh()); @@ -38,23 +38,19 @@ hyperelastic_dt(const DiscreteFunctionP0<Dimension, double>& c) } double -hyperelastic_dt(const std::shared_ptr<const IDiscreteFunction>& c) +hyperelastic_dt(const std::shared_ptr<const DiscreteFunctionVariant>& c) { - if ((c->descriptor().type() != DiscreteFunctionType::P0) or (c->dataType() != ASTNodeDataType::double_t)) { - throw NormalError("invalid discrete function type"); - } - - std::shared_ptr mesh = c->mesh(); + std::shared_ptr mesh = getCommonMesh({c}); switch (mesh->dimension()) { case 1: { - return hyperelastic_dt(dynamic_cast<const DiscreteFunctionP0<1, double>&>(*c)); + return hyperelastic_dt(c->get<DiscreteFunctionP0<1, const double>>()); } case 2: { - return hyperelastic_dt(dynamic_cast<const DiscreteFunctionP0<2, double>&>(*c)); + return hyperelastic_dt(c->get<DiscreteFunctionP0<2, const double>>()); } case 3: { - return hyperelastic_dt(dynamic_cast<const DiscreteFunctionP0<3, double>&>(*c)); + return hyperelastic_dt(c->get<DiscreteFunctionP0<3, const double>>()); } default: { throw UnexpectedError("invalid mesh dimension"); @@ -72,9 +68,9 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS using MeshType = Mesh<Connectivity<Dimension>>; using MeshDataType = MeshData<Dimension>; - using DiscreteScalarFunction = DiscreteFunctionP0<Dimension, double>; - using DiscreteVectorFunction = DiscreteFunctionP0<Dimension, Rd>; - using DiscreteTensorFunction = DiscreteFunctionP0<Dimension, Rdxd>; + using DiscreteScalarFunction = DiscreteFunctionP0<Dimension, const double>; + using DiscreteVectorFunction = DiscreteFunctionP0<Dimension, const Rd>; + using DiscreteTensorFunction = DiscreteFunctionP0<Dimension, const Rdxd>; class FixedBoundaryCondition; class PressureBoundaryCondition; @@ -399,28 +395,28 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS public: std::tuple<const std::shared_ptr<const ItemValueVariant>, const std::shared_ptr<const SubItemValuePerItemVariant>> compute_fluxes(const SolverType& solver_type, - const std::shared_ptr<const IDiscreteFunction>& i_rho, - const std::shared_ptr<const IDiscreteFunction>& i_aL, - const std::shared_ptr<const IDiscreteFunction>& i_aT, - const std::shared_ptr<const IDiscreteFunction>& i_u, - const std::shared_ptr<const IDiscreteFunction>& i_sigma, + const std::shared_ptr<const DiscreteFunctionVariant>& rho_v, + const std::shared_ptr<const DiscreteFunctionVariant>& aL_v, + const std::shared_ptr<const DiscreteFunctionVariant>& aT_v, + const std::shared_ptr<const DiscreteFunctionVariant>& u_v, + const std::shared_ptr<const DiscreteFunctionVariant>& sigma_v, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const { - std::shared_ptr i_mesh = getCommonMesh({i_rho, i_aL, i_aT, i_u, i_sigma}); + std::shared_ptr i_mesh = getCommonMesh({rho_v, aL_v, aT_v, u_v, sigma_v}); if (not i_mesh) { throw NormalError("discrete functions are not defined on the same mesh"); } - if (not checkDiscretizationType({i_rho, i_aL, i_u, i_sigma}, DiscreteFunctionType::P0)) { + if (not checkDiscretizationType({rho_v, aL_v, u_v, sigma_v}, DiscreteFunctionType::P0)) { throw NormalError("hyperelastic solver expects P0 functions"); } const MeshType& mesh = dynamic_cast<const MeshType&>(*i_mesh); - const DiscreteScalarFunction& rho = dynamic_cast<const DiscreteScalarFunction&>(*i_rho); - const DiscreteScalarFunction& aL = dynamic_cast<const DiscreteScalarFunction&>(*i_aL); - const DiscreteScalarFunction& aT = dynamic_cast<const DiscreteScalarFunction&>(*i_aT); - const DiscreteVectorFunction& u = dynamic_cast<const DiscreteVectorFunction&>(*i_u); - const DiscreteTensorFunction& sigma = dynamic_cast<const DiscreteTensorFunction&>(*i_sigma); + const DiscreteScalarFunction& rho = rho_v->get<DiscreteScalarFunction>(); + const DiscreteVectorFunction& u = u_v->get<DiscreteVectorFunction>(); + const DiscreteScalarFunction& aL = aL_v->get<DiscreteScalarFunction>(); + const DiscreteScalarFunction& aT = aT_v->get<DiscreteScalarFunction>(); + const DiscreteTensorFunction& sigma = sigma_v->get<DiscreteTensorFunction>(); NodeValuePerCell<const Rdxd> Ajr = this->_computeAjr(solver_type, mesh, rho * aL, rho * aT); @@ -441,16 +437,16 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS } std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const DiscreteFunctionP0<Dimension, double>>, - std::shared_ptr<const DiscreteFunctionP0<Dimension, Rd>>, - std::shared_ptr<const DiscreteFunctionP0<Dimension, double>>, - std::shared_ptr<const DiscreteFunctionP0<Dimension, Rdxd>>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply_fluxes(const double& dt, const MeshType& mesh, - const DiscreteFunctionP0<Dimension, double>& rho, - const DiscreteFunctionP0<Dimension, Rd>& u, - const DiscreteFunctionP0<Dimension, double>& E, - const DiscreteFunctionP0<Dimension, Rdxd>& CG, + const DiscreteScalarFunction& rho, + const DiscreteVectorFunction& u, + const DiscreteScalarFunction& E, + const DiscreteTensorFunction& CG, const NodeValue<const Rd>& ur, const NodeValuePerCell<const Rd>& Fjr) const { @@ -503,22 +499,22 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS parallel_for( mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { new_rho[j] *= Vj[j] / new_Vj[j]; }); - return {new_mesh, std::make_shared<DiscreteScalarFunction>(new_mesh, new_rho), - std::make_shared<DiscreteVectorFunction>(new_mesh, new_u), - std::make_shared<DiscreteScalarFunction>(new_mesh, new_E), - std::make_shared<DiscreteTensorFunction>(new_mesh, new_CG)}; + return {new_mesh, std::make_shared<DiscreteFunctionVariant>(DiscreteScalarFunction(new_mesh, new_rho)), + std::make_shared<DiscreteFunctionVariant>(DiscreteVectorFunction(new_mesh, new_u)), + std::make_shared<DiscreteFunctionVariant>(DiscreteScalarFunction(new_mesh, new_E)), + std::make_shared<DiscreteFunctionVariant>(DiscreteTensorFunction(new_mesh, new_CG))}; } std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply_fluxes(const double& dt, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& CG, + const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& CG, const std::shared_ptr<const ItemValueVariant>& ur, const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr) const { @@ -531,30 +527,30 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS throw NormalError("hyperelastic solver expects P0 functions"); } - return this->apply_fluxes(dt, // - dynamic_cast<const MeshType&>(*i_mesh), // - dynamic_cast<const DiscreteScalarFunction&>(*rho), // - dynamic_cast<const DiscreteVectorFunction&>(*u), // - dynamic_cast<const DiscreteScalarFunction&>(*E), // - dynamic_cast<const DiscreteTensorFunction&>(*CG), // - ur->get<NodeValue<const Rd>>(), // + return this->apply_fluxes(dt, // + dynamic_cast<const MeshType&>(*i_mesh), // + rho->get<DiscreteScalarFunction>(), // + u->get<DiscreteVectorFunction>(), // + E->get<DiscreteScalarFunction>(), // + CG->get<DiscreteTensorFunction>(), // + ur->get<NodeValue<const Rd>>(), // Fjr->get<NodeValuePerCell<const Rd>>()); } std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply(const SolverType& solver_type, const double& dt, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& CG, - const std::shared_ptr<const IDiscreteFunction>& aL, - const std::shared_ptr<const IDiscreteFunction>& aT, - const std::shared_ptr<const IDiscreteFunction>& sigma, + const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& CG, + const std::shared_ptr<const DiscreteFunctionVariant>& aL, + const std::shared_ptr<const DiscreteFunctionVariant>& aT, + const std::shared_ptr<const DiscreteFunctionVariant>& sigma, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const { auto [ur, Fjr] = compute_fluxes(solver_type, rho, aL, aT, u, sigma, bc_descriptor_list); diff --git a/src/scheme/HyperelasticSolver.hpp b/src/scheme/HyperelasticSolver.hpp index b91778122f632c88f606d2e21be793b1849eb206..f82cbe361051efc64a3e413d60c830febd62d907 100644 --- a/src/scheme/HyperelasticSolver.hpp +++ b/src/scheme/HyperelasticSolver.hpp @@ -5,13 +5,13 @@ #include <tuple> #include <vector> -class IDiscreteFunction; class IBoundaryConditionDescriptor; class IMesh; class ItemValueVariant; class SubItemValuePerItemVariant; +class DiscreteFunctionVariant; -double hyperelastic_dt(const std::shared_ptr<const IDiscreteFunction>& c); +double hyperelastic_dt(const std::shared_ptr<const DiscreteFunctionVariant>& c); class HyperelasticSolverHandler { @@ -29,40 +29,40 @@ class HyperelasticSolverHandler const std::shared_ptr<const SubItemValuePerItemVariant>> compute_fluxes( const SolverType& solver_type, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& aL, - const std::shared_ptr<const IDiscreteFunction>& aT, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& sigma, + const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& aL, + const std::shared_ptr<const DiscreteFunctionVariant>& aT, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& sigma, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const = 0; virtual std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply_fluxes(const double& dt, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& CG, + const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& CG, const std::shared_ptr<const ItemValueVariant>& ur, const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr) const = 0; virtual std::tuple<std::shared_ptr<const IMesh>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>, - std::shared_ptr<const IDiscreteFunction>> + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>, + std::shared_ptr<const DiscreteFunctionVariant>> apply(const SolverType& solver_type, const double& dt, - const std::shared_ptr<const IDiscreteFunction>& rho, - const std::shared_ptr<const IDiscreteFunction>& u, - const std::shared_ptr<const IDiscreteFunction>& E, - const std::shared_ptr<const IDiscreteFunction>& CG, - const std::shared_ptr<const IDiscreteFunction>& aL, - const std::shared_ptr<const IDiscreteFunction>& aT, - const std::shared_ptr<const IDiscreteFunction>& p, + const std::shared_ptr<const DiscreteFunctionVariant>& rho, + const std::shared_ptr<const DiscreteFunctionVariant>& u, + const std::shared_ptr<const DiscreteFunctionVariant>& E, + const std::shared_ptr<const DiscreteFunctionVariant>& CG, + const std::shared_ptr<const DiscreteFunctionVariant>& aL, + const std::shared_ptr<const DiscreteFunctionVariant>& aT, + const std::shared_ptr<const DiscreteFunctionVariant>& p, const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const = 0; IHyperelasticSolver() = default; diff --git a/src/scheme/IDiscreteFunction.hpp b/src/scheme/IDiscreteFunction.hpp deleted file mode 100644 index be6ca66278de95265e9a301ebc8f2fe0fa7ee5db..0000000000000000000000000000000000000000 --- a/src/scheme/IDiscreteFunction.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef I_DISCRETE_FUNCTION_HPP -#define I_DISCRETE_FUNCTION_HPP - -class IMesh; -class IDiscreteFunctionDescriptor; - -#include <language/utils/ASTNodeDataTypeTraits.hpp> -#include <memory> - -class IDiscreteFunction -{ - public: - enum class HandledItemDataType - { - value, - vector, - }; - - virtual std::shared_ptr<const IMesh> mesh() const = 0; - virtual const IDiscreteFunctionDescriptor& descriptor() const = 0; - virtual ASTNodeDataType dataType() const = 0; - - IDiscreteFunction() = default; - - IDiscreteFunction(const IDiscreteFunction&) = default; - - IDiscreteFunction(IDiscreteFunction&&) noexcept = default; - - virtual ~IDiscreteFunction() noexcept = default; -}; - -#endif // I_DISCRETE_FUNCTION_HPP diff --git a/src/utils/Array.hpp b/src/utils/Array.hpp index 7535b673565fa04aadba3935420f6946f5ad5544..3ee64824a650e18714a9b4b8523afb78cc89f643 100644 --- a/src/utils/Array.hpp +++ b/src/utils/Array.hpp @@ -24,6 +24,18 @@ class [[nodiscard]] Array const size_t m_size; public: + friend std::ostream& + operator<<(std::ostream& os, const UnsafeArrayView& x) + { + if (x.size() > 0) { + os << 0 << ':' << NaNHelper(x[0]); + } + for (size_t i = 1; i < x.size(); ++i) { + os << ' ' << i << ':' << NaNHelper(x[i]); + } + return os; + } + [[nodiscard]] PUGS_INLINE size_t size() const { diff --git a/src/utils/PugsTraits.hpp b/src/utils/PugsTraits.hpp index 46a2b1d6dc5923d8ee12668d88484875f404944c..285d7978d8a8f05e784534d0fb475bc01da75042 100644 --- a/src/utils/PugsTraits.hpp +++ b/src/utils/PugsTraits.hpp @@ -20,6 +20,12 @@ class ItemValue; template <typename DataType, ItemType item_type, typename ConnectivityPtr> class ItemArray; +template <size_t Dimension, typename DataType> +class DiscreteFunctionP0; + +template <size_t Dimension, typename DataType> +class DiscreteFunctionP0Vector; + // Traits is_trivially_castable template <typename T> @@ -116,7 +122,7 @@ constexpr inline bool is_item_value_v = false; template <typename DataType, ItemType item_type, typename ConnectivityPtr> constexpr inline bool is_item_value_v<ItemValue<DataType, item_type, ConnectivityPtr>> = true; -// Trais is ItemValue +// Trais is ItemArray template <typename T> constexpr inline bool is_item_array_v = false; @@ -124,6 +130,27 @@ constexpr inline bool is_item_array_v = false; template <typename DataType, ItemType item_type, typename ConnectivityPtr> constexpr inline bool is_item_array_v<ItemArray<DataType, item_type, ConnectivityPtr>> = true; +// Trais is DiscreteFunctionP0 + +template <typename T> +constexpr inline bool is_discrete_function_P0_v = false; + +template <size_t Dimension, typename DataType> +constexpr inline bool is_discrete_function_P0_v<DiscreteFunctionP0<Dimension, DataType>> = true; + +// Trais is DiscreteFunctionP0Vector + +template <typename T> +constexpr inline bool is_discrete_function_P0_vector_v = false; + +template <size_t Dimension, typename DataType> +constexpr inline bool is_discrete_function_P0_vector_v<DiscreteFunctionP0Vector<Dimension, DataType>> = true; + +// Trais is DiscreteFunction + +template <typename T> +constexpr inline bool is_discrete_function_v = is_discrete_function_P0_v<T> or is_discrete_function_P0_vector_v<T>; + // helper to check if a type is part of a variant template <typename T, typename V> diff --git a/src/utils/Table.hpp b/src/utils/Table.hpp index 6972ea1030dedbdd30c039e0880a3773024603dc..a4a134dfd1d5838766b062eb429c725eb66bbb33 100644 --- a/src/utils/Table.hpp +++ b/src/utils/Table.hpp @@ -63,6 +63,19 @@ class [[nodiscard]] Table Assert(row < table.numberOfRows(), "required row view is not contained in the Table"); } + friend std::ostream& + operator<<(std::ostream& os, const UnsafeRowView& x) + { + if (x.size() > 0) { + os << 0 << ':' << NaNHelper(x[0]); + } + for (size_t i = 1; i < x.size(); ++i) { + os << ' ' << i << ':' << NaNHelper(x[i]); + } + + return os; + } + // To try to keep these views close to the initial array one // forbids copy constructor and take benefits of C++-17 copy // elisions. @@ -113,6 +126,19 @@ class [[nodiscard]] Table } } + friend std::ostream& + operator<<(std::ostream& os, const RowView& x) + { + if (x.size() > 0) { + os << 0 << ':' << NaNHelper(x[0]); + } + for (size_t i = 1; i < x.size(); ++i) { + os << ' ' << i << ':' << NaNHelper(x[i]); + } + + return os; + } + RowView(const UnsafeTableView& table_view, index_type row) : m_table_view{table_view}, m_row{row} { Assert(row < m_table_view.numberOfRows(), "required row view is not contained in the Table view"); @@ -155,6 +181,19 @@ class [[nodiscard]] Table return m_table(m_row_begin + i, m_column_begin + j); } + friend std::ostream& + operator<<(std::ostream& os, const UnsafeTableView& t) + { + for (size_t i = 0; i < t.numberOfRows(); ++i) { + os << i << '|'; + for (size_t j = 0; j < t.numberOfColumns(); ++j) { + os << ' ' << j << ':' << NaNHelper(t(i, j)); + } + os << '\n'; + } + return os; + } + PUGS_INLINE void fill(const DataType& data) const { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3f174398186c2b5fd0bcc56aef017f40936f9704..0e585acac5ba1e5b7656ffa29411567e0f0d54f4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -82,7 +82,7 @@ add_executable (unit_tests test_EdgeIntegrator.cpp test_EigenvalueSolver.cpp test_EmbeddedData.cpp - test_EmbeddedIDiscreteFunctionUtils.cpp + test_EmbeddedDiscreteFunctionUtils.cpp test_EscapedString.cpp test_Exceptions.cpp test_ExecutionPolicy.cpp @@ -167,8 +167,12 @@ add_executable (mpi_unit_tests test_DiscreteFunctionVectorIntegratorByZone.cpp test_DiscreteFunctionVectorInterpoler.cpp test_DiscreteFunctionVectorInterpolerByZone.cpp - test_EmbeddedIDiscreteFunctionMathFunctions.cpp - test_EmbeddedIDiscreteFunctionOperators.cpp + test_EmbeddedDiscreteFunctionMathFunctions1D.cpp + test_EmbeddedDiscreteFunctionMathFunctions2D.cpp + test_EmbeddedDiscreteFunctionMathFunctions3D.cpp + test_EmbeddedDiscreteFunctionOperators1D.cpp + test_EmbeddedDiscreteFunctionOperators2D.cpp + test_EmbeddedDiscreteFunctionOperators3D.cpp test_InterpolateItemArray.cpp test_InterpolateItemValue.cpp test_ItemArray.cpp diff --git a/tests/test_BuiltinFunctionEmbedder.cpp b/tests/test_BuiltinFunctionEmbedder.cpp index 7fd481e163a77f73b32a0d08fba3f49224cdc130..2e56fe228bc4b5d0ae863ae177b3633efbfa6e90 100644 --- a/tests/test_BuiltinFunctionEmbedder.cpp +++ b/tests/test_BuiltinFunctionEmbedder.cpp @@ -10,12 +10,8 @@ inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_const_double"); template <> -inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<double>> = - ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_double"); - -template <> -inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<uint64_t>> = - ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_uint64_t"); +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const uint64_t>> = + ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_const_uint64_t"); TEST_CASE("BuiltinFunctionEmbedder", "[language]") { @@ -177,7 +173,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") REQUIRE(*data.data_ptr() == (2.3 + 4ul)); } - SECTION("double(std::shared_ptr<double>) BuiltinFunctionEmbedder") + SECTION("double(std::shared_ptr<const double>) BuiltinFunctionEmbedder") { std::function abs = [&](std::shared_ptr<const double> x) -> double { return std::abs(*x); }; @@ -237,7 +233,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") SECTION("uint64_t(std::vector<EmbeddedData>) BuiltinFunctionEmbedder") { - std::function sum = [&](const std::vector<std::shared_ptr<uint64_t>>& x) -> uint64_t { + std::function sum = [&](const std::vector<std::shared_ptr<const uint64_t>>& x) -> uint64_t { uint64_t sum = 0; for (size_t i = 0; i < x.size(); ++i) { sum += *x[i]; @@ -246,7 +242,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") }; std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = - std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<std::shared_ptr<uint64_t>>&)>>(sum); + std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<std::shared_ptr<const uint64_t>>&)>>(sum); REQUIRE(i_embedded_c->numberOfParameters() == 1); REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1); @@ -255,21 +251,21 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") std::vector<EmbeddedData> embedded_data; REQUIRE(std::get<uint64_t>(i_embedded_c->apply({embedded_data})) == 0); - embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(1))); - embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(2))); - embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(3))); + embedded_data.emplace_back(std::make_shared<DataHandler<const uint64_t>>(std::make_shared<const uint64_t>(1))); + embedded_data.emplace_back(std::make_shared<DataHandler<const uint64_t>>(std::make_shared<const uint64_t>(2))); + embedded_data.emplace_back(std::make_shared<DataHandler<const uint64_t>>(std::make_shared<const uint64_t>(3))); REQUIRE(std::get<uint64_t>(i_embedded_c->apply({embedded_data})) == 6); - embedded_data.emplace_back(std::make_shared<DataHandler<double>>(std::make_shared<double>(4))); + embedded_data.emplace_back(std::make_shared<DataHandler<const double>>(std::make_shared<const double>(4))); REQUIRE_THROWS_WITH(i_embedded_c->apply({embedded_data}), "unexpected error: unexpected argument types while casting: invalid" " EmbeddedData type, expecting " + - demangle<DataHandler<uint64_t>>()); + demangle<DataHandler<const uint64_t>>()); REQUIRE_THROWS_WITH(i_embedded_c->apply({TinyVector<1>{13}}), "unexpected error: unexpected argument types while casting \"" + demangle<TinyVector<1>>() + - "\" to \"" + demangle<std::vector<std::shared_ptr<uint64_t>>>() + '"'); + "\" to \"" + demangle<std::vector<std::shared_ptr<const uint64_t>>>() + '"'); } SECTION("double(void) BuiltinFunctionEmbedder") @@ -286,9 +282,9 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::double_t); } - SECTION("R*R -> R*R^2*shared_double BuiltinFunctionEmbedder") + SECTION("R*R -> R*R^2*shared_const_double BuiltinFunctionEmbedder") { - std::function c = [](double a, double b) -> std::tuple<double, TinyVector<2>, std::shared_ptr<double>> { + std::function c = [](double a, double b) -> std::tuple<double, TinyVector<2>, std::shared_ptr<const double>> { return std::make_tuple(a + b, TinyVector<2>{b, -a}, std::make_shared<double>(a - b)); }; @@ -311,15 +307,15 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") REQUIRE(*data_type.contentTypeList()[0] == ASTNodeDataType::double_t); REQUIRE(*data_type.contentTypeList()[1] == ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)); - REQUIRE(*data_type.contentTypeList()[2] == ast_node_data_type_from<std::shared_ptr<double>>); + REQUIRE(*data_type.contentTypeList()[2] == ast_node_data_type_from<std::shared_ptr<const double>>); } - SECTION("void -> N*R*shared_double BuiltinFunctionEmbedder") + SECTION("void -> N*R*shared_const_double BuiltinFunctionEmbedder") { - std::function c = [](void) -> std::tuple<uint64_t, double, std::shared_ptr<double>> { + std::function c = [](void) -> std::tuple<uint64_t, double, std::shared_ptr<const double>> { uint64_t a = 1; double b = 3.5; - return std::make_tuple(a, b, std::make_shared<double>(a + b)); + return std::make_tuple(a, b, std::make_shared<const double>(a + b)); }; std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = @@ -357,19 +353,19 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") SECTION("EmbeddedData(void) BuiltinFunctionEmbedder") { - std::function c = [](void) -> std::shared_ptr<double> { return std::make_shared<double>(1.5); }; + std::function c = [](void) -> std::shared_ptr<const double> { return std::make_shared<const double>(1.5); }; std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = - std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<double>(void)>>(c); + std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<const double>(void)>>(c); REQUIRE(i_embedded_c->numberOfParameters() == 0); REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0); - REQUIRE(i_embedded_c->getReturnDataType() == ast_node_data_type_from<std::shared_ptr<double>>); + REQUIRE(i_embedded_c->getReturnDataType() == ast_node_data_type_from<std::shared_ptr<const double>>); - const auto embedded_data = std::get<EmbeddedData>(i_embedded_c->apply(std::vector<DataVariant>{})); - const IDataHandler& handled_data = embedded_data.get(); - const DataHandler<double>& data = dynamic_cast<const DataHandler<double>&>(handled_data); + const auto embedded_data = std::get<EmbeddedData>(i_embedded_c->apply(std::vector<DataVariant>{})); + const IDataHandler& handled_data = embedded_data.get(); + const DataHandler<const double>& data = dynamic_cast<const DataHandler<const double>&>(handled_data); REQUIRE(*data.data_ptr() == 1.5); } diff --git a/tests/test_BuiltinFunctionProcessor.cpp b/tests/test_BuiltinFunctionProcessor.cpp index 0168633cea1d2d2e764b6b835093d1f17504024d..8de9ec2c2ed9e61479aa2d7165bf6e506fd6caf6 100644 --- a/tests/test_BuiltinFunctionProcessor.cpp +++ b/tests/test_BuiltinFunctionProcessor.cpp @@ -385,15 +385,15 @@ let d:R, d = det(A); tested_function_set.insert("det:R^3x3"); std::string_view data = R"( import math; -let A:R^3x3, A = [[-2.5, 2.9,-1.3], - [ 3.2, 2.3, 2.7], - [-2.6, 5.2,-3.5]]; +let A:R^3x3, A = [[-2, 2,-1], + [ 3, 2, 2], + [-2, 5,-3]]; let d:R, d = det(A); )"; CHECK_BUILTIN_FUNCTION_EVALUATION_RESULT(data, "d", - det(TinyMatrix<3>{-2.5, 2.9, -1.3, // - +3.2, 2.3, +2.7, // - -2.6, 5.2, -3.5})); + det(TinyMatrix<3>{-2, 2, -1, // + +3, 2, +2, // + -2, 5, -3})); } { // trace @@ -461,15 +461,15 @@ let invA:R^2x2, invA = inverse(A); tested_function_set.insert("inverse:R^3x3"); std::string_view data = R"( import math; -let A:R^3x3, A = [[-2.5, 2.9,-1.3], - [ 3.2, 2.3, 2.7], - [-2.6, 5.2,-3.5]]; +let A:R^3x3, A = [[-2, 2,-1], + [ 3, 2, 2], + [-2, 5,-3]]; let invA:R^3x3, invA = inverse(A); )"; CHECK_BUILTIN_FUNCTION_EVALUATION_RESULT(data, "invA", - inverse(TinyMatrix<3>{-2.5, 2.9, -1.3, // - +3.2, 2.3, +2.7, // - -2.6, 5.2, -3.5})); + inverse(TinyMatrix<3>{-2, 2, -1, // + +3, 2, +2, // + -2, 5, -3})); } { // transpose diff --git a/tests/test_Connectivity.cpp b/tests/test_Connectivity.cpp index 60e894a83a367b6d07ef80939ac0860095dfd322..b0465d08489c644685500d59b145e12594966522 100644 --- a/tests/test_Connectivity.cpp +++ b/tests/test_Connectivity.cpp @@ -3,6 +3,7 @@ #include <MeshDataBaseForTests.hpp> #include <mesh/Connectivity.hpp> +#include <mesh/ConnectivityUtils.hpp> #include <mesh/ItemValue.hpp> #include <mesh/ItemValueUtils.hpp> #include <mesh/Mesh.hpp> @@ -670,6 +671,318 @@ TEST_CASE("Connectivity", "[mesh]") } } + SECTION("item ordering") + { + SECTION("1D") + { + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + SECTION("cell -> nodes") + { + auto mesh = named_mesh.mesh(); + auto xr = mesh->xr(); + + const Connectivity<1>& connectivity = mesh->connectivity(); + + auto cell_to_node_matrix = connectivity.cellToNodeMatrix(); + + bool is_correct = true; + + for (CellId cell_id = 0; cell_id < connectivity.numberOfCells(); ++cell_id) { + if (xr[cell_to_node_matrix[cell_id][1]][0] < xr[cell_to_node_matrix[cell_id][0]][0]) { + is_correct = false; + } + } + REQUIRE(is_correct); + } + + SECTION("node -> cells") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<1>& connectivity = mesh->connectivity(); + + auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + auto cell_number = connectivity.cellNumber(); + + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + auto cell_node_list = node_to_cell_matrix[node_id]; + for (size_t i_node = 0; i_node < cell_node_list.size() - 1; ++i_node) { + is_correct &= (cell_number[cell_node_list[i_node]] < cell_number[cell_node_list[i_node + 1]]); + } + } + REQUIRE(is_correct); + } + } + } + } + + SECTION("2D") + { + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + SECTION("face -> nodes") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<2>& connectivity = mesh->connectivity(); + + auto face_to_node_matrix = connectivity.faceToNodeMatrix(); + auto node_number = connectivity.nodeNumber(); + + bool is_correct = true; + + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + auto face_node_list = face_to_node_matrix[face_id]; + if (node_number[face_node_list[1]] < node_number[face_node_list[0]]) { + is_correct = false; + } + } + REQUIRE(is_correct); + } + + SECTION("node -> faces") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<2>& connectivity = mesh->connectivity(); + + auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); + auto face_number = connectivity.faceNumber(); + + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + auto face_node_list = node_to_face_matrix[node_id]; + for (size_t i_node = 0; i_node < face_node_list.size() - 1; ++i_node) { + is_correct &= (face_number[face_node_list[i_node]] < face_number[face_node_list[i_node + 1]]); + } + } + REQUIRE(is_correct); + } + + SECTION("node -> cells") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<2>& connectivity = mesh->connectivity(); + + auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + auto cell_number = connectivity.cellNumber(); + + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + auto cell_node_list = node_to_cell_matrix[node_id]; + for (size_t i_node = 0; i_node < cell_node_list.size() - 1; ++i_node) { + is_correct &= (cell_number[cell_node_list[i_node]] < cell_number[cell_node_list[i_node + 1]]); + } + } + REQUIRE(is_correct); + } + + SECTION("face -> cells") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<2>& connectivity = mesh->connectivity(); + + auto face_to_cell_matrix = connectivity.faceToCellMatrix(); + auto cell_number = connectivity.cellNumber(); + + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + auto cell_face_list = face_to_cell_matrix[face_id]; + for (size_t i_face = 0; i_face < cell_face_list.size() - 1; ++i_face) { + is_correct &= (cell_number[cell_face_list[i_face]] < cell_number[cell_face_list[i_face + 1]]); + } + } + REQUIRE(is_correct); + } + } + } + } + + SECTION("3D") + { + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + SECTION("edge -> nodes") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<3>& connectivity = mesh->connectivity(); + + auto edge_to_node_matrix = connectivity.edgeToNodeMatrix(); + auto node_number = connectivity.nodeNumber(); + + bool is_correct = true; + + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + auto edge_node_list = edge_to_node_matrix[edge_id]; + if (node_number[edge_node_list[1]] < node_number[edge_node_list[0]]) { + is_correct = false; + } + } + REQUIRE(is_correct); + } + + SECTION("face -> nodes") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<3>& connectivity = mesh->connectivity(); + + auto face_to_node_matrix = connectivity.faceToNodeMatrix(); + auto node_number = connectivity.nodeNumber(); + + bool is_correct = true; + + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + auto face_node_list = face_to_node_matrix[face_id]; + for (size_t i = 1; i < face_node_list.size() - 1; ++i) { + if (node_number[face_node_list[i]] < node_number[face_node_list[0]]) { + is_correct = false; + } + } + for (size_t i = 2; i < face_node_list.size() - 1; ++i) { + if (node_number[face_node_list[i]] < node_number[face_node_list[1]]) { + is_correct = false; + } + } + } + REQUIRE(is_correct); + } + + SECTION("node -> edges") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<3>& connectivity = mesh->connectivity(); + + REQUIRE(checkConnectivityOrdering(connectivity)); + + auto node_to_edge_matrix = connectivity.nodeToEdgeMatrix(); + auto edge_number = connectivity.edgeNumber(); + + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + auto edge_node_list = node_to_edge_matrix[node_id]; + for (size_t i_node = 0; i_node < edge_node_list.size() - 1; ++i_node) { + is_correct &= (edge_number[edge_node_list[i_node]] < edge_number[edge_node_list[i_node + 1]]); + } + } + + REQUIRE(is_correct); + } + + SECTION("node -> faces") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<3>& connectivity = mesh->connectivity(); + + auto node_to_face_matrix = connectivity.nodeToFaceMatrix(); + auto face_number = connectivity.faceNumber(); + + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + auto face_node_list = node_to_face_matrix[node_id]; + for (size_t i_node = 0; i_node < face_node_list.size() - 1; ++i_node) { + is_correct &= (face_number[face_node_list[i_node]] < face_number[face_node_list[i_node + 1]]); + } + } + REQUIRE(is_correct); + } + + SECTION("node -> cells") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<3>& connectivity = mesh->connectivity(); + + auto node_to_cell_matrix = connectivity.nodeToCellMatrix(); + auto cell_number = connectivity.cellNumber(); + + bool is_correct = true; + for (NodeId node_id = 0; node_id < connectivity.numberOfNodes(); ++node_id) { + auto cell_node_list = node_to_cell_matrix[node_id]; + for (size_t i_node = 0; i_node < cell_node_list.size() - 1; ++i_node) { + is_correct &= (cell_number[cell_node_list[i_node]] < cell_number[cell_node_list[i_node + 1]]); + } + } + REQUIRE(is_correct); + } + + SECTION("edge -> faces") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<3>& connectivity = mesh->connectivity(); + + auto edge_to_face_matrix = connectivity.edgeToFaceMatrix(); + auto face_number = connectivity.faceNumber(); + + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + auto face_edge_list = edge_to_face_matrix[edge_id]; + for (size_t i_edge = 0; i_edge < face_edge_list.size() - 1; ++i_edge) { + is_correct &= (face_number[face_edge_list[i_edge]] < face_number[face_edge_list[i_edge + 1]]); + } + } + REQUIRE(is_correct); + } + + SECTION("edge -> cells") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<3>& connectivity = mesh->connectivity(); + + auto edge_to_cell_matrix = connectivity.edgeToCellMatrix(); + auto cell_number = connectivity.cellNumber(); + + bool is_correct = true; + for (EdgeId edge_id = 0; edge_id < connectivity.numberOfEdges(); ++edge_id) { + auto cell_edge_list = edge_to_cell_matrix[edge_id]; + for (size_t i_edge = 0; i_edge < cell_edge_list.size() - 1; ++i_edge) { + is_correct &= (cell_number[cell_edge_list[i_edge]] < cell_number[cell_edge_list[i_edge + 1]]); + } + } + REQUIRE(is_correct); + } + + SECTION("face -> cells") + { + auto mesh = named_mesh.mesh(); + + const Connectivity<3>& connectivity = mesh->connectivity(); + + auto face_to_cell_matrix = connectivity.faceToCellMatrix(); + auto cell_number = connectivity.cellNumber(); + + bool is_correct = true; + for (FaceId face_id = 0; face_id < connectivity.numberOfFaces(); ++face_id) { + auto cell_face_list = face_to_cell_matrix[face_id]; + for (size_t i_face = 0; i_face < cell_face_list.size() - 1; ++i_face) { + is_correct &= (cell_number[cell_face_list[i_face]] < cell_number[cell_face_list[i_face + 1]]); + } + } + REQUIRE(is_correct); + } + } + } + } + } + SECTION("ItemLocalNumbersInTheirSubItems") { auto check_item_local_numbers_in_their_subitems = [](auto item_to_subitem_matrix, auto subitem_to_item_matrix, diff --git a/tests/test_DiamondDualConnectivityBuilder.cpp b/tests/test_DiamondDualConnectivityBuilder.cpp index 70b8f75440061530f386654a4bbf9e3f5342d33e..45d9cd700ca7b5ae73e6c6fd22db024e7de3126c 100644 --- a/tests/test_DiamondDualConnectivityBuilder.cpp +++ b/tests/test_DiamondDualConnectivityBuilder.cpp @@ -5,6 +5,7 @@ #include <mesh/DualConnectivityManager.hpp> #include <mesh/Connectivity.hpp> +#include <mesh/ConnectivityUtils.hpp> #include <mesh/ItemValueUtils.hpp> #include <mesh/Mesh.hpp> @@ -54,6 +55,8 @@ TEST_CASE("DiamondDualConnectivityBuilder", "[mesh]") REQUIRE(dual_connectivity.numberOfFaces() == 220); REQUIRE(dual_connectivity.numberOfCells() == 110); + REQUIRE(checkConnectivityOrdering(dual_connectivity)); + SECTION("ref node list") { REQUIRE(primal_connectivity.numberOfRefItemList<ItemType::node>() == 4); @@ -159,6 +162,8 @@ TEST_CASE("DiamondDualConnectivityBuilder", "[mesh]") DualConnectivityManager::instance().getDiamondDualConnectivity(primal_connectivity); const ConnectivityType& dual_connectivity = *p_diamond_dual_connectivity; + REQUIRE(checkConnectivityOrdering(dual_connectivity)); + REQUIRE(dual_connectivity.numberOfNodes() == 331); REQUIRE(dual_connectivity.numberOfEdges() == 1461); REQUIRE(dual_connectivity.numberOfFaces() == 1651); diff --git a/tests/test_DiscreteFunctionIntegrator.cpp b/tests/test_DiscreteFunctionIntegrator.cpp index 250d8010244aac6eb3a908f4da5c60099ab5ae79..b3ba2efba4ae8fe3dc90b8b54f6df6032d622e8c 100644 --- a/tests/test_DiscreteFunctionIntegrator.cpp +++ b/tests/test_DiscreteFunctionIntegrator.cpp @@ -23,6 +23,7 @@ #include <scheme/DiscreteFunctionDescriptorP0.hpp> #include <scheme/DiscreteFunctionIntegrator.hpp> #include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <pegtl/string_input.hpp> @@ -98,10 +99,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( IntegrateCellValue<double(TinyVector<1>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_1d") @@ -116,10 +116,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( IntegrateCellValue<double(TinyVector<1>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_1d") @@ -134,10 +133,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( IntegrateCellValue<double(TinyVector<1>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_1d") @@ -152,10 +150,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( IntegrateCellValue<double(TinyVector<1>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_1d") @@ -173,10 +170,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_1d") @@ -194,10 +190,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_1d") @@ -215,10 +210,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_1d") @@ -236,10 +230,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_1d") @@ -257,10 +250,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_1d") @@ -278,10 +270,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( *mesh_1d); DiscreteFunctionIntegrator integrator(mesh_1d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } } @@ -344,10 +335,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( IntegrateCellValue<double(TinyVector<2>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_2d") @@ -362,10 +352,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( IntegrateCellValue<double(TinyVector<2>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_2d") @@ -380,10 +369,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( IntegrateCellValue<double(TinyVector<2>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_2d") @@ -398,10 +386,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( IntegrateCellValue<double(TinyVector<2>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_2d") @@ -419,10 +406,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_2d") @@ -440,10 +426,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_2d") @@ -461,10 +446,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_2d") @@ -482,10 +466,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_2d") @@ -503,10 +486,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_2d") @@ -524,10 +506,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_2d); DiscreteFunctionIntegrator integrator(mesh_2d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } } @@ -590,10 +571,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( IntegrateCellValue<double(TinyVector<3>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_3d") @@ -608,10 +588,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( IntegrateCellValue<double(TinyVector<3>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_3d") @@ -626,10 +605,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( IntegrateCellValue<double(TinyVector<3>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_3d") @@ -644,10 +622,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( IntegrateCellValue<double(TinyVector<3>)>::integrate(function_symbol_id, *quadrature_descriptor, *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_3d") @@ -665,10 +642,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_3d") @@ -686,10 +662,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_3d") @@ -707,10 +682,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_3d") @@ -728,10 +702,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_3d") @@ -749,10 +722,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_3d") @@ -770,10 +742,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( *mesh_3d); DiscreteFunctionIntegrator integrator(mesh_3d, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } } diff --git a/tests/test_DiscreteFunctionIntegratorByZone.cpp b/tests/test_DiscreteFunctionIntegratorByZone.cpp index 19c0ac87c1d941e4c5f0026e154087be305c55f2..217c15b38d17195f2e3baa56d0a698f0b2c9c2a4 100644 --- a/tests/test_DiscreteFunctionIntegratorByZone.cpp +++ b/tests/test_DiscreteFunctionIntegratorByZone.cpp @@ -25,6 +25,7 @@ #include <scheme/DiscreteFunctionDescriptorP0.hpp> #include <scheme/DiscreteFunctionIntegrator.hpp> #include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <pegtl/string_input.hpp> @@ -111,10 +112,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_1d") @@ -139,10 +139,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_1d") @@ -167,10 +166,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_1d") @@ -195,10 +193,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_1d") @@ -225,10 +222,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_1d") @@ -255,10 +251,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_1d") @@ -285,10 +280,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_1d") @@ -315,10 +309,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_1d") @@ -345,10 +338,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_1d") @@ -375,10 +367,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } @@ -450,10 +441,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_2d") @@ -478,10 +468,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_2d") @@ -506,10 +495,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_2d") @@ -534,10 +522,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_2d") @@ -564,10 +551,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_2d") @@ -594,10 +580,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_2d") @@ -624,10 +609,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_2d") @@ -654,10 +638,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_2d") @@ -684,10 +667,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_2d") @@ -714,10 +696,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } @@ -789,10 +770,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_3d") @@ -817,10 +797,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_3d") @@ -845,10 +824,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_3d") @@ -873,10 +851,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_3d") @@ -903,10 +880,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_3d") @@ -933,10 +909,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_3d") @@ -963,10 +938,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_3d") @@ -993,10 +967,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_3d") @@ -1023,10 +996,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_3d") @@ -1053,10 +1025,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( }); DiscreteFunctionIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, function_symbol_id); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } } diff --git a/tests/test_DiscreteFunctionInterpoler.cpp b/tests/test_DiscreteFunctionInterpoler.cpp index 431e5a55939dfc67a71a258f004afe92fdbe5a58..0287d97c89ef966f5a4d68ecd091875b3e19e14b 100644 --- a/tests/test_DiscreteFunctionInterpoler.cpp +++ b/tests/test_DiscreteFunctionInterpoler.cpp @@ -21,6 +21,7 @@ #include <scheme/DiscreteFunctionDescriptorP0.hpp> #include <scheme/DiscreteFunctionInterpoler.hpp> #include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <pegtl/string_input.hpp> @@ -101,10 +102,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_1d") @@ -124,10 +124,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_1d") @@ -147,10 +146,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_1d") @@ -170,10 +168,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_1d") @@ -195,10 +192,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_1d") @@ -220,10 +216,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_1d") @@ -245,10 +240,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_1d") @@ -270,10 +264,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_1d") @@ -296,10 +289,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_1d") @@ -329,10 +321,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } } @@ -400,10 +391,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_2d") @@ -423,10 +413,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_2d") @@ -446,10 +435,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_2d") @@ -469,10 +457,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_2d") @@ -494,10 +481,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_2d") @@ -519,10 +505,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_2d") @@ -544,10 +529,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_2d") @@ -569,10 +553,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_2d") @@ -595,10 +578,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_2d") @@ -629,10 +611,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } } @@ -700,10 +681,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_3d") @@ -723,10 +703,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_3d") @@ -746,10 +725,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_3d") @@ -769,10 +747,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_3d") @@ -794,10 +771,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_3d") @@ -819,10 +795,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_3d") @@ -844,10 +819,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_3d") @@ -869,10 +843,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_3d") @@ -895,10 +868,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_3d") @@ -929,10 +901,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE(same_cell_value(cell_value, - dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } } diff --git a/tests/test_DiscreteFunctionInterpolerByZone.cpp b/tests/test_DiscreteFunctionInterpolerByZone.cpp index dce3b645a7e98ee91b41f8cd5f158edb019d94ed..c4e6f0a00a15a8921615bb0540adf3c3668e7300 100644 --- a/tests/test_DiscreteFunctionInterpolerByZone.cpp +++ b/tests/test_DiscreteFunctionInterpolerByZone.cpp @@ -23,6 +23,7 @@ #include <scheme/DiscreteFunctionDescriptorP0.hpp> #include <scheme/DiscreteFunctionInterpoler.hpp> #include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <pegtl/string_input.hpp> @@ -113,10 +114,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_1d") @@ -140,10 +140,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_1d") @@ -167,10 +166,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_1d") @@ -194,10 +192,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_1d") @@ -223,10 +220,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_1d") @@ -252,10 +248,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_1d") @@ -281,10 +276,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_1d") @@ -310,10 +304,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_1d") @@ -340,10 +333,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_1d") @@ -377,10 +369,9 @@ let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } @@ -456,10 +447,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_2d") @@ -483,10 +473,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_2d") @@ -510,10 +499,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_2d") @@ -537,10 +525,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_2d") @@ -566,10 +553,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_2d") @@ -595,10 +581,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_2d") @@ -624,10 +609,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_2d") @@ -653,10 +637,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_2d") @@ -683,10 +666,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_2d") @@ -721,10 +703,9 @@ let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } @@ -800,10 +781,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("N_scalar_non_linear_3d") @@ -827,10 +807,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("Z_scalar_non_linear_3d") @@ -854,10 +833,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R_scalar_non_linear_3d") @@ -881,10 +859,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const double>>())); } SECTION("R1_non_linear_3d") @@ -910,10 +887,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2_non_linear_3d") @@ -939,10 +915,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3_non_linear_3d") @@ -968,10 +943,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R1x1_non_linear_3d") @@ -997,10 +971,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R2x2_non_linear_3d") @@ -1027,10 +1000,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } SECTION("R3x3_non_linear_3d") @@ -1065,10 +1037,9 @@ let R3x3_non_linear_3d: R^3 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin( DiscreteFunctionInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0>(), function_symbol_id); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); - REQUIRE( - same_cell_value(cell_value, dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, discrete_function.get<DiscreteFunctionP0<Dimension, const DataType>>())); } } } diff --git a/tests/test_DiscreteFunctionUtils.cpp b/tests/test_DiscreteFunctionUtils.cpp index c1cb07afea956f0ae9f70f6497d08bfda06edc71..85c916c4cf559ca4c2ceef612d1da03db779715e 100644 --- a/tests/test_DiscreteFunctionUtils.cpp +++ b/tests/test_DiscreteFunctionUtils.cpp @@ -28,39 +28,50 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") SECTION("common mesh") { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr wh = std::make_shared<DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh); + DiscreteFunctionP0<Dimension, double> uh(mesh); + DiscreteFunctionP0<Dimension, double> vh(mesh); + DiscreteFunctionP0<Dimension, TinyVector<2>> wh(mesh); - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); + DiscreteFunctionP0<Dimension, double> qh(mesh_copy); - REQUIRE(getCommonMesh({uh, vh, wh}).get() == mesh.get()); - REQUIRE(getCommonMesh({uh, vh, wh, qh}).use_count() == 0); + std::shared_ptr uh_v = std::make_shared<DiscreteFunctionVariant>(uh); + std::shared_ptr vh_v = std::make_shared<DiscreteFunctionVariant>(vh); + std::shared_ptr wh_v = std::make_shared<DiscreteFunctionVariant>(wh); + std::shared_ptr qh_v = std::make_shared<DiscreteFunctionVariant>(qh); + + REQUIRE(getCommonMesh({uh_v, vh_v, wh_v}).get() == mesh.get()); + REQUIRE(getCommonMesh({uh_v, vh_v, wh_v, qh_v}).use_count() == 0); } SECTION("check discretization type") { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - - std::shared_ptr Uh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - std::shared_ptr Vh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - - REQUIRE(checkDiscretizationType({uh}, DiscreteFunctionType::P0)); - REQUIRE(checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({Uh}, DiscreteFunctionType::P0)); + DiscreteFunctionP0<Dimension, double> uh(mesh); + DiscreteFunctionP0<Dimension, double> vh(mesh); + DiscreteFunctionP0<Dimension, double> qh(mesh_copy); + + DiscreteFunctionP0Vector<Dimension, double> Uh(mesh, 3); + DiscreteFunctionP0Vector<Dimension, double> Vh(mesh, 3); + + auto uh_v = std::make_shared<DiscreteFunctionVariant>(uh); + auto vh_v = std::make_shared<DiscreteFunctionVariant>(vh); + auto qh_v = std::make_shared<DiscreteFunctionVariant>(qh); + auto Uh_v = std::make_shared<DiscreteFunctionVariant>(Uh); + auto Vh_v = std::make_shared<DiscreteFunctionVariant>(Vh); + + REQUIRE(checkDiscretizationType({uh_v}, DiscreteFunctionType::P0)); + REQUIRE(checkDiscretizationType({uh_v, vh_v, qh_v}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({uh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({uh_v, vh_v, qh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh_v, Vh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({Uh_v, Vh_v}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({Uh_v}, DiscreteFunctionType::P0)); } SECTION("scalar function shallow copy") { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const double>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, double>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -68,14 +79,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^1 function shallow copy") { - using DataType = TinyVector<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyVector<1>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -83,14 +95,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^2 function shallow copy") { - using DataType = TinyVector<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyVector<2>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -98,14 +111,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^3 function shallow copy") { - using DataType = TinyVector<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyVector<3>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -113,14 +127,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^1x1 function shallow copy") { - using DataType = TinyMatrix<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyMatrix<1>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -128,14 +143,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^2x2 function shallow copy") { - using DataType = TinyMatrix<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyMatrix<2>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -143,14 +159,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^3x3 function shallow copy") { - using DataType = TinyMatrix<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyMatrix<3>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -158,8 +175,24 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); + } + + SECTION("P0Vector function shallow copy") + { + using DiscreteFunctionT = DiscreteFunctionP0Vector<Dimension, const double>; + std::shared_ptr uh = + std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0Vector<Dimension, double>(mesh, 2)); + std::shared_ptr vh = shallowCopy(mesh, uh); + + REQUIRE(uh == vh); + + std::shared_ptr wh = shallowCopy(mesh_copy, uh); + + REQUIRE(uh != wh); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellArrays()[CellId{0}][0]) == + &(wh->get<DiscreteFunctionT>().cellArrays()[CellId{0}][0])); } } } @@ -181,39 +214,50 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") SECTION("common mesh") { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr wh = std::make_shared<DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh); + DiscreteFunctionP0<Dimension, double> uh(mesh); + DiscreteFunctionP0<Dimension, double> vh(mesh); + DiscreteFunctionP0<Dimension, TinyVector<2>> wh(mesh); - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); + DiscreteFunctionP0<Dimension, double> qh(mesh_copy); - REQUIRE(getCommonMesh({uh, vh, wh}).get() == mesh.get()); - REQUIRE(getCommonMesh({uh, vh, wh, qh}).use_count() == 0); + std::shared_ptr uh_v = std::make_shared<DiscreteFunctionVariant>(uh); + std::shared_ptr vh_v = std::make_shared<DiscreteFunctionVariant>(vh); + std::shared_ptr wh_v = std::make_shared<DiscreteFunctionVariant>(wh); + std::shared_ptr qh_v = std::make_shared<DiscreteFunctionVariant>(qh); + + REQUIRE(getCommonMesh({uh_v, vh_v, wh_v}).get() == mesh.get()); + REQUIRE(getCommonMesh({uh_v, vh_v, wh_v, qh_v}).use_count() == 0); } SECTION("check discretization type") { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - - std::shared_ptr Uh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - std::shared_ptr Vh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - - REQUIRE(checkDiscretizationType({uh}, DiscreteFunctionType::P0)); - REQUIRE(checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({Uh}, DiscreteFunctionType::P0)); + DiscreteFunctionP0<Dimension, double> uh(mesh); + DiscreteFunctionP0<Dimension, double> vh(mesh); + DiscreteFunctionP0<Dimension, double> qh(mesh_copy); + + DiscreteFunctionP0Vector<Dimension, double> Uh(mesh, 3); + DiscreteFunctionP0Vector<Dimension, double> Vh(mesh, 3); + + auto uh_v = std::make_shared<DiscreteFunctionVariant>(uh); + auto vh_v = std::make_shared<DiscreteFunctionVariant>(vh); + auto qh_v = std::make_shared<DiscreteFunctionVariant>(qh); + auto Uh_v = std::make_shared<DiscreteFunctionVariant>(Uh); + auto Vh_v = std::make_shared<DiscreteFunctionVariant>(Vh); + + REQUIRE(checkDiscretizationType({uh_v}, DiscreteFunctionType::P0)); + REQUIRE(checkDiscretizationType({uh_v, vh_v, qh_v}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({uh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({uh_v, vh_v, qh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh_v, Vh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({Uh_v, Vh_v}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({Uh_v}, DiscreteFunctionType::P0)); } SECTION("scalar function shallow copy") { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const double>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, double>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -221,14 +265,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^1 function shallow copy") { - using DataType = TinyVector<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyVector<1>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -236,14 +281,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^2 function shallow copy") { - using DataType = TinyVector<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyVector<2>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -251,14 +297,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^3 function shallow copy") { - using DataType = TinyVector<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyVector<3>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -266,14 +313,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^1x1 function shallow copy") { - using DataType = TinyMatrix<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyMatrix<1>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -281,14 +329,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^2x2 function shallow copy") { - using DataType = TinyMatrix<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyMatrix<2>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -296,14 +345,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^3x3 function shallow copy") { - using DataType = TinyMatrix<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyMatrix<3>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -311,8 +361,24 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); + } + + SECTION("P0Vector function shallow copy") + { + using DiscreteFunctionT = DiscreteFunctionP0Vector<Dimension, const double>; + std::shared_ptr uh = + std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0Vector<Dimension, double>(mesh, 2)); + std::shared_ptr vh = shallowCopy(mesh, uh); + + REQUIRE(uh == vh); + + std::shared_ptr wh = shallowCopy(mesh_copy, uh); + + REQUIRE(uh != wh); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellArrays()[CellId{0}][0]) == + &(wh->get<DiscreteFunctionT>().cellArrays()[CellId{0}][0])); } } } @@ -334,39 +400,50 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") SECTION("common mesh") { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr wh = std::make_shared<DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh); + DiscreteFunctionP0<Dimension, double> uh(mesh); + DiscreteFunctionP0<Dimension, double> vh(mesh); + DiscreteFunctionP0<Dimension, TinyVector<2>> wh(mesh); + + DiscreteFunctionP0<Dimension, double> qh(mesh_copy); - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); + std::shared_ptr uh_v = std::make_shared<DiscreteFunctionVariant>(uh); + std::shared_ptr vh_v = std::make_shared<DiscreteFunctionVariant>(vh); + std::shared_ptr wh_v = std::make_shared<DiscreteFunctionVariant>(wh); + std::shared_ptr qh_v = std::make_shared<DiscreteFunctionVariant>(qh); - REQUIRE(getCommonMesh({uh, vh, wh}).get() == mesh.get()); - REQUIRE(getCommonMesh({uh, vh, wh, qh}).use_count() == 0); + REQUIRE(getCommonMesh({uh_v, vh_v, wh_v}).get() == mesh.get()); + REQUIRE(getCommonMesh({uh_v, vh_v, wh_v, qh_v}).use_count() == 0); } SECTION("check discretization type") { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - std::shared_ptr vh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); - - std::shared_ptr qh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_copy); - - std::shared_ptr Uh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - std::shared_ptr Vh = std::make_shared<DiscreteFunctionP0Vector<Dimension, double>>(mesh, 3); - - REQUIRE(checkDiscretizationType({uh}, DiscreteFunctionType::P0)); - REQUIRE(checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({uh, vh, qh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh}, DiscreteFunctionType::P0Vector)); - REQUIRE(checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0Vector)); - REQUIRE(not checkDiscretizationType({Uh, Vh}, DiscreteFunctionType::P0)); - REQUIRE(not checkDiscretizationType({Uh}, DiscreteFunctionType::P0)); + DiscreteFunctionP0<Dimension, double> uh(mesh); + DiscreteFunctionP0<Dimension, double> vh(mesh); + DiscreteFunctionP0<Dimension, double> qh(mesh_copy); + + DiscreteFunctionP0Vector<Dimension, double> Uh(mesh, 3); + DiscreteFunctionP0Vector<Dimension, double> Vh(mesh, 3); + + auto uh_v = std::make_shared<DiscreteFunctionVariant>(uh); + auto vh_v = std::make_shared<DiscreteFunctionVariant>(vh); + auto qh_v = std::make_shared<DiscreteFunctionVariant>(qh); + auto Uh_v = std::make_shared<DiscreteFunctionVariant>(Uh); + auto Vh_v = std::make_shared<DiscreteFunctionVariant>(Vh); + + REQUIRE(checkDiscretizationType({uh_v}, DiscreteFunctionType::P0)); + REQUIRE(checkDiscretizationType({uh_v, vh_v, qh_v}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({uh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({uh_v, vh_v, qh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(checkDiscretizationType({Uh_v, Vh_v}, DiscreteFunctionType::P0Vector)); + REQUIRE(not checkDiscretizationType({Uh_v, Vh_v}, DiscreteFunctionType::P0)); + REQUIRE(not checkDiscretizationType({Uh_v}, DiscreteFunctionType::P0)); } SECTION("scalar function shallow copy") { - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const double>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, double>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -374,14 +451,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^1 function shallow copy") { - using DataType = TinyVector<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyVector<1>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -389,14 +467,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^2 function shallow copy") { - using DataType = TinyVector<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyVector<2>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -404,14 +483,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^3 function shallow copy") { - using DataType = TinyVector<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyVector<3>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -419,14 +499,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^1x1 function shallow copy") { - using DataType = TinyMatrix<1>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyMatrix<1>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -434,14 +515,15 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^2x2 function shallow copy") { - using DataType = TinyMatrix<2>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyMatrix<2>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -449,14 +531,31 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); } SECTION("R^3x3 function shallow copy") { - using DataType = TinyMatrix<3>; - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, DataType>>(mesh); + using DataType = TinyMatrix<3>; + using DiscreteFunctionT = DiscreteFunctionP0<Dimension, const DataType>; + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, DataType>(mesh)); + std::shared_ptr vh = shallowCopy(mesh, uh); + + REQUIRE(uh == vh); + + std::shared_ptr wh = shallowCopy(mesh_copy, uh); + + REQUIRE(uh != wh); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellValues()[CellId{0}]) == + &(wh->get<DiscreteFunctionT>().cellValues()[CellId{0}])); + } + + SECTION("P0Vector function shallow copy") + { + using DiscreteFunctionT = DiscreteFunctionP0Vector<Dimension, const double>; + std::shared_ptr uh = + std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0Vector<Dimension, double>(mesh, 2)); std::shared_ptr vh = shallowCopy(mesh, uh); REQUIRE(uh == vh); @@ -464,8 +563,8 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr wh = shallowCopy(mesh_copy, uh); REQUIRE(uh != wh); - REQUIRE(&(uh->cellValues()[CellId{0}]) == - &(dynamic_cast<const DiscreteFunctionP0<Dimension, DataType>&>(*wh).cellValues()[CellId{0}])); + REQUIRE(&(uh->get<DiscreteFunctionT>().cellArrays()[CellId{0}][0]) == + &(wh->get<DiscreteFunctionT>().cellArrays()[CellId{0}][0])); } } } @@ -487,7 +586,7 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr other_mesh = CartesianMeshBuilder{TinyVector<1>{-1}, TinyVector<1>{3}, TinyVector<1, size_t>{19}}.mesh(); - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh); + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, double>(mesh)); REQUIRE_THROWS_WITH(shallowCopy(other_mesh, uh), "error: cannot shallow copy when connectivity changes"); } @@ -501,7 +600,7 @@ TEST_CASE("DiscreteFunctionUtils", "[scheme]") std::shared_ptr mesh_1d = MeshDataBaseForTests::get().cartesian1DMesh(); std::shared_ptr mesh_2d = MeshDataBaseForTests::get().cartesian2DMesh(); - std::shared_ptr uh = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh_1d); + std::shared_ptr uh = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionP0<Dimension, double>(mesh_1d)); REQUIRE_THROWS_WITH(shallowCopy(mesh_2d, uh), "error: incompatible mesh dimensions"); } diff --git a/tests/test_DiscreteFunctionVectorIntegrator.cpp b/tests/test_DiscreteFunctionVectorIntegrator.cpp index 848db0dfdb6af1d9efaa166411454aee626e67bb..4c510542ba9b244d505b7531db8d49f0c106bc2d 100644 --- a/tests/test_DiscreteFunctionVectorIntegrator.cpp +++ b/tests/test_DiscreteFunctionVectorIntegrator.cpp @@ -23,6 +23,7 @@ #include <scheme/DiscreteFunctionDescriptorP0Vector.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/DiscreteFunctionVectorIntegrator.hpp> #include <pegtl/string_input.hpp> @@ -100,7 +101,7 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; DiscreteFunctionVectorIntegrator integrator(mesh_1d, quadrature_descriptor, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); size_t i = 0; @@ -108,36 +109,32 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<1>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_1d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<1>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_1d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<1>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_1d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<1>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_1d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); @@ -193,7 +190,7 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; DiscreteFunctionVectorIntegrator integrator(mesh_2d, quadrature_descriptor, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); size_t i = 0; @@ -201,36 +198,32 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<2>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_2d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<2>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_2d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<2>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_2d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<2>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_2d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); @@ -286,7 +279,7 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; DiscreteFunctionVectorIntegrator integrator(mesh_3d, quadrature_descriptor, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); size_t i = 0; @@ -294,36 +287,32 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<3>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_3d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<3>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_3d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<3>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_3d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { CellValue<double> cell_value = IntegrateCellValue<double(TinyVector<3>)>::integrate(function_id_list[i], *quadrature_descriptor, *mesh_3d); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); diff --git a/tests/test_DiscreteFunctionVectorIntegratorByZone.cpp b/tests/test_DiscreteFunctionVectorIntegratorByZone.cpp index 98111d4c6b7f1dd4788745db480e72c06c083945..ac516d3ff9b7d20e3cedd152f522c7f7263e8acd 100644 --- a/tests/test_DiscreteFunctionVectorIntegratorByZone.cpp +++ b/tests/test_DiscreteFunctionVectorIntegratorByZone.cpp @@ -25,6 +25,7 @@ #include <scheme/DiscreteFunctionDescriptorP0Vector.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/DiscreteFunctionVectorIntegrator.hpp> #include <pegtl/string_input.hpp> @@ -103,7 +104,7 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; DiscreteFunctionVectorIntegrator integrator(mesh_1d, zone_list, quadrature_descriptor, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); size_t i = 0; @@ -121,8 +122,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -139,8 +140,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -157,8 +158,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -175,8 +176,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); @@ -231,7 +232,7 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; DiscreteFunctionVectorIntegrator integrator(mesh_2d, zone_list, quadrature_descriptor, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); size_t i = 0; @@ -249,8 +250,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -267,8 +268,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -285,8 +286,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -303,8 +304,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); @@ -359,7 +360,7 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; DiscreteFunctionVectorIntegrator integrator(mesh_3d, zone_list, quadrature_descriptor, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = integrator.integrate(); + DiscreteFunctionVariant discrete_function = integrator.integrate(); size_t i = 0; @@ -377,8 +378,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -395,8 +396,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -413,8 +414,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -431,8 +432,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; cell_value[cell_id] = array[j]; }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); diff --git a/tests/test_DiscreteFunctionVectorInterpoler.cpp b/tests/test_DiscreteFunctionVectorInterpoler.cpp index a52e0e7c84f9174e761a4953db9c98acdf2db496..e47b8754d7ff7fe46d8f90d903af2efaed06be51 100644 --- a/tests/test_DiscreteFunctionVectorInterpoler.cpp +++ b/tests/test_DiscreteFunctionVectorInterpoler.cpp @@ -20,6 +20,7 @@ #include <scheme/DiscreteFunctionDescriptorP0Vector.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/DiscreteFunctionVectorInterpoler.hpp> #include <pegtl/string_input.hpp> @@ -96,7 +97,7 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; DiscreteFunctionVectorInterpoler interpoler(mesh_1d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); size_t i = 0; @@ -108,9 +109,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; cell_value[cell_id] = std::exp(2 * x[0]) + 3 > 4; }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -121,9 +121,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; cell_value[cell_id] = std::floor(3 * x[0] * x[0] + 2); }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -134,9 +133,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; cell_value[cell_id] = std::floor(std::exp(2 * x[0]) - 1); }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -147,9 +145,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; cell_value[cell_id] = 2 * std::exp(x[0]) + 3; }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); @@ -204,7 +201,7 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; DiscreteFunctionVectorInterpoler interpoler(mesh_2d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); size_t i = 0; @@ -216,9 +213,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; cell_value[cell_id] = std::exp(2 * x[0]) + 3 > 4; }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -229,9 +225,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; cell_value[cell_id] = std::floor(3 * (x[0] * x[1]) * (x[0] * x[1]) + 2); }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -242,9 +237,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; cell_value[cell_id] = std::floor(std::exp(2 * x[1]) - 1); }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -255,9 +249,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; cell_value[cell_id] = 2 * std::exp(x[0] + x[1]) + 3; }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); @@ -312,7 +305,7 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; DiscreteFunctionVectorInterpoler interpoler(mesh_3d, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); size_t i = 0; @@ -324,9 +317,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; cell_value[cell_id] = std::exp(2 * x[0] + x[2]) + 3 > 4; }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -337,9 +329,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; cell_value[cell_id] = std::floor(3 * (x[0] * x[1]) * (x[0] * x[1]) + 2); }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -350,9 +341,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; cell_value[cell_id] = std::floor(std::exp(2 * x[1]) - x[2]); }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -363,9 +353,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; cell_value[cell_id] = 2 * std::exp(x[0] + x[1]) + 3 * x[2]; }); - REQUIRE( - same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE(same_cell_value(cell_value, i++, + discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); diff --git a/tests/test_DiscreteFunctionVectorInterpolerByZone.cpp b/tests/test_DiscreteFunctionVectorInterpolerByZone.cpp index 5bbe87d84f4204b9dd9a4dda985ded8f39aaf59c..2fe9849341741d0483202621f40cb45dbc4acc81 100644 --- a/tests/test_DiscreteFunctionVectorInterpolerByZone.cpp +++ b/tests/test_DiscreteFunctionVectorInterpolerByZone.cpp @@ -22,6 +22,7 @@ #include <scheme/DiscreteFunctionDescriptorP0Vector.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/DiscreteFunctionVectorInterpoler.hpp> #include <pegtl/string_input.hpp> @@ -105,7 +106,7 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; DiscreteFunctionVectorInterpoler interpoler(mesh_1d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); size_t i = 0; @@ -121,8 +122,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -137,8 +138,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -153,8 +154,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -169,8 +170,8 @@ let R_scalar_non_linear_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); @@ -230,7 +231,7 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; DiscreteFunctionVectorInterpoler interpoler(mesh_2d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); size_t i = 0; @@ -246,8 +247,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -262,8 +263,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -278,8 +279,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -294,8 +295,8 @@ let R_scalar_non_linear_2d: R^2 -> R, x -> 2 * exp(x[0] + x[1]) + 3; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); @@ -355,7 +356,7 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; DiscreteFunctionVectorInterpoler interpoler(mesh_3d, zone_list, std::make_shared<DiscreteFunctionDescriptorP0Vector>(), function_id_list); - std::shared_ptr discrete_function = interpoler.interpolate(); + DiscreteFunctionVariant discrete_function = interpoler.interpolate(); size_t i = 0; @@ -371,8 +372,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -387,8 +388,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -403,8 +404,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } { @@ -419,8 +420,8 @@ let R_scalar_non_linear_3d: R^3 -> R, x -> 2 * exp(x[0] + x[1]) + 3 * x[2]; } }); - REQUIRE(same_cell_value(cell_value, i++, - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*discrete_function))); + REQUIRE( + same_cell_value(cell_value, i++, discrete_function.get<DiscreteFunctionP0Vector<Dimension, const double>>())); } REQUIRE(i == function_id_list.size()); diff --git a/tests/test_Dual1DConnectivityBuilder.cpp b/tests/test_Dual1DConnectivityBuilder.cpp index 2b194a92baa821d6da4bac1e6277aaea6c1ddb1b..b7a35abfc577d93f729a0befc166c16c04f47fd3 100644 --- a/tests/test_Dual1DConnectivityBuilder.cpp +++ b/tests/test_Dual1DConnectivityBuilder.cpp @@ -5,6 +5,7 @@ #include <mesh/DualConnectivityManager.hpp> #include <mesh/Connectivity.hpp> +#include <mesh/ConnectivityUtils.hpp> #include <mesh/ItemValueUtils.hpp> #include <mesh/Mesh.hpp> @@ -48,6 +49,8 @@ TEST_CASE("Dual1DConnectivityBuilder", "[mesh]") DualConnectivityManager::instance().getDual1DConnectivity(primal_connectivity); const ConnectivityType& dual_connectivity = *p_dual_1d_connectivity; + REQUIRE(checkConnectivityOrdering(dual_connectivity)); + REQUIRE(dual_connectivity.numberOfNodes() == 36); REQUIRE(dual_connectivity.numberOfCells() == 35); diff --git a/tests/test_EmbeddedDiscreteFunctionMathFunctions.hpp b/tests/test_EmbeddedDiscreteFunctionMathFunctions.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bfa17ffc7609a8a304ee5dd36b3574782fbba464 --- /dev/null +++ b/tests/test_EmbeddedDiscreteFunctionMathFunctions.hpp @@ -0,0 +1,93 @@ +#ifndef TEST_EMBEDDED_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP +#define TEST_EMBEDDED_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP + +#define CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(P_U, FCT, U_TYPE, FU_TYPE) \ + { \ + std::shared_ptr p_fu = ::FCT(P_U); \ + \ + REQUIRE(p_fu.use_count() > 0); \ + \ + const U_TYPE& u = P_U->get<U_TYPE>(); \ + const FU_TYPE& fu = p_fu->get<FU_TYPE>(); \ + \ + bool is_same = true; \ + auto values = u.cellValues(); \ + for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { \ + using namespace std; \ + if (fu[cell_id] != FCT(values[cell_id])) { \ + is_same = false; \ + break; \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#define CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(P_U, P_V, FCT, U_TYPE, V_TYPE, FUV_TYPE) \ + { \ + std::shared_ptr p_fuv = ::FCT(P_U, P_V); \ + \ + REQUIRE(p_fuv.use_count() > 0); \ + \ + const U_TYPE& u = P_U->get<U_TYPE>(); \ + const V_TYPE& v = P_V->get<V_TYPE>(); \ + const FUV_TYPE& fuv = p_fuv->get<FUV_TYPE>(); \ + \ + bool is_same = true; \ + auto u_values = u.cellValues(); \ + auto v_values = v.cellValues(); \ + for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { \ + using namespace std; \ + if (fuv[cell_id] != FCT(u_values[cell_id], v_values[cell_id])) { \ + is_same = false; \ + break; \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#define CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(P_U, V, FCT, U_TYPE, FUV_TYPE) \ + { \ + std::shared_ptr p_fuv = ::FCT(P_U, V); \ + \ + REQUIRE(p_fuv.use_count() > 0); \ + const U_TYPE& u = P_U->get<U_TYPE>(); \ + const FUV_TYPE& fuv = p_fuv->get<FUV_TYPE>(); \ + \ + bool is_same = true; \ + auto u_values = u.cellValues(); \ + for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { \ + using namespace std; \ + if (fuv[cell_id] != FCT(u_values[cell_id], V)) { \ + is_same = false; \ + break; \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#define CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(U, P_V, FCT, V_TYPE, FUV_TYPE) \ + { \ + std::shared_ptr p_fuv = ::FCT(U, P_V); \ + \ + REQUIRE(p_fuv.use_count() > 0); \ + \ + const V_TYPE& v = P_V->get<V_TYPE>(); \ + const FUV_TYPE& fuv = p_fuv->get<FUV_TYPE>(); \ + \ + bool is_same = true; \ + auto v_values = v.cellValues(); \ + for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { \ + using namespace std; \ + if (fuv[cell_id] != FCT(U, v_values[cell_id])) { \ + is_same = false; \ + break; \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#endif // TEST_EMBEDDED_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP diff --git a/tests/test_EmbeddedDiscreteFunctionMathFunctions1D.cpp b/tests/test_EmbeddedDiscreteFunctionMathFunctions1D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ed0331dde90ba7270c0050a633a84982545a5e7b --- /dev/null +++ b/tests/test_EmbeddedDiscreteFunctionMathFunctions1D.cpp @@ -0,0 +1,715 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> + +#include <scheme/DiscreteFunctionP0.hpp> + +#include <language/utils/EmbeddedDiscreteFunctionMathFunctions.hpp> +#include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> + +#include <test_EmbeddedDiscreteFunctionMathFunctions.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") +{ + constexpr size_t Dimension = 1; + + using Rd = TinyVector<Dimension>; + + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + using DiscreteFunctionR = DiscreteFunctionP0<Dimension, const double>; + using DiscreteFunctionR1 = DiscreteFunctionP0<Dimension, const TinyVector<1>>; + using DiscreteFunctionR2 = DiscreteFunctionP0<Dimension, const TinyVector<2>>; + using DiscreteFunctionR3 = DiscreteFunctionP0<Dimension, const TinyVector<3>>; + using DiscreteFunctionR1x1 = DiscreteFunctionP0<Dimension, const TinyMatrix<1>>; + using DiscreteFunctionR2x2 = DiscreteFunctionP0<Dimension, const TinyMatrix<2>>; + using DiscreteFunctionR3x3 = DiscreteFunctionP0<Dimension, const TinyMatrix<3>>; + + using DiscreteFunctionVector = DiscreteFunctionP0Vector<Dimension, const double>; + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh = named_mesh.mesh(); + + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> positive_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> bounded_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_u = std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(mesh, values)); + std::shared_ptr p_other_mesh_u = + std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(other_mesh, values)); + std::shared_ptr p_positive_u = + std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(mesh, positive_values)); + std::shared_ptr p_bounded_u = + std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(mesh, bounded_values)); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, uj)); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R1_u = std::make_shared<const DiscreteFunctionVariant>( + DiscreteFunctionR1(other_mesh, p_R1_u->get<DiscreteFunctionR1>().cellValues())); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return TinyVector<2>{x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<2>{x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<2>{x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, uj)); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R2_u = std::make_shared<const DiscreteFunctionVariant>( + DiscreteFunctionR2(other_mesh, p_R2_u->get<DiscreteFunctionR2>().cellValues())); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<3>{x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<3>{x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, uj)); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R3_u = std::make_shared<const DiscreteFunctionVariant>( + DiscreteFunctionR3(other_mesh, p_R3_u->get<DiscreteFunctionR3>().cellValues())); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR1x1(mesh, uj)); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR2x2(mesh, uj)); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR3x3(mesh, uj)); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, uj_vector)); + }(); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, vj_vector)); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, wj_vector)); + }(); + + SECTION("sqrt Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, sqrt, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("abs Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, abs, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("sin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, sin, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("cos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, cos, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("tan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, tan, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("asin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, asin, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("acos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, acos, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("atan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, atan, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("sinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, sinh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("cosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, cosh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("tanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, tanh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("asinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, asinh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("acosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, acosh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("atanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, atanh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("exp Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, exp, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("log Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, log, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("atan2 Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + } + + SECTION("atan2 Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("atan2 R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("min Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } + + SECTION("min Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("min R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("min Vh -> R") + { + REQUIRE(min(p_u) == min(p_u->get<DiscreteFunctionR>().cellValues())); + REQUIRE_THROWS_WITH(min(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("max Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } + + SECTION("max Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("max Vh -> R") + { + REQUIRE(max(p_u) == max(p_u->get<DiscreteFunctionR>().cellValues())); + REQUIRE_THROWS_WITH(max(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("max R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("pow Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } + + SECTION("pow Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("pow R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("dot Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot, // + DiscreteFunctionR1, DiscreteFunctionR1, DiscreteFunctionR); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot, // + DiscreteFunctionR2, DiscreteFunctionR2, DiscreteFunctionR); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot, // + DiscreteFunctionR3, DiscreteFunctionR3, DiscreteFunctionR); + + { + std::shared_ptr p_fuv = ::dot(p_Vector3_u, p_Vector3_v); + + REQUIRE(p_fuv.use_count() > 0); + + const DiscreteFunctionVector& u = p_Vector3_u->get<DiscreteFunctionVector>(); + const DiscreteFunctionVector& v = p_Vector3_v->get<DiscreteFunctionVector>(); + const DiscreteFunctionR& fuv = p_fuv->get<DiscreteFunctionR>(); + + bool is_same = true; + auto u_arrays = u.cellArrays(); + auto v_arrays = v.cellArrays(); + for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { + using namespace std; + double dot_u_v = [&](auto&& a, auto&& b) { + double sum = 0; + for (size_t i = 0; i < a.size(); ++i) { + sum += a[i] * b[i]; + } + return sum; + }(u_arrays[cell_id], v_arrays[cell_id]); + if (fuv[cell_id] != dot_u_v) { + is_same = false; + break; + } + } + + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); + } + + SECTION("det Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, det, // + DiscreteFunctionR1x1, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, det, // + DiscreteFunctionR2x2, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, det, // + DiscreteFunctionR3x3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(det(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(det(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(det(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(det(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("trace Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, trace, // + DiscreteFunctionR1x1, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, trace, // + DiscreteFunctionR2x2, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, trace, // + DiscreteFunctionR3x3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(trace(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(trace(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(trace(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(trace(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("inverse Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, inverse, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, inverse, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, inverse, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(inverse(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(inverse(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(inverse(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(inverse(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("transpose Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, transpose, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, transpose, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, transpose, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(transpose(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(transpose(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(transpose(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(transpose(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("sum_of_Vh Vh -> Vh") + { + { + auto p_sum_components = sum_of_Vh_components(p_Vector3_u); + REQUIRE(p_sum_components.use_count() == 1); + + const DiscreteFunctionR& sum_components = p_sum_components->get<DiscreteFunctionR>(); + const DiscreteFunctionVector& vector3_u = p_Vector3_u->get<DiscreteFunctionVector>(); + DiscreteFunctionP0<Dimension, double> direct_sum(mesh); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + double sum = 0; + for (size_t i = 0; i < vector3_u.size(); ++i) { + sum += vector3_u[cell_id][i]; + } + + direct_sum[cell_id] = sum; + } + + bool is_same = true; + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + if (sum_components[cell_id] != direct_sum[cell_id]) { + is_same = false; + break; + } + } + + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(sum_of_Vh_components(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("vectorize (Vh) -> Vh") + { + { + std::shared_ptr p_vector3 = vectorize(std::vector{p_u, p_positive_u, p_bounded_u}); + REQUIRE(p_vector3.use_count() == 1); + + const DiscreteFunctionVector vector3 = p_vector3->get<DiscreteFunctionVector>(); + + const DiscreteFunctionR& u = p_u->get<DiscreteFunctionR>(); + const DiscreteFunctionR& positive_u = p_positive_u->get<DiscreteFunctionR>(); + const DiscreteFunctionR& bounded_u = p_bounded_u->get<DiscreteFunctionR>(); + + REQUIRE(vector3.size() == 3); + + bool is_same = true; + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + is_same &= (u[cell_id] == vector3[cell_id][0]); + is_same &= (positive_u[cell_id] == vector3[cell_id][1]); + is_same &= (bounded_u[cell_id] == vector3[cell_id][2]); + } + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(vectorize(std::vector{p_u, p_other_mesh_u}), + "error: discrete functions are not defined on the same mesh"); + REQUIRE_THROWS_WITH(vectorize(std::vector{p_R1_u}), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("dot Vh*Rd -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot, // + DiscreteFunctionR1, DiscreteFunctionR); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot, // + DiscreteFunctionR2, DiscreteFunctionR); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot, // + DiscreteFunctionR3, DiscreteFunctionR); + REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), + "error: incompatible operand types Vh(P0:R^1) and R^2"); + REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), + "error: incompatible operand types Vh(P0:R^2) and R^3"); + REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); + } + + SECTION("dot Rd*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot, // + DiscreteFunctionR1, DiscreteFunctionR); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot, // + DiscreteFunctionR2, DiscreteFunctionR); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot, // + DiscreteFunctionR3, DiscreteFunctionR); + REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), + "error: incompatible operand types R^2 and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), + "error: incompatible operand types R^3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); + } + + SECTION("sum_of_R* Vh -> R*") + { + REQUIRE(sum_of<double>(p_u) == sum(p_u->get<DiscreteFunctionR>().cellValues())); + REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->get<DiscreteFunctionR1>().cellValues())); + REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->get<DiscreteFunctionR2>().cellValues())); + REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->get<DiscreteFunctionR3>().cellValues())); + REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->get<DiscreteFunctionR1x1>().cellValues())); + REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->get<DiscreteFunctionR2x2>().cellValues())); + REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->get<DiscreteFunctionR3x3>().cellValues())); + + REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + + SECTION("integral_of_R* Vh -> R*") + { + auto integrate_locally = [&](const auto& cell_values) { + const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); + using DataType = decltype(double{} * cell_values[CellId{0}]); + CellValue<DataType> local_integral{mesh->connectivity()}; + parallel_for( + local_integral.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); + return local_integral; + }; + + REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->get<DiscreteFunctionR>().cellValues()))); + REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == + sum(integrate_locally(p_R1_u->get<DiscreteFunctionR1>().cellValues()))); + REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == + sum(integrate_locally(p_R2_u->get<DiscreteFunctionR2>().cellValues()))); + REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == + sum(integrate_locally(p_R3_u->get<DiscreteFunctionR3>().cellValues()))); + REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == + sum(integrate_locally(p_R1x1_u->get<DiscreteFunctionR1x1>().cellValues()))); + REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == + sum(integrate_locally(p_R2x2_u->get<DiscreteFunctionR2x2>().cellValues()))); + REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == + sum(integrate_locally(p_R3x3_u->get<DiscreteFunctionR3x3>().cellValues()))); + + REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + } + } +} diff --git a/tests/test_EmbeddedDiscreteFunctionMathFunctions2D.cpp b/tests/test_EmbeddedDiscreteFunctionMathFunctions2D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dfbdb01500b08f73dd9804d4d4581aafe4c4ba63 --- /dev/null +++ b/tests/test_EmbeddedDiscreteFunctionMathFunctions2D.cpp @@ -0,0 +1,718 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> + +#include <scheme/DiscreteFunctionP0.hpp> + +#include <language/utils/EmbeddedDiscreteFunctionMathFunctions.hpp> +#include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> + +#include <test_EmbeddedDiscreteFunctionMathFunctions.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") +{ + SECTION("2D") + { + constexpr size_t Dimension = 2; + + using Rd = TinyVector<Dimension>; + + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + using DiscreteFunctionR = DiscreteFunctionP0<Dimension, const double>; + using DiscreteFunctionR1 = DiscreteFunctionP0<Dimension, const TinyVector<1>>; + using DiscreteFunctionR2 = DiscreteFunctionP0<Dimension, const TinyVector<2>>; + using DiscreteFunctionR3 = DiscreteFunctionP0<Dimension, const TinyVector<3>>; + using DiscreteFunctionR1x1 = DiscreteFunctionP0<Dimension, const TinyMatrix<1>>; + using DiscreteFunctionR2x2 = DiscreteFunctionP0<Dimension, const TinyMatrix<2>>; + using DiscreteFunctionR3x3 = DiscreteFunctionP0<Dimension, const TinyMatrix<3>>; + + using DiscreteFunctionVector = DiscreteFunctionP0Vector<Dimension, const double>; + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh = named_mesh.mesh(); + + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> positive_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> bounded_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_u = std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(mesh, values)); + std::shared_ptr p_other_mesh_u = + std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(other_mesh, values)); + std::shared_ptr p_positive_u = + std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(mesh, positive_values)); + std::shared_ptr p_bounded_u = + std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(mesh, bounded_values)); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, uj)); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R1_u = std::make_shared<const DiscreteFunctionVariant>( + DiscreteFunctionR1(other_mesh, p_R1_u->get<DiscreteFunctionR1>().cellValues())); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return TinyVector<2>{x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<2>{x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<2>{x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, uj)); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R2_u = std::make_shared<const DiscreteFunctionVariant>( + DiscreteFunctionR2(other_mesh, p_R2_u->get<DiscreteFunctionR2>().cellValues())); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<3>{x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<3>{x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, uj)); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R3_u = std::make_shared<const DiscreteFunctionVariant>( + DiscreteFunctionR3(other_mesh, p_R3_u->get<DiscreteFunctionR3>().cellValues())); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR1x1(mesh, uj)); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR2x2(mesh, uj)); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR3x3(mesh, uj)); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, uj_vector)); + }(); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, vj_vector)); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, wj_vector)); + }(); + + SECTION("sqrt Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, sqrt, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("abs Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, abs, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("sin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, sin, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("cos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, cos, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("tan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, tan, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("asin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, asin, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("acos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, acos, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("atan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, atan, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("sinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, sinh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("cosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, cosh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("tanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, tanh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("asinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, asinh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("acosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, acosh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("atanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, atanh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("exp Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, exp, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("log Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, log, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("atan2 Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + } + + SECTION("atan2 Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("atan2 R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("min Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } + + SECTION("min Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("min R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("min Vh -> R") + { + REQUIRE(min(p_u) == min(p_u->get<DiscreteFunctionR>().cellValues())); + REQUIRE_THROWS_WITH(min(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("max Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } + + SECTION("max Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("max Vh -> R") + { + REQUIRE(max(p_u) == max(p_u->get<DiscreteFunctionR>().cellValues())); + REQUIRE_THROWS_WITH(max(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("max R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("pow Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } + + SECTION("pow Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("pow R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("dot Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot, // + DiscreteFunctionR1, DiscreteFunctionR1, DiscreteFunctionR); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot, // + DiscreteFunctionR2, DiscreteFunctionR2, DiscreteFunctionR); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot, // + DiscreteFunctionR3, DiscreteFunctionR3, DiscreteFunctionR); + + { + std::shared_ptr p_fuv = ::dot(p_Vector3_u, p_Vector3_v); + + REQUIRE(p_fuv.use_count() > 0); + + const DiscreteFunctionVector& u = p_Vector3_u->get<DiscreteFunctionVector>(); + const DiscreteFunctionVector& v = p_Vector3_v->get<DiscreteFunctionVector>(); + const DiscreteFunctionR& fuv = p_fuv->get<DiscreteFunctionR>(); + + bool is_same = true; + auto u_arrays = u.cellArrays(); + auto v_arrays = v.cellArrays(); + for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { + using namespace std; + double dot_u_v = [&](auto&& a, auto&& b) { + double sum = 0; + for (size_t i = 0; i < a.size(); ++i) { + sum += a[i] * b[i]; + } + return sum; + }(u_arrays[cell_id], v_arrays[cell_id]); + if (fuv[cell_id] != dot_u_v) { + is_same = false; + break; + } + } + + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); + } + + SECTION("det Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, det, // + DiscreteFunctionR1x1, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, det, // + DiscreteFunctionR2x2, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, det, // + DiscreteFunctionR3x3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(det(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(det(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(det(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(det(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("trace Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, trace, // + DiscreteFunctionR1x1, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, trace, // + DiscreteFunctionR2x2, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, trace, // + DiscreteFunctionR3x3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(trace(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(trace(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(trace(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(trace(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("inverse Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, inverse, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, inverse, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, inverse, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(inverse(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(inverse(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(inverse(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(inverse(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("transpose Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, transpose, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, transpose, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, transpose, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(transpose(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(transpose(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(transpose(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(transpose(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("sum_of_Vh Vh -> Vh") + { + { + auto p_sum_components = sum_of_Vh_components(p_Vector3_u); + REQUIRE(p_sum_components.use_count() == 1); + + const DiscreteFunctionR& sum_components = p_sum_components->get<DiscreteFunctionR>(); + const DiscreteFunctionVector& vector3_u = p_Vector3_u->get<DiscreteFunctionVector>(); + DiscreteFunctionP0<Dimension, double> direct_sum(mesh); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + double sum = 0; + for (size_t i = 0; i < vector3_u.size(); ++i) { + sum += vector3_u[cell_id][i]; + } + + direct_sum[cell_id] = sum; + } + + bool is_same = true; + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + if (sum_components[cell_id] != direct_sum[cell_id]) { + is_same = false; + break; + } + } + + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(sum_of_Vh_components(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("vectorize (Vh) -> Vh") + { + { + std::shared_ptr p_vector3 = vectorize(std::vector{p_u, p_positive_u, p_bounded_u}); + REQUIRE(p_vector3.use_count() == 1); + + const DiscreteFunctionVector vector3 = p_vector3->get<DiscreteFunctionVector>(); + + const DiscreteFunctionR& u = p_u->get<DiscreteFunctionR>(); + const DiscreteFunctionR& positive_u = p_positive_u->get<DiscreteFunctionR>(); + const DiscreteFunctionR& bounded_u = p_bounded_u->get<DiscreteFunctionR>(); + + REQUIRE(vector3.size() == 3); + + bool is_same = true; + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + is_same &= (u[cell_id] == vector3[cell_id][0]); + is_same &= (positive_u[cell_id] == vector3[cell_id][1]); + is_same &= (bounded_u[cell_id] == vector3[cell_id][2]); + } + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(vectorize(std::vector{p_u, p_other_mesh_u}), + "error: discrete functions are not defined on the same mesh"); + REQUIRE_THROWS_WITH(vectorize(std::vector{p_R1_u}), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("dot Vh*Rd -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot, // + DiscreteFunctionR1, DiscreteFunctionR); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot, // + DiscreteFunctionR2, DiscreteFunctionR); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot, // + DiscreteFunctionR3, DiscreteFunctionR); + REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), + "error: incompatible operand types Vh(P0:R^1) and R^2"); + REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), + "error: incompatible operand types Vh(P0:R^2) and R^3"); + REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); + } + + SECTION("dot Rd*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot, // + DiscreteFunctionR1, DiscreteFunctionR); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot, // + DiscreteFunctionR2, DiscreteFunctionR); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot, // + DiscreteFunctionR3, DiscreteFunctionR); + REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), + "error: incompatible operand types R^2 and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), + "error: incompatible operand types R^3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); + } + + SECTION("sum_of_R* Vh -> R*") + { + REQUIRE(sum_of<double>(p_u) == sum(p_u->get<DiscreteFunctionR>().cellValues())); + REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->get<DiscreteFunctionR1>().cellValues())); + REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->get<DiscreteFunctionR2>().cellValues())); + REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->get<DiscreteFunctionR3>().cellValues())); + REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->get<DiscreteFunctionR1x1>().cellValues())); + REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->get<DiscreteFunctionR2x2>().cellValues())); + REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->get<DiscreteFunctionR3x3>().cellValues())); + + REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + + SECTION("integral_of_R* Vh -> R*") + { + auto integrate_locally = [&](const auto& cell_values) { + const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); + using DataType = decltype(double{} * cell_values[CellId{0}]); + CellValue<DataType> local_integral{mesh->connectivity()}; + parallel_for( + local_integral.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); + return local_integral; + }; + + REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->get<DiscreteFunctionR>().cellValues()))); + REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == + sum(integrate_locally(p_R1_u->get<DiscreteFunctionR1>().cellValues()))); + REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == + sum(integrate_locally(p_R2_u->get<DiscreteFunctionR2>().cellValues()))); + REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == + sum(integrate_locally(p_R3_u->get<DiscreteFunctionR3>().cellValues()))); + REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == + sum(integrate_locally(p_R1x1_u->get<DiscreteFunctionR1x1>().cellValues()))); + REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == + sum(integrate_locally(p_R2x2_u->get<DiscreteFunctionR2x2>().cellValues()))); + REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == + sum(integrate_locally(p_R3x3_u->get<DiscreteFunctionR3x3>().cellValues()))); + + REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + } + } + } +} diff --git a/tests/test_EmbeddedDiscreteFunctionMathFunctions3D.cpp b/tests/test_EmbeddedDiscreteFunctionMathFunctions3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f9896ad64df5601f54f9d701fc5bfe94f4d51b9 --- /dev/null +++ b/tests/test_EmbeddedDiscreteFunctionMathFunctions3D.cpp @@ -0,0 +1,715 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> + +#include <scheme/DiscreteFunctionP0.hpp> + +#include <language/utils/EmbeddedDiscreteFunctionMathFunctions.hpp> +#include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> + +#include <test_EmbeddedDiscreteFunctionMathFunctions.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") +{ + constexpr size_t Dimension = 3; + + using Rd = TinyVector<Dimension>; + + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + using DiscreteFunctionR = DiscreteFunctionP0<Dimension, const double>; + using DiscreteFunctionR1 = DiscreteFunctionP0<Dimension, const TinyVector<1>>; + using DiscreteFunctionR2 = DiscreteFunctionP0<Dimension, const TinyVector<2>>; + using DiscreteFunctionR3 = DiscreteFunctionP0<Dimension, const TinyVector<3>>; + using DiscreteFunctionR1x1 = DiscreteFunctionP0<Dimension, const TinyMatrix<1>>; + using DiscreteFunctionR2x2 = DiscreteFunctionP0<Dimension, const TinyMatrix<2>>; + using DiscreteFunctionR3x3 = DiscreteFunctionP0<Dimension, const TinyMatrix<3>>; + + using DiscreteFunctionVector = DiscreteFunctionP0Vector<Dimension, const double>; + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh = named_mesh.mesh(); + + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> positive_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> bounded_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_u = std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(mesh, values)); + std::shared_ptr p_other_mesh_u = + std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(other_mesh, values)); + std::shared_ptr p_positive_u = + std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(mesh, positive_values)); + std::shared_ptr p_bounded_u = + std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR(mesh, bounded_values)); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, uj)); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R1_u = std::make_shared<const DiscreteFunctionVariant>( + DiscreteFunctionR1(other_mesh, p_R1_u->get<DiscreteFunctionR1>().cellValues())); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return TinyVector<2>{x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<2>{x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<2>{x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, uj)); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R2_u = std::make_shared<const DiscreteFunctionVariant>( + DiscreteFunctionR2(other_mesh, p_R2_u->get<DiscreteFunctionR2>().cellValues())); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<3>{x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<3>{x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, uj)); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R3_u = std::make_shared<const DiscreteFunctionVariant>( + DiscreteFunctionR3(other_mesh, p_R3_u->get<DiscreteFunctionR3>().cellValues())); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR1x1(mesh, uj)); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR2x2(mesh, uj)); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionR3x3(mesh, uj)); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, uj_vector)); + }(); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, vj_vector)); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<const DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, wj_vector)); + }(); + + SECTION("sqrt Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, sqrt, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("abs Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, abs, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("sin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, sin, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("cos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, cos, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("tan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, tan, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("asin Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, asin, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("acos Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, acos, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("atan Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, atan, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("sinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, sinh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("cosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, cosh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("tanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, tanh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("asinh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, asinh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("acosh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, acosh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("atanh Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_bounded_u, atanh, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("exp Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_u, exp, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("log Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_positive_u, log, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("atan2 Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + } + + SECTION("atan2 Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("atan2 R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("min Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } + + SECTION("min Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("min R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("min Vh -> R") + { + REQUIRE(min(p_u) == min(p_u->get<DiscreteFunctionR>().cellValues())); + REQUIRE_THROWS_WITH(min(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("max Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } + + SECTION("max Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("max Vh -> R") + { + REQUIRE(max(p_u) == max(p_u->get<DiscreteFunctionR>().cellValues())); + REQUIRE_THROWS_WITH(max(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("max R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("pow Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); + } + + SECTION("pow Vh*R -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); + } + + SECTION("pow R*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow, // + DiscreteFunctionR, DiscreteFunctionR); + REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); + } + + SECTION("dot Vh*Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot, // + DiscreteFunctionR1, DiscreteFunctionR1, DiscreteFunctionR); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot, // + DiscreteFunctionR2, DiscreteFunctionR2, DiscreteFunctionR); + CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot, // + DiscreteFunctionR3, DiscreteFunctionR3, DiscreteFunctionR); + + { + std::shared_ptr p_fuv = ::dot(p_Vector3_u, p_Vector3_v); + + REQUIRE(p_fuv.use_count() > 0); + + const DiscreteFunctionVector& u = p_Vector3_u->get<DiscreteFunctionVector>(); + const DiscreteFunctionVector& v = p_Vector3_v->get<DiscreteFunctionVector>(); + const DiscreteFunctionR& fuv = p_fuv->get<DiscreteFunctionR>(); + + bool is_same = true; + auto u_arrays = u.cellArrays(); + auto v_arrays = v.cellArrays(); + for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { + using namespace std; + double dot_u_v = [&](auto&& a, auto&& b) { + double sum = 0; + for (size_t i = 0; i < a.size(); ++i) { + sum += a[i] * b[i]; + } + return sum; + }(u_arrays[cell_id], v_arrays[cell_id]); + if (fuv[cell_id] != dot_u_v) { + is_same = false; + break; + } + } + + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); + } + + SECTION("det Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, det, // + DiscreteFunctionR1x1, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, det, // + DiscreteFunctionR2x2, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, det, // + DiscreteFunctionR3x3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(det(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(det(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(det(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(det(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("trace Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, trace, // + DiscreteFunctionR1x1, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, trace, // + DiscreteFunctionR2x2, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, trace, // + DiscreteFunctionR3x3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(trace(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(trace(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(trace(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(trace(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("inverse Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, inverse, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, inverse, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, inverse, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(inverse(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(inverse(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(inverse(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(inverse(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("transpose Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R1x1_u, transpose, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R2x2_u, transpose, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + + CHECK_EMBEDDED_VH_TO_VH_FUNCTION_EVALUATION(p_R3x3_u, transpose, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(transpose(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(transpose(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(transpose(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(transpose(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("sum_of_Vh Vh -> Vh") + { + { + auto p_sum_components = sum_of_Vh_components(p_Vector3_u); + REQUIRE(p_sum_components.use_count() == 1); + + const DiscreteFunctionR& sum_components = p_sum_components->get<DiscreteFunctionR>(); + const DiscreteFunctionVector& vector3_u = p_Vector3_u->get<DiscreteFunctionVector>(); + DiscreteFunctionP0<Dimension, double> direct_sum(mesh); + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + double sum = 0; + for (size_t i = 0; i < vector3_u.size(); ++i) { + sum += vector3_u[cell_id][i]; + } + + direct_sum[cell_id] = sum; + } + + bool is_same = true; + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + if (sum_components[cell_id] != direct_sum[cell_id]) { + is_same = false; + break; + } + } + + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(sum_of_Vh_components(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + } + + SECTION("vectorize (Vh) -> Vh") + { + { + std::shared_ptr p_vector3 = vectorize(std::vector{p_u, p_positive_u, p_bounded_u}); + REQUIRE(p_vector3.use_count() == 1); + + const DiscreteFunctionVector vector3 = p_vector3->get<DiscreteFunctionVector>(); + + const DiscreteFunctionR& u = p_u->get<DiscreteFunctionR>(); + const DiscreteFunctionR& positive_u = p_positive_u->get<DiscreteFunctionR>(); + const DiscreteFunctionR& bounded_u = p_bounded_u->get<DiscreteFunctionR>(); + + REQUIRE(vector3.size() == 3); + + bool is_same = true; + for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { + is_same &= (u[cell_id] == vector3[cell_id][0]); + is_same &= (positive_u[cell_id] == vector3[cell_id][1]); + is_same &= (bounded_u[cell_id] == vector3[cell_id][2]); + } + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(vectorize(std::vector{p_u, p_other_mesh_u}), + "error: discrete functions are not defined on the same mesh"); + REQUIRE_THROWS_WITH(vectorize(std::vector{p_R1_u}), "error: invalid operand type Vh(P0:R^1)"); + } + + SECTION("dot Vh*Rd -> Vh") + { + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot, // + DiscreteFunctionR1, DiscreteFunctionR); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot, // + DiscreteFunctionR2, DiscreteFunctionR); + CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot, // + DiscreteFunctionR3, DiscreteFunctionR); + REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), + "error: incompatible operand types Vh(P0:R^1) and R^2"); + REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), + "error: incompatible operand types Vh(P0:R^2) and R^3"); + REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); + } + + SECTION("dot Rd*Vh -> Vh") + { + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot, // + DiscreteFunctionR1, DiscreteFunctionR); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot, // + DiscreteFunctionR2, DiscreteFunctionR); + CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot, // + DiscreteFunctionR3, DiscreteFunctionR); + REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), + "error: incompatible operand types R^2 and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), + "error: incompatible operand types R^3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); + } + + SECTION("sum_of_R* Vh -> R*") + { + REQUIRE(sum_of<double>(p_u) == sum(p_u->get<DiscreteFunctionR>().cellValues())); + REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->get<DiscreteFunctionR1>().cellValues())); + REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->get<DiscreteFunctionR2>().cellValues())); + REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->get<DiscreteFunctionR3>().cellValues())); + REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->get<DiscreteFunctionR1x1>().cellValues())); + REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->get<DiscreteFunctionR2x2>().cellValues())); + REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->get<DiscreteFunctionR3x3>().cellValues())); + + REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + + SECTION("integral_of_R* Vh -> R*") + { + auto integrate_locally = [&](const auto& cell_values) { + const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); + using DataType = decltype(double{} * cell_values[CellId{0}]); + CellValue<DataType> local_integral{mesh->connectivity()}; + parallel_for( + local_integral.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); + return local_integral; + }; + + REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->get<DiscreteFunctionR>().cellValues()))); + REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == + sum(integrate_locally(p_R1_u->get<DiscreteFunctionR1>().cellValues()))); + REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == + sum(integrate_locally(p_R2_u->get<DiscreteFunctionR2>().cellValues()))); + REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == + sum(integrate_locally(p_R3_u->get<DiscreteFunctionR3>().cellValues()))); + REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == + sum(integrate_locally(p_R1x1_u->get<DiscreteFunctionR1x1>().cellValues()))); + REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == + sum(integrate_locally(p_R2x2_u->get<DiscreteFunctionR2x2>().cellValues()))); + REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == + sum(integrate_locally(p_R3x3_u->get<DiscreteFunctionR3x3>().cellValues()))); + + REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + } + } + } +} diff --git a/tests/test_EmbeddedDiscreteFunctionOperators.hpp b/tests/test_EmbeddedDiscreteFunctionOperators.hpp new file mode 100644 index 0000000000000000000000000000000000000000..93faf56eb06d16469a89bd54206620ee98e0e74d --- /dev/null +++ b/tests/test_EmbeddedDiscreteFunctionOperators.hpp @@ -0,0 +1,177 @@ +#ifndef TEST_EMBEDDED_DISCRETE_FUNCTION_OPERATORS_HPP +#define TEST_EMBEDDED_DISCRETE_FUNCTION_OPERATORS_HPP + +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> + +#include <language/utils/EmbeddedDiscreteFunctionOperators.hpp> +#include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionP0Vector.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> + +// clazy:excludeall=non-pod-global-static + +#define CHECK_EMBEDDED_VH2_TO_VH(P_U, OPERATOR, P_V, U_TYPE, V_TYPE, U_OP_V_TYPE) \ + { \ + std::shared_ptr p_u_op_v = P_U OPERATOR P_V; \ + \ + REQUIRE(p_u_op_v.use_count() > 0); \ + \ + auto u_op_v = p_u_op_v->get<U_OP_V_TYPE>().cellValues(); \ + \ + auto u_values = P_U->get<U_TYPE>().cellValues(); \ + auto v_values = P_V->get<V_TYPE>().cellValues(); \ + bool is_same = true; \ + for (CellId cell_id = 0; cell_id < u_values.numberOfItems(); ++cell_id) { \ + if (u_op_v[cell_id] != (u_values[cell_id] OPERATOR v_values[cell_id])) { \ + is_same = false; \ + break; \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#define CHECK_EMBEDDED_VECTOR_VH2_TO_VH(P_U, OPERATOR, P_V, TYPE) \ + { \ + std::shared_ptr p_u_op_v = P_U OPERATOR P_V; \ + \ + REQUIRE(p_u_op_v.use_count() > 0); \ + \ + auto u_op_v_arrays = p_u_op_v->get<TYPE>().cellArrays(); \ + \ + auto u_arrays = P_U->get<TYPE>().cellArrays(); \ + auto v_arrays = P_V->get<TYPE>().cellArrays(); \ + \ + REQUIRE(u_arrays.sizeOfArrays() > 0); \ + REQUIRE(u_arrays.sizeOfArrays() == v_arrays.sizeOfArrays()); \ + REQUIRE(u_arrays.sizeOfArrays() == u_op_v_arrays.sizeOfArrays()); \ + \ + bool is_same = true; \ + for (CellId cell_id = 0; cell_id < u_arrays.numberOfItems(); ++cell_id) { \ + for (size_t i = 0; i < u_arrays.sizeOfArrays(); ++i) { \ + if (u_op_v_arrays[cell_id][i] != (u_arrays[cell_id][i] OPERATOR v_arrays[cell_id][i])) { \ + is_same = false; \ + break; \ + } \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#define CHECK_EMBEDDED_VHxX_TO_VH(P_U, OPERATOR, V, U_TYPE, U_OP_V_TYPE) \ + { \ + std::shared_ptr p_u_op_v = P_U OPERATOR V; \ + \ + REQUIRE(p_u_op_v.use_count() > 0); \ + \ + auto u_op_v = p_u_op_v->get<U_OP_V_TYPE>().cellValues(); \ + \ + auto u_values = P_U->get<U_TYPE>().cellValues(); \ + bool is_same = true; \ + for (CellId cell_id = 0; cell_id < u_values.numberOfItems(); ++cell_id) { \ + if (u_op_v[cell_id] != (u_values[cell_id] OPERATOR V)) { \ + is_same = false; \ + break; \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#define CHECK_EMBEDDED_XxVH_TO_VH(U, OPERATOR, P_V, V_TYPE, U_OP_V_TYPE) \ + { \ + std::shared_ptr p_u_op_v = U OPERATOR P_V; \ + \ + REQUIRE(p_u_op_v.use_count() > 0); \ + \ + auto u_op_v = p_u_op_v->get<U_OP_V_TYPE>().cellValues(); \ + \ + auto v_values = P_V->get<V_TYPE>().cellValues(); \ + bool is_same = true; \ + for (CellId cell_id = 0; cell_id < v_values.numberOfItems(); ++cell_id) { \ + if (u_op_v[cell_id] != (U OPERATOR v_values[cell_id])) { \ + is_same = false; \ + break; \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#define CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(U, OPERATOR, P_V, TYPE) \ + { \ + std::shared_ptr p_u_op_v = U OPERATOR P_V; \ + \ + REQUIRE(p_u_op_v.use_count() > 0); \ + \ + auto u_op_v = p_u_op_v->get<TYPE>().cellArrays(); \ + \ + auto v_arrays = P_V->get<TYPE>().cellArrays(); \ + \ + REQUIRE(v_arrays.numberOfItems() == u_op_v.numberOfItems()); \ + REQUIRE(v_arrays.sizeOfArrays() == u_op_v.sizeOfArrays()); \ + \ + bool is_same = true; \ + for (CellId cell_id = 0; cell_id < v_arrays.numberOfItems(); ++cell_id) { \ + for (size_t i = 0; i < v_arrays.sizeOfArrays(); ++i) { \ + if (u_op_v[cell_id][i] != (U OPERATOR v_arrays[cell_id][i])) { \ + is_same = false; \ + std::clog << u_op_v[cell_id][i] << " !=" << (U OPERATOR v_arrays[cell_id][i]) << '\n'; \ + } \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#define CHECK_EMBEDDED_VH_TO_VH(OPERATOR, P_U, U_TYPE) \ + { \ + std::shared_ptr p_op_u = OPERATOR P_U; \ + \ + REQUIRE(p_op_u.use_count() > 0); \ + \ + auto op_u = p_op_u->get<U_TYPE>().cellValues(); \ + \ + auto u_values = P_U->get<U_TYPE>().cellValues(); \ + bool is_same = true; \ + for (CellId cell_id = 0; cell_id < u_values.numberOfItems(); ++cell_id) { \ + if (op_u[cell_id] != (OPERATOR u_values[cell_id])) { \ + is_same = false; \ + break; \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#define CHECK_EMBEDDED_VECTOR_VH_TO_VH(OPERATOR, P_U, TYPE) \ + { \ + std::shared_ptr p_op_u = OPERATOR P_U; \ + \ + REQUIRE(p_op_u.use_count() > 0); \ + \ + auto op_u_arrays = p_op_u->get<TYPE>().cellArrays(); \ + \ + auto u_arrays = P_U->get<TYPE>().cellArrays(); \ + \ + REQUIRE(u_arrays.sizeOfArrays() == op_u_arrays.sizeOfArrays()); \ + REQUIRE(u_arrays.numberOfItems() == op_u_arrays.numberOfItems()); \ + \ + bool is_same = true; \ + for (CellId cell_id = 0; cell_id < u_arrays.numberOfItems(); ++cell_id) { \ + for (size_t i = 0; i < u_arrays.sizeOfArrays(); ++i) { \ + if (op_u_arrays[cell_id][i] != (OPERATOR u_arrays[cell_id][i])) { \ + is_same = false; \ + break; \ + } \ + } \ + } \ + \ + REQUIRE(is_same); \ + } + +#endif // TEST_EMBEDDED_DISCRETE_FUNCTION_OPERATORS_HPP diff --git a/tests/test_EmbeddedDiscreteFunctionOperators1D.cpp b/tests/test_EmbeddedDiscreteFunctionOperators1D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5538543de393bd2fb8009e3d2cbd04d57107ead3 --- /dev/null +++ b/tests/test_EmbeddedDiscreteFunctionOperators1D.cpp @@ -0,0 +1,862 @@ +#include <test_EmbeddedDiscreteFunctionOperators.hpp> + +#ifdef __clang__ +#pragma clang optimize off +#endif // __clang__ + +TEST_CASE("EmbeddedDiscreteFunctionOperators1D", "[scheme]") +{ + constexpr size_t Dimension = 1; + + using Rd = TinyVector<Dimension>; + + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + using DiscreteFunctionR = DiscreteFunctionP0<Dimension, const double>; + using DiscreteFunctionR1 = DiscreteFunctionP0<Dimension, const TinyVector<1>>; + using DiscreteFunctionR2 = DiscreteFunctionP0<Dimension, const TinyVector<2>>; + using DiscreteFunctionR3 = DiscreteFunctionP0<Dimension, const TinyVector<3>>; + using DiscreteFunctionR1x1 = DiscreteFunctionP0<Dimension, const TinyMatrix<1>>; + using DiscreteFunctionR2x2 = DiscreteFunctionP0<Dimension, const TinyMatrix<2>>; + using DiscreteFunctionR3x3 = DiscreteFunctionP0<Dimension, const TinyMatrix<3>>; + + using DiscreteFunctionVector = DiscreteFunctionP0Vector<Dimension, const double>; + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh = named_mesh.mesh(); + + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> u_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> v_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_R_u = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR(mesh, u_R_values)); + std::shared_ptr p_other_mesh_R_u = + std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR(other_mesh, u_R_values)); + std::shared_ptr p_R_v = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR(mesh, v_R_values)); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, uj)); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R1_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR1(other_mesh, p_R1_u->get<DiscreteFunctionR1>().cellValues())); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return TinyVector<2>{x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<2>{x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<2>{x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, uj)); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R2_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR2(other_mesh, p_R2_u->get<DiscreteFunctionR2>().cellValues())); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<3>{x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<3>{x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, uj)); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R3_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR3(other_mesh, p_R3_u->get<DiscreteFunctionR3>().cellValues())); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1x1(mesh, uj)); + }(); + + std::shared_ptr p_other_mesh_R1x1_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR1x1(other_mesh, p_R1x1_u->get<DiscreteFunctionR1x1>().cellValues())); + + std::shared_ptr p_R1x1_v = [=] { + CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = TinyMatrix<1>{0.3 - xj[cell_id][0]}; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1x1(mesh, vj)); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2x2(mesh, uj)); + }(); + + std::shared_ptr p_other_mesh_R2x2_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR2x2(other_mesh, p_R2x2_u->get<DiscreteFunctionR2x2>().cellValues())); + + std::shared_ptr p_R2x2_v = [=] { + CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + vj[cell_id] = TinyMatrix<2>{x[0] + 0.3, 1 - x[1] - x[0], // + 2 * x[1] + x[0], x[1] - x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2x2(mesh, vj)); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3x3(mesh, uj)); + }(); + + std::shared_ptr p_other_mesh_R3x3_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR3x3(other_mesh, p_R3x3_u->get<DiscreteFunctionR3x3>().cellValues())); + + std::shared_ptr p_R3x3_v = [=] { + CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + vj[cell_id] = TinyMatrix<3>{0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // + 2.3 * x[2], x[1] - x[0], x[2] - x[1], // + 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3x3(mesh, vj)); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, uj_vector)); + }(); + + std::shared_ptr p_other_mesh_Vector3_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionVector(other_mesh, p_Vector3_u->get<DiscreteFunctionVector>().cellArrays())); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, vj_vector)); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, wj_vector)); + }(); + + SECTION("binary operators") + { + SECTION("sum") + { + SECTION("Vh + Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, +, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1_u, +, p_R1_v, // + DiscreteFunctionR1, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2_u, +, p_R2_v, // + DiscreteFunctionR2, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3_u, +, p_R3_v, // + DiscreteFunctionR3, DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v, DiscreteFunctionVector); + + REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } + + SECTION("Vh + X -> Vh") + { + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, bool{true}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, uint64_t{1}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, int64_t{2}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, double{1.3}, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3}), // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3}), // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2}), // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, +, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } + + SECTION("X + Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + +, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } + + SECTION("difference") + { + SECTION("Vh - Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, -, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1_u, -, p_R1_v, // + DiscreteFunctionR1, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2_u, -, p_R2_v, // + DiscreteFunctionR2, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3_u, -, p_R3_v, // + DiscreteFunctionR3, DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v, DiscreteFunctionVector); + + REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } + + SECTION("Vh - X -> Vh") + { + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, bool{true}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, uint64_t{1}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, int64_t{2}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, double{1.3}, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3}), // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3}), // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2}), // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, -, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } + + SECTION("X - Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + -, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } + + SECTION("product") + { + SECTION("Vh * Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R1_v, // + DiscreteFunctionR, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R2_v, // + DiscreteFunctionR, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R3_v, // + DiscreteFunctionR, DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R1x1_v, // + DiscreteFunctionR, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R2x2_v, // + DiscreteFunctionR, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R3x3_v, // + DiscreteFunctionR, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, *, p_R1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, *, p_R2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, *, p_R3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3, DiscreteFunctionR3); + + { + std::shared_ptr p_u_op_v = p_R_u * p_Vector3_v; + + REQUIRE(p_u_op_v.use_count() > 0); + DiscreteFunctionVector u_op_v = p_u_op_v->get<DiscreteFunctionVector>(); + + auto u_values = p_R_u->get<DiscreteFunctionR>().cellValues(); + auto v_arrays = p_Vector3_v->get<DiscreteFunctionVector>().cellArrays(); + bool is_same = true; + for (CellId cell_id = 0; cell_id < u_values.numberOfItems(); ++cell_id) { + for (size_t i = 0; i < u_op_v.size(); ++i) { + if (u_op_v[cell_id][i] != (u_values[cell_id] * v_arrays[cell_id][i])) { + is_same = false; + break; + } + } + } + + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); + + REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); + + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); + } + + SECTION("Vh * X -> Vh") + { + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, bool{true}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, uint64_t{1}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, int64_t{2}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, double{1.3}, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, *, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, *, (TinyVector<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, *, (TinyVector<2>{1.2, 2.3}), // + DiscreteFunctionR2x2, DiscreteFunctionR2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, *, (TinyVector<3>{3.2, 7.1, 5.2}), // + DiscreteFunctionR3x3, DiscreteFunctionR3); + + REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R^2) and R^2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R^3) and R^3"); + REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R^1) and R^1x1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^2) and R^2x2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^3) and R^3x3"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), + "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); + REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); + REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); + } + + SECTION("X * Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u, DiscreteFunctionVector); + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u, DiscreteFunctionVector); + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u, DiscreteFunctionVector); + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u, DiscreteFunctionVector); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, + "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, + "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, + "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); + } + } + + SECTION("ratio") + { + SECTION("Vh / Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, /, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + + REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); + } + + SECTION("X / Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + } + } + } + + SECTION("unary operators") + { + SECTION("unary minus") + { + SECTION("- Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH(-, p_R_u, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH(-, p_R1_u, DiscreteFunctionR1); + CHECK_EMBEDDED_VH_TO_VH(-, p_R2_u, DiscreteFunctionR2); + CHECK_EMBEDDED_VH_TO_VH(-, p_R3_u, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH_TO_VH(-, p_R1x1_u, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH_TO_VH(-, p_R2x2_u, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH_TO_VH(-, p_R3x3_u, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_VH_TO_VH(-, p_Vector3_u, DiscreteFunctionVector); + } + } + } + } + } +} + +#ifdef __clang__ +#pragma clang optimize on +#endif // __clang__ diff --git a/tests/test_EmbeddedDiscreteFunctionOperators2D.cpp b/tests/test_EmbeddedDiscreteFunctionOperators2D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbf114d085d04a76da6715d3493516c9ead57044 --- /dev/null +++ b/tests/test_EmbeddedDiscreteFunctionOperators2D.cpp @@ -0,0 +1,864 @@ +#include <test_EmbeddedDiscreteFunctionOperators.hpp> + +#ifdef __clang__ +#pragma clang optimize off +#endif // __clang__ + +TEST_CASE("EmbeddedDiscreteFunctionOperators2D", "[scheme]") +{ + constexpr size_t Dimension = 2; + + using Rd = TinyVector<Dimension>; + + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + using DiscreteFunctionR = DiscreteFunctionP0<Dimension, const double>; + using DiscreteFunctionR1 = DiscreteFunctionP0<Dimension, const TinyVector<1>>; + using DiscreteFunctionR2 = DiscreteFunctionP0<Dimension, const TinyVector<2>>; + using DiscreteFunctionR3 = DiscreteFunctionP0<Dimension, const TinyVector<3>>; + using DiscreteFunctionR1x1 = DiscreteFunctionP0<Dimension, const TinyMatrix<1>>; + using DiscreteFunctionR2x2 = DiscreteFunctionP0<Dimension, const TinyMatrix<2>>; + using DiscreteFunctionR3x3 = DiscreteFunctionP0<Dimension, const TinyMatrix<3>>; + + using DiscreteFunctionVector = DiscreteFunctionP0Vector<Dimension, const double>; + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh = named_mesh.mesh(); + + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> u_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> v_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_R_u = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR(mesh, u_R_values)); + std::shared_ptr p_other_mesh_R_u = + std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR(other_mesh, u_R_values)); + std::shared_ptr p_R_v = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR(mesh, v_R_values)); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, uj)); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R1_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR1(other_mesh, p_R1_u->get<DiscreteFunctionR1>().cellValues())); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return TinyVector<2>{x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<2>{x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<2>{x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, uj)); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R2_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR2(other_mesh, p_R2_u->get<DiscreteFunctionR2>().cellValues())); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<3>{x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<3>{x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, uj)); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R3_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR3(other_mesh, p_R3_u->get<DiscreteFunctionR3>().cellValues())); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1x1(mesh, uj)); + }(); + + std::shared_ptr p_other_mesh_R1x1_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR1x1(other_mesh, p_R1x1_u->get<DiscreteFunctionR1x1>().cellValues())); + + std::shared_ptr p_R1x1_v = [=] { + CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = TinyMatrix<1>{0.3 - xj[cell_id][0]}; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1x1(mesh, vj)); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2x2(mesh, uj)); + }(); + + std::shared_ptr p_other_mesh_R2x2_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR2x2(other_mesh, p_R2x2_u->get<DiscreteFunctionR2x2>().cellValues())); + + std::shared_ptr p_R2x2_v = [=] { + CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + vj[cell_id] = TinyMatrix<2>{x[0] + 0.3, 1 - x[1] - x[0], // + 2 * x[1] + x[0], x[1] - x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2x2(mesh, vj)); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3x3(mesh, uj)); + }(); + + std::shared_ptr p_other_mesh_R3x3_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR3x3(other_mesh, p_R3x3_u->get<DiscreteFunctionR3x3>().cellValues())); + + std::shared_ptr p_R3x3_v = [=] { + CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + vj[cell_id] = TinyMatrix<3>{0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // + 2.3 * x[2], x[1] - x[0], x[2] - x[1], // + 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3x3(mesh, vj)); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, uj_vector)); + }(); + + std::shared_ptr p_other_mesh_Vector3_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionVector(other_mesh, p_Vector3_u->get<DiscreteFunctionVector>().cellArrays())); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, vj_vector)); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, wj_vector)); + }(); + + SECTION("binary operators") + { + SECTION("sum") + { + SECTION("Vh + Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, +, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1_u, +, p_R1_v, // + DiscreteFunctionR1, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2_u, +, p_R2_v, // + DiscreteFunctionR2, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3_u, +, p_R3_v, // + DiscreteFunctionR3, DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v, DiscreteFunctionVector); + + REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } + + SECTION("Vh + X -> Vh") + { + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, bool{true}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, uint64_t{1}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, int64_t{2}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, double{1.3}, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3}), // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3}), // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2}), // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, +, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } + + SECTION("X + Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + +, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } + + SECTION("difference") + { + SECTION("Vh - Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, -, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1_u, -, p_R1_v, // + DiscreteFunctionR1, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2_u, -, p_R2_v, // + DiscreteFunctionR2, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3_u, -, p_R3_v, // + DiscreteFunctionR3, DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v, DiscreteFunctionVector); + + REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } + + SECTION("Vh - X -> Vh") + { + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, bool{true}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, uint64_t{1}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, int64_t{2}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, double{1.3}, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3}), // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3}), // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2}), // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, -, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } + + SECTION("X - Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + -, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } + + SECTION("product") + { + SECTION("Vh * Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R1_v, // + DiscreteFunctionR, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R2_v, // + DiscreteFunctionR, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R3_v, // + DiscreteFunctionR, DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R1x1_v, // + DiscreteFunctionR, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R2x2_v, // + DiscreteFunctionR, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R3x3_v, // + DiscreteFunctionR, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, *, p_R1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, *, p_R2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, *, p_R3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3, DiscreteFunctionR3); + + { + std::shared_ptr p_u_op_v = p_R_u * p_Vector3_v; + + REQUIRE(p_u_op_v.use_count() > 0); + DiscreteFunctionVector u_op_v = p_u_op_v->get<DiscreteFunctionVector>(); + + auto u_values = p_R_u->get<DiscreteFunctionR>().cellValues(); + auto v_arrays = p_Vector3_v->get<DiscreteFunctionVector>().cellArrays(); + bool is_same = true; + for (CellId cell_id = 0; cell_id < u_values.numberOfItems(); ++cell_id) { + for (size_t i = 0; i < u_op_v.size(); ++i) { + if (u_op_v[cell_id][i] != (u_values[cell_id] * v_arrays[cell_id][i])) { + is_same = false; + break; + } + } + } + + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); + + REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); + + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); + } + + SECTION("Vh * X -> Vh") + { + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, bool{true}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, uint64_t{1}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, int64_t{2}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, double{1.3}, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, *, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, *, (TinyVector<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, *, (TinyVector<2>{1.2, 2.3}), // + DiscreteFunctionR2x2, DiscreteFunctionR2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, *, (TinyVector<3>{3.2, 7.1, 5.2}), // + DiscreteFunctionR3x3, DiscreteFunctionR3); + + REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R^2) and R^2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R^3) and R^3"); + REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R^1) and R^1x1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^2) and R^2x2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^3) and R^3x3"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), + "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); + REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); + REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); + } + + SECTION("X * Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u, DiscreteFunctionVector); + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u, DiscreteFunctionVector); + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u, DiscreteFunctionVector); + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u, DiscreteFunctionVector); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, + "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, + "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, + "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); + } + } + + SECTION("ratio") + { + SECTION("Vh / Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, /, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + + REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); + } + + SECTION("X / Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + } + } + } + + SECTION("unary operators") + { + SECTION("unary minus") + { + SECTION("- Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH(-, p_R_u, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH(-, p_R1_u, DiscreteFunctionR1); + CHECK_EMBEDDED_VH_TO_VH(-, p_R2_u, DiscreteFunctionR2); + CHECK_EMBEDDED_VH_TO_VH(-, p_R3_u, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH_TO_VH(-, p_R1x1_u, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH_TO_VH(-, p_R2x2_u, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH_TO_VH(-, p_R3x3_u, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_VH_TO_VH(-, p_Vector3_u, DiscreteFunctionVector); + } + } + } + } + } +} + +#ifdef __clang__ +#pragma clang optimize on +#endif // __clang__ diff --git a/tests/test_EmbeddedDiscreteFunctionOperators3D.cpp b/tests/test_EmbeddedDiscreteFunctionOperators3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b24d0a9128db6bcc8d4c3eff70a38a3c5fc9ee4 --- /dev/null +++ b/tests/test_EmbeddedDiscreteFunctionOperators3D.cpp @@ -0,0 +1,864 @@ +#include <test_EmbeddedDiscreteFunctionOperators.hpp> + +#ifdef __clang__ +#pragma clang optimize off +#endif // __clang__ + +TEST_CASE("EmbeddedDiscreteFunctionOperators3D", "[scheme]") +{ + constexpr size_t Dimension = 3; + + using Rd = TinyVector<Dimension>; + + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + using DiscreteFunctionR = DiscreteFunctionP0<Dimension, const double>; + using DiscreteFunctionR1 = DiscreteFunctionP0<Dimension, const TinyVector<1>>; + using DiscreteFunctionR2 = DiscreteFunctionP0<Dimension, const TinyVector<2>>; + using DiscreteFunctionR3 = DiscreteFunctionP0<Dimension, const TinyVector<3>>; + using DiscreteFunctionR1x1 = DiscreteFunctionP0<Dimension, const TinyMatrix<1>>; + using DiscreteFunctionR2x2 = DiscreteFunctionP0<Dimension, const TinyMatrix<2>>; + using DiscreteFunctionR3x3 = DiscreteFunctionP0<Dimension, const TinyMatrix<3>>; + + using DiscreteFunctionVector = DiscreteFunctionP0Vector<Dimension, const double>; + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh = named_mesh.mesh(); + + std::shared_ptr other_mesh = + std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); + + CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); + + CellValue<double> u_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + CellValue<double> v_R_values = [=] { + CellValue<double> build_values{mesh->connectivity()}; + parallel_for( + build_values.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); + return build_values; + }(); + + std::shared_ptr p_R_u = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR(mesh, u_R_values)); + std::shared_ptr p_other_mesh_R_u = + std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR(other_mesh, u_R_values)); + std::shared_ptr p_R_v = std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR(mesh, v_R_values)); + + std::shared_ptr p_R1_u = [=] { + CellValue<TinyVector<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, uj)); + }(); + + std::shared_ptr p_R1_v = [=] { + CellValue<TinyVector<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R1_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR1(other_mesh, p_R1_u->get<DiscreteFunctionR1>().cellValues())); + + constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { + if constexpr (Dimension == 1) { + return TinyVector<2>{x[0], 1 + x[0] * x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<2>{x[0], x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<2>{x[0], x[1] + x[2]}; + } + }; + + std::shared_ptr p_R2_u = [=] { + CellValue<TinyVector<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, uj)); + }(); + + std::shared_ptr p_R2_v = [=] { + CellValue<TinyVector<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R2_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR2(other_mesh, p_R2_u->get<DiscreteFunctionR2>().cellValues())); + + constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { + if constexpr (Dimension == 1) { + return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; + } else if constexpr (Dimension == 2) { + return TinyVector<3>{x[0], x[1], x[0] + x[1]}; + } else if constexpr (Dimension == 3) { + return TinyVector<3>{x[0], x[1], x[2]}; + } + }; + + std::shared_ptr p_R3_u = [=] { + CellValue<TinyVector<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, uj)); + }(); + + std::shared_ptr p_R3_v = [=] { + CellValue<TinyVector<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3(mesh, vj)); + }(); + + std::shared_ptr p_other_mesh_R3_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR3(other_mesh, p_R3_u->get<DiscreteFunctionR3>().cellValues())); + + std::shared_ptr p_R1x1_u = [=] { + CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), + PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1x1(mesh, uj)); + }(); + + std::shared_ptr p_other_mesh_R1x1_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR1x1(other_mesh, p_R1x1_u->get<DiscreteFunctionR1x1>().cellValues())); + + std::shared_ptr p_R1x1_v = [=] { + CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = TinyMatrix<1>{0.3 - xj[cell_id][0]}; }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR1x1(mesh, vj)); + }(); + + std::shared_ptr p_R2x2_u = [=] { + CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // + 2 * x[1], -x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2x2(mesh, uj)); + }(); + + std::shared_ptr p_other_mesh_R2x2_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR2x2(other_mesh, p_R2x2_u->get<DiscreteFunctionR2x2>().cellValues())); + + std::shared_ptr p_R2x2_v = [=] { + CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<2> x = to_2d(xj[cell_id]); + + vj[cell_id] = TinyMatrix<2>{x[0] + 0.3, 1 - x[1] - x[0], // + 2 * x[1] + x[0], x[1] - x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR2x2(mesh, vj)); + }(); + + std::shared_ptr p_R3x3_u = [=] { + CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; + parallel_for( + uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // + 2 * x[1], -x[0], x[0] - x[1], // + 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3x3(mesh, uj)); + }(); + + std::shared_ptr p_other_mesh_R3x3_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionR3x3(other_mesh, p_R3x3_u->get<DiscreteFunctionR3x3>().cellValues())); + + std::shared_ptr p_R3x3_v = [=] { + CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; + parallel_for( + vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + + vj[cell_id] = TinyMatrix<3>{0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // + 2.3 * x[2], x[1] - x[0], x[2] - x[1], // + 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionR3x3(mesh, vj)); + }(); + + std::shared_ptr p_Vector3_u = [=] { + CellArray<double> uj_vector{mesh->connectivity(), 3}; + parallel_for( + uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + uj_vector[cell_id][0] = 2 * x[0] + 1; + uj_vector[cell_id][1] = 1 - x[1] * x[2]; + uj_vector[cell_id][2] = x[0] + x[2]; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, uj_vector)); + }(); + + std::shared_ptr p_other_mesh_Vector3_u = std::make_shared<DiscreteFunctionVariant>( + DiscreteFunctionVector(other_mesh, p_Vector3_u->get<DiscreteFunctionVector>().cellArrays())); + + std::shared_ptr p_Vector3_v = [=] { + CellArray<double> vj_vector{mesh->connectivity(), 3}; + parallel_for( + vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + vj_vector[cell_id][0] = x[0] * x[1] + 1; + vj_vector[cell_id][1] = 2 * x[1]; + vj_vector[cell_id][2] = x[2] * x[0]; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, vj_vector)); + }(); + + std::shared_ptr p_Vector2_w = [=] { + CellArray<double> wj_vector{mesh->connectivity(), 2}; + parallel_for( + wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<3> x = to_3d(xj[cell_id]); + wj_vector[cell_id][0] = x[0] + x[1] * 2; + wj_vector[cell_id][1] = x[0] * x[1]; + }); + + return std::make_shared<DiscreteFunctionVariant>(DiscreteFunctionVector(mesh, wj_vector)); + }(); + + SECTION("binary operators") + { + SECTION("sum") + { + SECTION("Vh + Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, +, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1_u, +, p_R1_v, // + DiscreteFunctionR1, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2_u, +, p_R2_v, // + DiscreteFunctionR2, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3_u, +, p_R3_v, // + DiscreteFunctionR3, DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v, DiscreteFunctionVector); + + REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } + + SECTION("Vh + X -> Vh") + { + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, bool{true}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, uint64_t{1}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, int64_t{2}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, +, double{1.3}, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3}), // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3}), // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2}), // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, +, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } + + SECTION("X + Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, +, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + +, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } + + SECTION("difference") + { + SECTION("Vh - Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, -, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1_u, -, p_R1_v, // + DiscreteFunctionR1, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2_u, -, p_R2_v, // + DiscreteFunctionR2, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3_u, -, p_R3_v, // + DiscreteFunctionR3, DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v, DiscreteFunctionVector); + + REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); + + REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, + "error: operands are defined on different meshes"); + } + + SECTION("Vh - X -> Vh") + { + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, bool{true}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, uint64_t{1}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, int64_t{2}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, -, double{1.3}, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3}), // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3}), // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2}), // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, -, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), "error: incompatible operand types Vh(P0:R) and R^3"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R) and R^2x2"); + REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), + "error: incompatible operand types Vh(P0Vector:R) and R^1"); + REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + } + + SECTION("X - Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, -, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + -, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, "error: incompatible operand types R^3 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, + "error: incompatible operand types R^1 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + } + } + + SECTION("product") + { + SECTION("Vh * Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R1_v, // + DiscreteFunctionR, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R2_v, // + DiscreteFunctionR, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R3_v, // + DiscreteFunctionR, DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R1x1_v, // + DiscreteFunctionR, DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R2x2_v, // + DiscreteFunctionR, DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, *, p_R3x3_v, // + DiscreteFunctionR, DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VH2_TO_VH(p_R1x1_u, *, p_R1_v, // + DiscreteFunctionR1x1, DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_VH2_TO_VH(p_R2x2_u, *, p_R2_v, // + DiscreteFunctionR2x2, DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_VH2_TO_VH(p_R3x3_u, *, p_R3_v, // + DiscreteFunctionR3x3, DiscreteFunctionR3, DiscreteFunctionR3); + + { + std::shared_ptr p_u_op_v = p_R_u * p_Vector3_v; + + REQUIRE(p_u_op_v.use_count() > 0); + DiscreteFunctionVector u_op_v = p_u_op_v->get<DiscreteFunctionVector>(); + + auto u_values = p_R_u->get<DiscreteFunctionR>().cellValues(); + auto v_arrays = p_Vector3_v->get<DiscreteFunctionVector>().cellArrays(); + bool is_same = true; + for (CellId cell_id = 0; cell_id < u_values.numberOfItems(); ++cell_id) { + for (size_t i = 0; i < u_op_v.size(); ++i) { + if (u_op_v[cell_id][i] != (u_values[cell_id] * v_arrays[cell_id][i])) { + is_same = false; + break; + } + } + } + + REQUIRE(is_same); + } + + REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); + + REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, + "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); + + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); + REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); + } + + SECTION("Vh * X -> Vh") + { + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, bool{true}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, uint64_t{1}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, int64_t{2}, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_VHxX_TO_VH(p_R_u, *, double{1.3}, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, *, + (TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VHxX_TO_VH(p_R1x1_u, *, (TinyVector<1>{1.3}), // + DiscreteFunctionR1x1, DiscreteFunctionR1); + CHECK_EMBEDDED_VHxX_TO_VH(p_R2x2_u, *, (TinyVector<2>{1.2, 2.3}), // + DiscreteFunctionR2x2, DiscreteFunctionR2); + CHECK_EMBEDDED_VHxX_TO_VH(p_R3x3_u, *, (TinyVector<3>{3.2, 7.1, 5.2}), // + DiscreteFunctionR3x3, DiscreteFunctionR3); + + REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R^2) and R^2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), + "error: incompatible operand types Vh(P0:R^3) and R^3"); + REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R^1) and R^1x1"); + REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^2) and R^2x2"); + REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^3) and R^3x3"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), + "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); + REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), + "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); + + REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), + "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); + REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); + } + + SECTION("X * Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u, // + DiscreteFunctionR1, DiscreteFunctionR1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u, // + DiscreteFunctionR2, DiscreteFunctionR2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + *, p_R3_u, // + DiscreteFunctionR3, DiscreteFunctionR3); + + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u, // + DiscreteFunctionR1x1, DiscreteFunctionR1x1); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u, // + DiscreteFunctionR2x2, DiscreteFunctionR2x2); + CHECK_EMBEDDED_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // + 4.7, 2.3, 7.1, // + 9.7, 3.2, 6.8}), + *, p_R3x3_u, // + DiscreteFunctionR3x3, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u, DiscreteFunctionVector); + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u, DiscreteFunctionVector); + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u, DiscreteFunctionVector); + CHECK_EMBEDDED_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u, DiscreteFunctionVector); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, + "error: incompatible operand types R^2x2 and Vh(P0:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, + "error: incompatible operand types R^3x3 and Vh(P0:R)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, + "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, + "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, + "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); + + REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, + "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, + "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); + } + } + + SECTION("ratio") + { + SECTION("Vh / Vh -> Vh") + { + CHECK_EMBEDDED_VH2_TO_VH(p_R_u, /, p_R_v, // + DiscreteFunctionR, DiscreteFunctionR, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); + + REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); + } + + SECTION("X / Vh -> Vh") + { + CHECK_EMBEDDED_XxVH_TO_VH(bool{true}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(uint64_t{1}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(int64_t{2}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, /, p_R_u, // + DiscreteFunctionR, DiscreteFunctionR); + } + } + } + + SECTION("unary operators") + { + SECTION("unary minus") + { + SECTION("- Vh -> Vh") + { + CHECK_EMBEDDED_VH_TO_VH(-, p_R_u, DiscreteFunctionR); + + CHECK_EMBEDDED_VH_TO_VH(-, p_R1_u, DiscreteFunctionR1); + CHECK_EMBEDDED_VH_TO_VH(-, p_R2_u, DiscreteFunctionR2); + CHECK_EMBEDDED_VH_TO_VH(-, p_R3_u, DiscreteFunctionR3); + + CHECK_EMBEDDED_VH_TO_VH(-, p_R1x1_u, DiscreteFunctionR1x1); + CHECK_EMBEDDED_VH_TO_VH(-, p_R2x2_u, DiscreteFunctionR2x2); + CHECK_EMBEDDED_VH_TO_VH(-, p_R3x3_u, DiscreteFunctionR3x3); + + CHECK_EMBEDDED_VECTOR_VH_TO_VH(-, p_Vector3_u, DiscreteFunctionVector); + } + } + } + } + } +} + +#ifdef __clang__ +#pragma clang optimize on +#endif // __clang__ diff --git a/tests/test_EmbeddedDiscreteFunctionUtils.cpp b/tests/test_EmbeddedDiscreteFunctionUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd2fe97b69541189d1eb859bad6d952e9d705605 --- /dev/null +++ b/tests/test_EmbeddedDiscreteFunctionUtils.cpp @@ -0,0 +1,83 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <language/utils/EmbeddedDiscreteFunctionUtils.hpp> +#include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionP0Vector.hpp> + +#include <MeshDataBaseForTests.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("EmbeddedDiscreteFunctionUtils", "[language]") +{ + using R1 = TinyVector<1, double>; + using R2 = TinyVector<2, double>; + using R3 = TinyVector<3, double>; + + using R1x1 = TinyMatrix<1, 1, double>; + using R2x2 = TinyMatrix<2, 2, double>; + using R3x3 = TinyMatrix<3, 3, double>; + + SECTION("operand type name") + { + SECTION("basic types") + { + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(double{1}) == "R"); + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(std::make_shared<double>(1)) == "R"); + } + + SECTION("discrete P0 function") + { + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh_1d = named_mesh.mesh(); + + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, double>{mesh_1d}) == + "Vh(P0:R)"); + + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R1>{mesh_1d}) == + "Vh(P0:R^1)"); + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R2>{mesh_1d}) == + "Vh(P0:R^2)"); + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R3>{mesh_1d}) == + "Vh(P0:R^3)"); + + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R1x1>{mesh_1d}) == + "Vh(P0:R^1x1)"); + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R2x2>{mesh_1d}) == + "Vh(P0:R^2x2)"); + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R3x3>{mesh_1d}) == + "Vh(P0:R^3x3)"); + } + } + } + + SECTION("discrete P0Vector function") + { + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh_1d = named_mesh.mesh(); + + REQUIRE(EmbeddedDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0Vector<1, double>{mesh_1d, 2}) == + "Vh(P0Vector:R)"); + } + } + } + } + +#ifndef NDEBUG + SECTION("errors") + { + REQUIRE_THROWS_WITH(EmbeddedDiscreteFunctionUtils::getOperandTypeName(std::shared_ptr<double>()), + "dangling shared_ptr"); + } + +#endif // NDEBUG +} diff --git a/tests/test_EmbeddedIDiscreteFunctionMathFunctions.cpp b/tests/test_EmbeddedIDiscreteFunctionMathFunctions.cpp deleted file mode 100644 index 6d00782f96379548ebb66927044782def35612e8..0000000000000000000000000000000000000000 --- a/tests/test_EmbeddedIDiscreteFunctionMathFunctions.cpp +++ /dev/null @@ -1,2675 +0,0 @@ -#include <catch2/catch_test_macros.hpp> -#include <catch2/matchers/catch_matchers_all.hpp> - -#include <MeshDataBaseForTests.hpp> - -#include <language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp> -#include <scheme/DiscreteFunctionP0.hpp> -#include <scheme/DiscreteFunctionP0Vector.hpp> - -// clazy:excludeall=non-pod-global-static - -#define CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(P_U, FCT) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(*P_U)>; \ - std::shared_ptr p_fu = ::FCT(P_U); \ - \ - REQUIRE(p_fu.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fu)); \ - \ - const auto& fu = dynamic_cast<const DiscreteFunctionType&>(*p_fu); \ - \ - auto values = P_U->cellValues(); \ - bool is_same = true; \ - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { \ - if (fu[cell_id] != std::FCT(values[cell_id])) { \ - is_same = false; \ - break; \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#define CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(P_LHS, P_RHS, FCT) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(FCT(*P_LHS, *P_RHS))>; \ - std::shared_ptr p_fuv = ::FCT(P_LHS, P_RHS); \ - \ - REQUIRE(p_fuv.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fuv)); \ - \ - const auto& fuv = dynamic_cast<const DiscreteFunctionType&>(*p_fuv); \ - \ - auto lhs_values = P_LHS->cellValues(); \ - auto rhs_values = P_RHS->cellValues(); \ - bool is_same = true; \ - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { \ - using namespace std; \ - if (fuv[cell_id] != FCT(lhs_values[cell_id], rhs_values[cell_id])) { \ - is_same = false; \ - break; \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#define CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(P_LHS, RHS, FCT) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(FCT(*P_LHS, RHS))>; \ - std::shared_ptr p_fuv = ::FCT(P_LHS, RHS); \ - \ - REQUIRE(p_fuv.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fuv)); \ - \ - const auto& fuv = dynamic_cast<const DiscreteFunctionType&>(*p_fuv); \ - \ - auto lhs_values = P_LHS->cellValues(); \ - bool is_same = true; \ - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { \ - using namespace std; \ - if (fuv[cell_id] != FCT(lhs_values[cell_id], RHS)) { \ - is_same = false; \ - break; \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#define CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(LHS, P_RHS, FCT) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(FCT(LHS, *P_RHS))>; \ - std::shared_ptr p_fuv = ::FCT(LHS, P_RHS); \ - \ - REQUIRE(p_fuv.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fuv)); \ - \ - const auto& fuv = dynamic_cast<const DiscreteFunctionType&>(*p_fuv); \ - \ - auto rhs_values = P_RHS->cellValues(); \ - bool is_same = true; \ - for (CellId cell_id = 0; cell_id < rhs_values.numberOfItems(); ++cell_id) { \ - using namespace std; \ - if (fuv[cell_id] != FCT(LHS, rhs_values[cell_id])) { \ - is_same = false; \ - break; \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -TEST_CASE("EmbeddedIDiscreteFunctionMathFunctions", "[scheme]") -{ - SECTION("1D") - { - constexpr size_t Dimension = 1; - - using Rd = TinyVector<Dimension>; - - std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh = named_mesh.mesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> positive_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> bounded_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, values); - std::shared_ptr p_other_mesh_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, values); - std::shared_ptr p_positive_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, positive_values); - std::shared_ptr p_bounded_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, bounded_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return TinyVector<2>{x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<2>{x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<2>{x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<3>{x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<3>{x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sqrt Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, sqrt); - REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("abs Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, abs); - REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("sin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sin); - REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("cos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cos); - REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("tan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tan); - REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("asin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, asin); - REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("acos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, acos); - REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("atan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atan); - REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("sinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sinh); - REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("cosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cosh); - REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("tanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tanh); - REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("asinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, asinh); - REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("acosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, acosh); - REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("atanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atanh); - REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("exp Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, exp); - REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("log Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, log); - REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("atan2 Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2); - REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - } - - SECTION("atan2 Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2); - REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("atan2 R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2); - REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("min Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min); - REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } - - SECTION("min Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min); - REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("min R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min); - REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("min Vh -> R") - { - REQUIRE(min(std::shared_ptr<const IDiscreteFunction>{p_u}) == min(p_u->cellValues())); - REQUIRE_THROWS_WITH(min(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("max Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max); - REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } - - SECTION("max Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max); - REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("max Vh -> R") - { - REQUIRE(max(std::shared_ptr<const IDiscreteFunction>{p_u}) == max(p_u->cellValues())); - REQUIRE_THROWS_WITH(max(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("max R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max); - REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("pow Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow); - REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } - - SECTION("pow Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow); - REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("pow R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow); - REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("dot Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot); - - { - auto p_UV = dot(p_Vector3_u, p_Vector3_v); - REQUIRE(p_UV.use_count() == 1); - - auto UV = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_UV); - auto direct_UV = dot(*p_Vector3_u, *p_Vector3_v); - - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - if (UV[cell_id] != direct_UV[cell_id]) { - is_same = false; - break; - } - } - - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); - } - - SECTION("det Vh -> Vh") - { - { - std::shared_ptr p_fu = det(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != det(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = det(p_R2x2_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != det(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = det(p_R3x3_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != det(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(det(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(det(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(det(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(det(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("trace Vh -> Vh") - { - { - std::shared_ptr p_fu = trace(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != trace(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = trace(p_R2x2_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != trace(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = trace(p_R3x3_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != trace(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(trace(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(trace(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(trace(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(trace(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("inverse Vh -> Vh") - { - { - std::shared_ptr p_fu = inverse(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id](0, 0) != inverse(values[cell_id])(0, 0)) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = inverse(p_R2x2_u); - constexpr size_t nb_row = 2; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - const TinyMatrix invA = inverse(values[cell_id]); - const TinyMatrix<nb_row>& fu_i = fu[cell_id]; - for (size_t i = 0; i < nb_row; ++i) { - for (size_t j = 0; j < nb_row; ++j) { - if (fu_i(i, j) != invA(i, j)) { - is_same = false; - } - } - } - if (not is_same) { - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = inverse(p_R3x3_u); - constexpr size_t nb_row = 3; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - const TinyMatrix invA = inverse(values[cell_id]); - const TinyMatrix<nb_row>& fu_i = fu[cell_id]; - for (size_t i = 0; i < nb_row; ++i) { - for (size_t j = 0; j < nb_row; ++j) { - if (fu_i(i, j) != invA(i, j)) { - is_same = false; - } - } - } - if (not is_same) { - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(inverse(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(inverse(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(inverse(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(inverse(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("transpose Vh -> Vh") - { - { - std::shared_ptr p_fu = transpose(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id](0, 0) != transpose(values[cell_id])(0, 0)) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = transpose(p_R2x2_u); - constexpr size_t nb_row = 2; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - const TinyMatrix invA = transpose(values[cell_id]); - const TinyMatrix<nb_row>& fu_i = fu[cell_id]; - for (size_t i = 0; i < nb_row; ++i) { - for (size_t j = 0; j < nb_row; ++j) { - if (fu_i(i, j) != invA(i, j)) { - is_same = false; - } - } - } - if (not is_same) { - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = transpose(p_R3x3_u); - constexpr size_t nb_row = 3; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - const TinyMatrix invA = transpose(values[cell_id]); - const TinyMatrix<nb_row>& fu_i = fu[cell_id]; - for (size_t i = 0; i < nb_row; ++i) { - for (size_t j = 0; j < nb_row; ++j) { - if (fu_i(i, j) != invA(i, j)) { - is_same = false; - } - } - } - if (not is_same) { - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(transpose(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(transpose(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(transpose(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(transpose(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("sum_of_Vh Vh -> Vh") - { - { - auto p_sum_components = sum_of_Vh_components(p_Vector3_u); - REQUIRE(p_sum_components.use_count() == 1); - - const DiscreteFunctionP0<Dimension, double>& sum_components = - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_sum_components); - - DiscreteFunctionP0<Dimension, double> direct_sum(mesh); - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - double sum = 0; - for (size_t i = 0; i < p_Vector3_u->size(); ++i) { - sum += (*p_Vector3_u)[cell_id][i]; - } - - direct_sum[cell_id] = sum; - } - - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - if (sum_components[cell_id] != direct_sum[cell_id]) { - is_same = false; - break; - } - } - - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(sum_of_Vh_components(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("vectorize (Vh) -> Vh") - { - { - std::shared_ptr p_sum_components = - vectorize(std::vector<std::shared_ptr<const IDiscreteFunction>>{p_u, p_positive_u, p_bounded_u}); - REQUIRE(p_sum_components.use_count() == 1); - - REQUIRE(p_sum_components.use_count() == 1); - - const DiscreteFunctionP0Vector<Dimension, double> sum_components = - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_sum_components); - REQUIRE(sum_components.size() == 3); - - DiscreteFunctionP0<Dimension, double> direct_sum(mesh); - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - is_same &= ((*p_u)[cell_id] == sum_components[cell_id][0]); - is_same &= ((*p_positive_u)[cell_id] == sum_components[cell_id][1]); - is_same &= ((*p_bounded_u)[cell_id] == sum_components[cell_id][2]); - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(vectorize(std::vector<std::shared_ptr<const IDiscreteFunction>>{p_u, p_other_mesh_u}), - "error: discrete functions are not defined on the same mesh"); - REQUIRE_THROWS_WITH(vectorize(std::vector<std::shared_ptr<const IDiscreteFunction>>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("dot Vh*Rd -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot); - REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), - "error: incompatible operand types Vh(P0:R^1) and R^2"); - REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), - "error: incompatible operand types Vh(P0:R^2) and R^3"); - REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); - } - - SECTION("dot Rd*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot); - REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), - "error: incompatible operand types R^2 and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), - "error: incompatible operand types R^3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); - } - - SECTION("sum_of_R* Vh -> R*") - { - REQUIRE(sum_of<double>(p_u) == sum(p_u->cellValues())); - REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->cellValues())); - REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->cellValues())); - REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->cellValues())); - - REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); - } - - SECTION("integral_of_R* Vh -> R*") - { - auto integrate_locally = [&](const auto& cell_values) { - const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); - using DataType = decltype(double{} * cell_values[CellId{0}]); - CellValue<DataType> local_integral{mesh->connectivity()}; - parallel_for( - local_integral.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); - return local_integral; - }; - - REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->cellValues()))); - REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == sum(integrate_locally(p_R1_u->cellValues()))); - REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == sum(integrate_locally(p_R2_u->cellValues()))); - REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == sum(integrate_locally(p_R3_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == sum(integrate_locally(p_R1x1_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == sum(integrate_locally(p_R2x2_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == sum(integrate_locally(p_R3x3_u->cellValues()))); - - REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); - } - } - } - } - - SECTION("2D") - { - constexpr size_t Dimension = 2; - - using Rd = TinyVector<Dimension>; - - std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh = named_mesh.mesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> positive_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> bounded_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, values); - std::shared_ptr p_other_mesh_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, values); - std::shared_ptr p_positive_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, positive_values); - std::shared_ptr p_bounded_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, bounded_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return TinyVector<2>{x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<2>{x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<2>{x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<3>{x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<3>{x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sqrt Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, sqrt); - REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("abs Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, abs); - REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("sin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sin); - REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("cos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cos); - REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("tan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tan); - REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("asin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, asin); - REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("acos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, acos); - REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("atan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atan); - REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("sinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sinh); - REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("cosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cosh); - REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("tanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tanh); - REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("asinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, asinh); - REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("acosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, acosh); - REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("atanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atanh); - REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("exp Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, exp); - REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("log Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, log); - REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("atan2 Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2); - REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - } - - SECTION("atan2 Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2); - REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("atan2 R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2); - REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("min Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min); - REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } - - SECTION("min Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min); - REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("min R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min); - REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("min Vh -> R") - { - REQUIRE(min(std::shared_ptr<const IDiscreteFunction>{p_u}) == min(p_u->cellValues())); - REQUIRE_THROWS_WITH(min(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("max Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max); - REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } - - SECTION("max Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max); - REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("max Vh -> R") - { - REQUIRE(max(std::shared_ptr<const IDiscreteFunction>{p_u}) == max(p_u->cellValues())); - REQUIRE_THROWS_WITH(max(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("max R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max); - REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("pow Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow); - REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } - - SECTION("pow Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow); - REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("pow R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow); - REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("dot Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot); - - { - auto p_UV = dot(p_Vector3_u, p_Vector3_v); - REQUIRE(p_UV.use_count() == 1); - - auto UV = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_UV); - auto direct_UV = dot(*p_Vector3_u, *p_Vector3_v); - - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - if (UV[cell_id] != direct_UV[cell_id]) { - is_same = false; - break; - } - } - - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); - } - - SECTION("det Vh -> Vh") - { - { - std::shared_ptr p_fu = det(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != det(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = det(p_R2x2_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != det(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = det(p_R3x3_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != det(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(det(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(det(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(det(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(det(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("trace Vh -> Vh") - { - { - std::shared_ptr p_fu = trace(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != trace(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = trace(p_R2x2_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != trace(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = trace(p_R3x3_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != trace(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(trace(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(trace(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(trace(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(trace(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("inverse Vh -> Vh") - { - { - std::shared_ptr p_fu = inverse(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id](0, 0) != inverse(values[cell_id])(0, 0)) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = inverse(p_R2x2_u); - constexpr size_t nb_row = 2; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - const TinyMatrix invA = inverse(values[cell_id]); - const TinyMatrix<nb_row>& fu_i = fu[cell_id]; - for (size_t i = 0; i < nb_row; ++i) { - for (size_t j = 0; j < nb_row; ++j) { - if (fu_i(i, j) != invA(i, j)) { - is_same = false; - } - } - } - if (not is_same) { - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = inverse(p_R3x3_u); - constexpr size_t nb_row = 3; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - const TinyMatrix invA = inverse(values[cell_id]); - const TinyMatrix<nb_row>& fu_i = fu[cell_id]; - for (size_t i = 0; i < nb_row; ++i) { - for (size_t j = 0; j < nb_row; ++j) { - if (fu_i(i, j) != invA(i, j)) { - is_same = false; - } - } - } - if (not is_same) { - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(inverse(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(inverse(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(inverse(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(inverse(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("transpose Vh -> Vh") - { - { - std::shared_ptr p_fu = transpose(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id](0, 0) != transpose(values[cell_id])(0, 0)) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = transpose(p_R2x2_u); - constexpr size_t nb_row = 2; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - const TinyMatrix invA = transpose(values[cell_id]); - const TinyMatrix<nb_row>& fu_i = fu[cell_id]; - for (size_t i = 0; i < nb_row; ++i) { - for (size_t j = 0; j < nb_row; ++j) { - if (fu_i(i, j) != invA(i, j)) { - is_same = false; - } - } - } - if (not is_same) { - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = transpose(p_R3x3_u); - constexpr size_t nb_row = 3; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - const TinyMatrix invA = transpose(values[cell_id]); - const TinyMatrix<nb_row>& fu_i = fu[cell_id]; - for (size_t i = 0; i < nb_row; ++i) { - for (size_t j = 0; j < nb_row; ++j) { - if (fu_i(i, j) != invA(i, j)) { - is_same = false; - } - } - } - if (not is_same) { - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(transpose(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(transpose(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(transpose(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(transpose(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("sum_of_Vh Vh -> Vh") - { - { - auto p_sum_components = sum_of_Vh_components(p_Vector3_u); - REQUIRE(p_sum_components.use_count() == 1); - - const DiscreteFunctionP0<Dimension, double>& sum_components = - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_sum_components); - - DiscreteFunctionP0<Dimension, double> direct_sum(mesh); - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - double sum = 0; - for (size_t i = 0; i < p_Vector3_u->size(); ++i) { - sum += (*p_Vector3_u)[cell_id][i]; - } - - direct_sum[cell_id] = sum; - } - - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - if (sum_components[cell_id] != direct_sum[cell_id]) { - is_same = false; - break; - } - } - - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(sum_of_Vh_components(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("vectorize (Vh) -> Vh") - { - { - std::shared_ptr p_sum_components = - vectorize(std::vector<std::shared_ptr<const IDiscreteFunction>>{p_u, p_positive_u, p_bounded_u}); - REQUIRE(p_sum_components.use_count() == 1); - - const DiscreteFunctionP0Vector<Dimension, double> sum_components = - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_sum_components); - REQUIRE(sum_components.size() == 3); - - DiscreteFunctionP0<Dimension, double> direct_sum(mesh); - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - is_same &= ((*p_u)[cell_id] == sum_components[cell_id][0]); - is_same &= ((*p_positive_u)[cell_id] == sum_components[cell_id][1]); - is_same &= ((*p_bounded_u)[cell_id] == sum_components[cell_id][2]); - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(vectorize(std::vector<std::shared_ptr<const IDiscreteFunction>>{p_u, p_other_mesh_u}), - "error: discrete functions are not defined on the same mesh"); - REQUIRE_THROWS_WITH(vectorize(std::vector<std::shared_ptr<const IDiscreteFunction>>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("dot Vh*Rd -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot); - REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), - "error: incompatible operand types Vh(P0:R^1) and R^2"); - REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), - "error: incompatible operand types Vh(P0:R^2) and R^3"); - REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); - } - - SECTION("dot Rd*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot); - REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), - "error: incompatible operand types R^2 and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), - "error: incompatible operand types R^3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); - } - - SECTION("sum_of_R* Vh -> R*") - { - REQUIRE(sum_of<double>(p_u) == sum(p_u->cellValues())); - REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->cellValues())); - REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->cellValues())); - REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->cellValues())); - - REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); - } - - SECTION("integral_of_R* Vh -> R*") - { - auto integrate_locally = [&](const auto& cell_values) { - const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); - using DataType = decltype(double{} * cell_values[CellId{0}]); - CellValue<DataType> local_integral{mesh->connectivity()}; - parallel_for( - local_integral.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); - return local_integral; - }; - - REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->cellValues()))); - REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == sum(integrate_locally(p_R1_u->cellValues()))); - REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == sum(integrate_locally(p_R2_u->cellValues()))); - REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == sum(integrate_locally(p_R3_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == sum(integrate_locally(p_R1x1_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == sum(integrate_locally(p_R2x2_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == sum(integrate_locally(p_R3x3_u->cellValues()))); - - REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); - } - } - } - } - - SECTION("3D") - { - constexpr size_t Dimension = 3; - - using Rd = TinyVector<Dimension>; - - std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh = named_mesh.mesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> positive_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 2 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> bounded_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.9 * std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, values); - std::shared_ptr p_other_mesh_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, values); - std::shared_ptr p_positive_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, positive_values); - std::shared_ptr p_bounded_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, bounded_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return TinyVector<2>{x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<2>{x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<2>{x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<3>{x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<3>{x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sqrt Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, sqrt); - REQUIRE_THROWS_WITH(sqrt(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("abs Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, abs); - REQUIRE_THROWS_WITH(abs(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("sin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sin); - REQUIRE_THROWS_WITH(sin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("cos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cos); - REQUIRE_THROWS_WITH(cos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("tan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tan); - REQUIRE_THROWS_WITH(tan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("asin Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, asin); - REQUIRE_THROWS_WITH(asin(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("acos Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, acos); - REQUIRE_THROWS_WITH(acos(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("atan Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atan); - REQUIRE_THROWS_WITH(atan(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("sinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, sinh); - REQUIRE_THROWS_WITH(sinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("cosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, cosh); - REQUIRE_THROWS_WITH(cosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("tanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, tanh); - REQUIRE_THROWS_WITH(tanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("asinh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, asinh); - REQUIRE_THROWS_WITH(asinh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("acosh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, acosh); - REQUIRE_THROWS_WITH(acosh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("atanh Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_bounded_u, atanh); - REQUIRE_THROWS_WITH(atanh(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("exp Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_u, exp); - REQUIRE_THROWS_WITH(exp(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("log Vh -> Vh") - { - CHECK_EMBEDDED_VH_TO_VH_REAL_FUNCTION_EVALUATION(p_positive_u, log); - REQUIRE_THROWS_WITH(log(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("atan2 Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, atan2); - REQUIRE_THROWS_WITH(atan2(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(atan2(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(atan2(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - } - - SECTION("atan2 Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 3.6, atan2); - REQUIRE_THROWS_WITH(atan2(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("atan2 R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.4, p_u, atan2); - REQUIRE_THROWS_WITH(atan2(2.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("min Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, min); - REQUIRE_THROWS_WITH(::min(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::min(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::min(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } - - SECTION("min Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, min); - REQUIRE_THROWS_WITH(min(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("min R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, min); - REQUIRE_THROWS_WITH(min(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("min Vh -> R") - { - REQUIRE(min(std::shared_ptr<const IDiscreteFunction>{p_u}) == min(p_u->cellValues())); - REQUIRE_THROWS_WITH(min(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("max Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_u, p_bounded_u, max); - REQUIRE_THROWS_WITH(::max(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(::max(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(::max(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } - - SECTION("max Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_u, 1.2, max); - REQUIRE_THROWS_WITH(max(p_R1_u, 2.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("max Vh -> R") - { - REQUIRE(max(std::shared_ptr<const IDiscreteFunction>{p_u}) == max(p_u->cellValues())); - REQUIRE_THROWS_WITH(max(std::shared_ptr<const IDiscreteFunction>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("max R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(0.4, p_u, max); - REQUIRE_THROWS_WITH(max(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("pow Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_positive_u, p_bounded_u, pow); - REQUIRE_THROWS_WITH(pow(p_u, p_other_mesh_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(pow(p_u, p_R1_u), "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(pow(p_R1_u, p_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R)"); - } - - SECTION("pow Vh*R -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_positive_u, 3.3, pow); - REQUIRE_THROWS_WITH(pow(p_R1_u, 3.1), "error: incompatible operand types Vh(P0:R^1) and R"); - } - - SECTION("pow R*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION(2.1, p_u, pow); - REQUIRE_THROWS_WITH(pow(3.1, p_R1_u), "error: incompatible operand types R and Vh(P0:R^1)"); - } - - SECTION("dot Vh*Vh -> Vh") - { - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R1_u, p_R1_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R2_u, p_R2_v, dot); - CHECK_EMBEDDED_VH2_TO_VH_FUNCTION_EVALUATION(p_R3_u, p_R3_v, dot); - - { - auto p_UV = dot(p_Vector3_u, p_Vector3_v); - REQUIRE(p_UV.use_count() == 1); - - auto UV = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_UV); - auto direct_UV = dot(*p_Vector3_u, *p_Vector3_v); - - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - if (UV[cell_id] != direct_UV[cell_id]) { - is_same = false; - break; - } - } - - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(dot(p_R1_u, p_other_mesh_R1_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); - } - - SECTION("det Vh -> Vh") - { - { - std::shared_ptr p_fu = det(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != det(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = det(p_R2x2_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != det(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = det(p_R3x3_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != det(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(det(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(det(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(det(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(det(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("trace Vh -> Vh") - { - { - std::shared_ptr p_fu = trace(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != trace(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = trace(p_R2x2_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != trace(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = trace(p_R3x3_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != trace(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(trace(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(trace(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(trace(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(trace(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("inverse Vh -> Vh") - { - { - std::shared_ptr p_fu = inverse(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != inverse(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = inverse(p_R2x2_u); - constexpr size_t nb_row = 2; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != inverse(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = inverse(p_R3x3_u); - constexpr size_t nb_row = 3; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != inverse(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(inverse(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(inverse(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(inverse(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(inverse(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("transpose Vh -> Vh") - { - { - std::shared_ptr p_fu = transpose(p_R1x1_u); - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>&>(*p_fu); - - auto values = p_R1x1_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != transpose(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = transpose(p_R2x2_u); - constexpr size_t nb_row = 2; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R2x2_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != transpose(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - { - std::shared_ptr p_fu = transpose(p_R3x3_u); - constexpr size_t nb_row = 3; - - REQUIRE(p_fu.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu)); - - const auto& fu = dynamic_cast<const DiscreteFunctionP0<Dimension, TinyMatrix<nb_row>>&>(*p_fu); - - auto values = p_R3x3_u->cellValues(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < values.numberOfItems(); ++cell_id) { - if (fu[cell_id] != transpose(values[cell_id])) { - is_same = false; - break; - } - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(transpose(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(transpose(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(transpose(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(transpose(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("sum_of_Vh Vh -> Vh") - { - { - auto p_sum_components = sum_of_Vh_components(p_Vector3_u); - REQUIRE(p_sum_components.use_count() == 1); - - const DiscreteFunctionP0<Dimension, double>& sum_components = - dynamic_cast<const DiscreteFunctionP0<Dimension, double>&>(*p_sum_components); - - DiscreteFunctionP0<Dimension, double> direct_sum(mesh); - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - double sum = 0; - for (size_t i = 0; i < p_Vector3_u->size(); ++i) { - sum += (*p_Vector3_u)[cell_id][i]; - } - - direct_sum[cell_id] = sum; - } - - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - if (sum_components[cell_id] != direct_sum[cell_id]) { - is_same = false; - break; - } - } - - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(sum_of_Vh_components(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - } - - SECTION("vectorize (Vh) -> Vh") - { - { - std::shared_ptr p_sum_components = - vectorize(std::vector<std::shared_ptr<const IDiscreteFunction>>{p_u, p_positive_u, p_bounded_u}); - REQUIRE(p_sum_components.use_count() == 1); - - REQUIRE(p_sum_components.use_count() == 1); - - const DiscreteFunctionP0Vector<Dimension, double> sum_components = - dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_sum_components); - REQUIRE(sum_components.size() == 3); - - DiscreteFunctionP0<Dimension, double> direct_sum(mesh); - bool is_same = true; - for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) { - is_same &= ((*p_u)[cell_id] == sum_components[cell_id][0]); - is_same &= ((*p_positive_u)[cell_id] == sum_components[cell_id][1]); - is_same &= ((*p_bounded_u)[cell_id] == sum_components[cell_id][2]); - } - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(vectorize(std::vector<std::shared_ptr<const IDiscreteFunction>>{p_u, p_other_mesh_u}), - "error: discrete functions are not defined on the same mesh"); - REQUIRE_THROWS_WITH(vectorize(std::vector<std::shared_ptr<const IDiscreteFunction>>{p_R1_u}), - "error: invalid operand type Vh(P0:R^1)"); - } - - SECTION("dot Vh*Rd -> Vh") - { - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R1_u, (TinyVector<1>{3}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R2_u, (TinyVector<2>{-6, 2}), dot); - CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot); - REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), - "error: incompatible operand types Vh(P0:R^1) and R^2"); - REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), - "error: incompatible operand types Vh(P0:R^2) and R^3"); - REQUIRE_THROWS_WITH(dot(p_R3_u, (TinyVector<1>{-1})), "error: incompatible operand types Vh(P0:R^3) and R^1"); - } - - SECTION("dot Rd*Vh -> Vh") - { - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<1>{3}), p_R1_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<2>{-6, 2}), p_R2_u, dot); - CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot); - REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), - "error: incompatible operand types R^2 and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), - "error: incompatible operand types R^3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(dot((TinyVector<1>{-1}), p_R3_u), "error: incompatible operand types R^1 and Vh(P0:R^3)"); - } - - SECTION("sum_of_R* Vh -> R*") - { - REQUIRE(sum_of<double>(p_u) == sum(p_u->cellValues())); - REQUIRE(sum_of<TinyVector<1>>(p_R1_u) == sum(p_R1_u->cellValues())); - REQUIRE(sum_of<TinyVector<2>>(p_R2_u) == sum(p_R2_u->cellValues())); - REQUIRE(sum_of<TinyVector<3>>(p_R3_u) == sum(p_R3_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<1>>(p_R1x1_u) == sum(p_R1x1_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<2>>(p_R2x2_u) == sum(p_R2x2_u->cellValues())); - REQUIRE(sum_of<TinyMatrix<3>>(p_R3x3_u) == sum(p_R3x3_u->cellValues())); - - REQUIRE_THROWS_WITH(sum_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); - } - - SECTION("integral_of_R* Vh -> R*") - { - auto integrate_locally = [&](const auto& cell_values) { - const auto& Vj = MeshDataManager::instance().getMeshData(*mesh).Vj(); - using DataType = decltype(double{} * cell_values[CellId{0}]); - CellValue<DataType> local_integral{mesh->connectivity()}; - parallel_for( - local_integral.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { local_integral[cell_id] = Vj[cell_id] * cell_values[cell_id]; }); - return local_integral; - }; - - REQUIRE(integral_of<double>(p_u) == sum(integrate_locally(p_u->cellValues()))); - REQUIRE(integral_of<TinyVector<1>>(p_R1_u) == sum(integrate_locally(p_R1_u->cellValues()))); - REQUIRE(integral_of<TinyVector<2>>(p_R2_u) == sum(integrate_locally(p_R2_u->cellValues()))); - REQUIRE(integral_of<TinyVector<3>>(p_R3_u) == sum(integrate_locally(p_R3_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<1>>(p_R1x1_u) == sum(integrate_locally(p_R1x1_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<2>>(p_R2x2_u) == sum(integrate_locally(p_R2x2_u->cellValues()))); - REQUIRE(integral_of<TinyMatrix<3>>(p_R3x3_u) == sum(integrate_locally(p_R3x3_u->cellValues()))); - - REQUIRE_THROWS_WITH(integral_of<TinyVector<1>>(p_u), "error: invalid operand type Vh(P0:R)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); - } - } - } - } -} diff --git a/tests/test_EmbeddedIDiscreteFunctionOperators.cpp b/tests/test_EmbeddedIDiscreteFunctionOperators.cpp deleted file mode 100644 index 54e0e82f1ee25ea3166e51472e6be227e34a8080..0000000000000000000000000000000000000000 --- a/tests/test_EmbeddedIDiscreteFunctionOperators.cpp +++ /dev/null @@ -1,2735 +0,0 @@ -#include <catch2/catch_test_macros.hpp> -#include <catch2/matchers/catch_matchers_all.hpp> - -#include <MeshDataBaseForTests.hpp> - -#include <language/utils/EmbeddedIDiscreteFunctionOperators.hpp> -#include <scheme/DiscreteFunctionP0.hpp> -#include <scheme/DiscreteFunctionP0Vector.hpp> - -// clazy:excludeall=non-pod-global-static - -#define CHECK_SCALAR_VH2_TO_VH(P_LHS, OPERATOR, P_RHS) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(*P_LHS OPERATOR * P_RHS)>; \ - \ - std::shared_ptr p_fuv = P_LHS OPERATOR P_RHS; \ - \ - REQUIRE(p_fuv.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fuv)); \ - \ - const auto& fuv = dynamic_cast<const DiscreteFunctionType&>(*p_fuv); \ - \ - auto lhs_values = P_LHS->cellValues(); \ - auto rhs_values = P_RHS->cellValues(); \ - bool is_same = true; \ - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { \ - if (fuv[cell_id] != (lhs_values[cell_id] OPERATOR rhs_values[cell_id])) { \ - is_same = false; \ - break; \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#define CHECK_SCALAR_VHxX_TO_VH(P_LHS, OPERATOR, RHS) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(*P_LHS OPERATOR RHS)>; \ - \ - std::shared_ptr p_fuv = P_LHS OPERATOR RHS; \ - \ - REQUIRE(p_fuv.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fuv)); \ - \ - const auto& fuv = dynamic_cast<const DiscreteFunctionType&>(*p_fuv); \ - \ - auto lhs_values = P_LHS->cellValues(); \ - bool is_same = true; \ - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { \ - if (fuv[cell_id] != (lhs_values[cell_id] OPERATOR RHS)) { \ - is_same = false; \ - break; \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#define CHECK_SCALAR_XxVH_TO_VH(LHS, OPERATOR, P_RHS) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(LHS OPERATOR * P_RHS)>; \ - \ - std::shared_ptr p_fuv = LHS OPERATOR P_RHS; \ - \ - REQUIRE(p_fuv.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fuv)); \ - \ - const auto& fuv = dynamic_cast<const DiscreteFunctionType&>(*p_fuv); \ - \ - auto rhs_values = P_RHS->cellValues(); \ - bool is_same = true; \ - for (CellId cell_id = 0; cell_id < rhs_values.numberOfItems(); ++cell_id) { \ - if (fuv[cell_id] != (LHS OPERATOR rhs_values[cell_id])) { \ - is_same = false; \ - break; \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#define CHECK_VECTOR_VH2_TO_VH(P_LHS, OPERATOR, P_RHS) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(*P_LHS OPERATOR * P_RHS)>; \ - \ - std::shared_ptr p_fuv = P_LHS OPERATOR P_RHS; \ - \ - REQUIRE(p_fuv.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fuv)); \ - \ - const auto& fuv = dynamic_cast<const DiscreteFunctionType&>(*p_fuv); \ - \ - auto lhs_arrays = P_LHS->cellArrays(); \ - auto rhs_arrays = P_RHS->cellArrays(); \ - bool is_same = true; \ - REQUIRE(rhs_arrays.sizeOfArrays() > 0); \ - REQUIRE(lhs_arrays.sizeOfArrays() == rhs_arrays.sizeOfArrays()); \ - REQUIRE(lhs_arrays.sizeOfArrays() == fuv.size()); \ - for (CellId cell_id = 0; cell_id < lhs_arrays.numberOfItems(); ++cell_id) { \ - for (size_t i = 0; i < fuv.size(); ++i) { \ - if (fuv[cell_id][i] != (lhs_arrays[cell_id][i] OPERATOR rhs_arrays[cell_id][i])) { \ - is_same = false; \ - break; \ - } \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#define CHECK_VECTOR_XxVH_TO_VH(LHS, OPERATOR, P_RHS) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(LHS OPERATOR * P_RHS)>; \ - \ - std::shared_ptr p_fuv = LHS OPERATOR P_RHS; \ - \ - REQUIRE(p_fuv.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fuv)); \ - \ - const auto& fuv = dynamic_cast<const DiscreteFunctionType&>(*p_fuv); \ - \ - auto rhs_arrays = P_RHS->cellArrays(); \ - bool is_same = true; \ - REQUIRE(rhs_arrays.sizeOfArrays() > 0); \ - REQUIRE(fuv.size() == rhs_arrays.sizeOfArrays()); \ - for (CellId cell_id = 0; cell_id < rhs_arrays.numberOfItems(); ++cell_id) { \ - for (size_t i = 0; i < fuv.size(); ++i) { \ - if (fuv[cell_id][i] != (LHS OPERATOR rhs_arrays[cell_id][i])) { \ - is_same = false; \ - break; \ - } \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#define CHECK_SCALAR_VH_TO_VH(OPERATOR, P_RHS) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(OPERATOR * P_RHS)>; \ - \ - std::shared_ptr p_fu = OPERATOR P_RHS; \ - \ - REQUIRE(p_fu.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fu)); \ - \ - const auto& fu = dynamic_cast<const DiscreteFunctionType&>(*p_fu); \ - \ - auto rhs_values = P_RHS->cellValues(); \ - bool is_same = true; \ - for (CellId cell_id = 0; cell_id < rhs_values.numberOfItems(); ++cell_id) { \ - if (fu[cell_id] != (OPERATOR rhs_values[cell_id])) { \ - is_same = false; \ - break; \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#define CHECK_VECTOR_VH_TO_VH(OPERATOR, P_RHS) \ - { \ - using DiscreteFunctionType = const std::decay_t<decltype(OPERATOR * P_RHS)>; \ - \ - std::shared_ptr p_fu = OPERATOR P_RHS; \ - \ - REQUIRE(p_fu.use_count() > 0); \ - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionType&>(*p_fu)); \ - \ - const auto& fu = dynamic_cast<const DiscreteFunctionType&>(*p_fu); \ - \ - auto rhs_arrays = P_RHS->cellArrays(); \ - REQUIRE(rhs_arrays.sizeOfArrays() > 0); \ - REQUIRE(rhs_arrays.sizeOfArrays() == fu.size()); \ - bool is_same = true; \ - for (CellId cell_id = 0; cell_id < rhs_arrays.numberOfItems(); ++cell_id) { \ - for (size_t i = 0; i < rhs_arrays.sizeOfArrays(); ++i) { \ - if (fu[cell_id][i] != (OPERATOR rhs_arrays[cell_id][i])) { \ - is_same = false; \ - break; \ - } \ - } \ - } \ - \ - REQUIRE(is_same); \ - } - -#ifdef __clang__ -#pragma clang optimize off -#endif // __clang__ - -TEST_CASE("EmbeddedIDiscreteFunctionOperators", "[scheme]") -{ - SECTION("binary operators") - { - SECTION("1D") - { - constexpr size_t Dimension = 1; - - using Rd = TinyVector<Dimension>; - - std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh = named_mesh.mesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> v_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - std::shared_ptr p_other_mesh_R_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, u_R_values); - std::shared_ptr p_R_v = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, v_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return TinyVector<2>{x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<2>{x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<2>{x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<3>{x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<3>{x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R1x1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(other_mesh, p_R1x1_u->cellValues()); - - std::shared_ptr p_R1x1_v = [=] { - CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = TinyMatrix<1>{0.3 - xj[cell_id][0]}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, vj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R2x2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(other_mesh, p_R2x2_u->cellValues()); - - std::shared_ptr p_R2x2_v = [=] { - CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - vj[cell_id] = TinyMatrix<2>{x[0] + 0.3, 1 - x[1] - x[0], // - 2 * x[1] + x[0], x[1] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, vj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R3x3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(other_mesh, p_R3x3_u->cellValues()); - - std::shared_ptr p_R3x3_v = [=] { - CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - vj[cell_id] = TinyMatrix<3>{0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // - 2.3 * x[2], x[1] - x[0], x[2] - x[1], // - 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, vj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_other_mesh_Vector3_u = - std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(other_mesh, p_Vector3_u->cellArrays()); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sum") - { - SECTION("Vh + Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, +, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, +, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, +, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, +, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, - "error: operands are defined on different meshes"); - } - - SECTION("Vh + X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, +, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X + Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, +, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - +, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, - "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("difference") - { - SECTION("Vh - Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, -, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, -, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, -, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, -, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, - "error: operands are defined on different meshes"); - } - - SECTION("Vh - X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, -, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X - Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, -, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - -, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, - "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("product") - { - SECTION("Vh * Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3x3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3_v); - - { - std::shared_ptr p_fuv = p_R_u * p_Vector3_v; - - REQUIRE(p_fuv.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv)); - - const auto& fuv = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv); - - auto lhs_values = p_R_u->cellValues(); - auto rhs_arrays = p_Vector3_v->cellArrays(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { - for (size_t i = 0; i < fuv.size(); ++i) { - if (fuv[cell_id][i] != (lhs_values[cell_id] * rhs_arrays[cell_id][i])) { - is_same = false; - break; - } - } - } - - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, - "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, - "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, - "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); - - REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); - - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } - - SECTION("Vh * X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, *, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0:R^2) and R^2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R^3) and R^3"); - REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), - "error: incompatible operand types Vh(P0:R^1) and R^1x1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^2) and R^2x2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^3) and R^3x3"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), - "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); - REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); - REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); - } - - SECTION("X * Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R1x1_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R2x2_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R3x3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - *, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - *, p_R3x3_u); - - CHECK_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, - "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, - "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, - "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, - "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); - } - } - - SECTION("ratio") - { - SECTION("Vh / Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, /, p_R_v); - - REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - - REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); - } - - SECTION("X / Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, /, p_R_u); - } - } - } - } - } - - SECTION("2D") - { - constexpr size_t Dimension = 2; - - using Rd = TinyVector<Dimension>; - - std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh = named_mesh.mesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> v_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - std::shared_ptr p_other_mesh_R_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, u_R_values); - std::shared_ptr p_R_v = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, v_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return TinyVector<2>{x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<2>{x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<2>{x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<3>{x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<3>{x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R1x1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(other_mesh, p_R1x1_u->cellValues()); - - std::shared_ptr p_R1x1_v = [=] { - CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = TinyMatrix<1>{0.3 - xj[cell_id][0]}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, vj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R2x2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(other_mesh, p_R2x2_u->cellValues()); - - std::shared_ptr p_R2x2_v = [=] { - CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - vj[cell_id] = TinyMatrix<2>{x[0] + 0.3, 1 - x[1] - x[0], // - 2 * x[1] + x[0], x[1] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, vj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R3x3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(other_mesh, p_R3x3_u->cellValues()); - - std::shared_ptr p_R3x3_v = [=] { - CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - vj[cell_id] = TinyMatrix<3>{0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // - 2.3 * x[2], x[1] - x[0], x[2] - x[1], // - 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, vj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_other_mesh_Vector3_u = - std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(other_mesh, p_Vector3_u->cellArrays()); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sum") - { - SECTION("Vh + Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, +, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, +, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, +, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, +, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, - "error: operands are defined on different meshes"); - } - - SECTION("Vh + X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, +, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X + Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, +, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - +, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, - "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("difference") - { - SECTION("Vh - Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, -, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, -, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, -, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, -, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, - "error: operands are defined on different meshes"); - } - - SECTION("Vh - X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, -, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X - Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, -, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - -, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, - "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("product") - { - SECTION("Vh * Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3x3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3_v); - - { - std::shared_ptr p_fuv = p_R_u * p_Vector3_v; - - REQUIRE(p_fuv.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv)); - - const auto& fuv = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv); - - auto lhs_values = p_R_u->cellValues(); - auto rhs_arrays = p_Vector3_v->cellArrays(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { - for (size_t i = 0; i < fuv.size(); ++i) { - if (fuv[cell_id][i] != (lhs_values[cell_id] * rhs_arrays[cell_id][i])) { - is_same = false; - break; - } - } - } - - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, - "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, - "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, - "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); - - REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); - - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } - - SECTION("Vh * X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, *, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0:R^2) and R^2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R^3) and R^3"); - REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), - "error: incompatible operand types Vh(P0:R^1) and R^1x1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^2) and R^2x2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^3) and R^3x3"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), - "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); - REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); - REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); - } - - SECTION("X * Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R1x1_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R2x2_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R3x3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - *, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - *, p_R3x3_u); - - CHECK_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, - "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, - "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, - "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, - "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); - } - } - - SECTION("ratio") - { - SECTION("Vh / Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, /, p_R_v); - - REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - - REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); - } - - SECTION("X / Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, /, p_R_u); - } - } - } - } - } - - SECTION("3D") - { - constexpr size_t Dimension = 3; - - using Rd = TinyVector<Dimension>; - - std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh = named_mesh.mesh(); - - std::shared_ptr other_mesh = - std::make_shared<Mesh<Connectivity<Dimension>>>(mesh->shared_connectivity(), mesh->xr()); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - CellValue<double> v_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.6 + std::sin(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - std::shared_ptr p_other_mesh_R_u = - std::make_shared<const DiscreteFunctionP0<Dimension, double>>(other_mesh, u_R_values); - std::shared_ptr p_R_v = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, v_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R1_v = [=] { - CellValue<TinyVector<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id][0] = xj[cell_id][0] * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(other_mesh, p_R1_u->cellValues()); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return TinyVector<2>{x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<2>{x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<2>{x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R2_v = [=] { - CellValue<TinyVector<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - vj[cell_id] = TinyVector<2>{x[0] * x[1] + 1, 2 * x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(other_mesh, p_R2_u->cellValues()); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<3>{x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<3>{x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R3_v = [=] { - CellValue<TinyVector<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj[cell_id] = TinyVector<3>{x[0] * x[1] + 1, 2 * x[1], x[2] * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, vj); - }(); - - std::shared_ptr p_other_mesh_R3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(other_mesh, p_R3_u->cellValues()); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R1x1_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(other_mesh, p_R1x1_u->cellValues()); - - std::shared_ptr p_R1x1_v = [=] { - CellValue<TinyMatrix<1>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { vj[cell_id] = TinyMatrix<1>{0.3 - xj[cell_id][0]}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, vj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R2x2_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(other_mesh, p_R2x2_u->cellValues()); - - std::shared_ptr p_R2x2_v = [=] { - CellValue<TinyMatrix<2>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - vj[cell_id] = TinyMatrix<2>{x[0] + 0.3, 1 - x[1] - x[0], // - 2 * x[1] + x[0], x[1] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, vj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_other_mesh_R3x3_u = - std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(other_mesh, p_R3x3_u->cellValues()); - - std::shared_ptr p_R3x3_v = [=] { - CellValue<TinyMatrix<3>> vj{mesh->connectivity()}; - parallel_for( - vj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - vj[cell_id] = TinyMatrix<3>{0.2 * x[0] + 1, 2 + x[1], 3 - x[2], // - 2.3 * x[2], x[1] - x[0], x[2] - x[1], // - 2 * x[2] + x[0], x[1] + 0.2 * x[2], x[2] - 2 * x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, vj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - std::shared_ptr p_other_mesh_Vector3_u = - std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(other_mesh, p_Vector3_u->cellArrays()); - - std::shared_ptr p_Vector3_v = [=] { - CellArray<double> vj_vector{mesh->connectivity(), 3}; - parallel_for( - vj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - vj_vector[cell_id][0] = x[0] * x[1] + 1; - vj_vector[cell_id][1] = 2 * x[1]; - vj_vector[cell_id][2] = x[2] * x[0]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, vj_vector); - }(); - - std::shared_ptr p_Vector2_w = [=] { - CellArray<double> wj_vector{mesh->connectivity(), 2}; - parallel_for( - wj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - wj_vector[cell_id][0] = x[0] + x[1] * 2; - wj_vector[cell_id][1] = x[0] * x[1]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, wj_vector); - }(); - - SECTION("sum") - { - SECTION("Vh + Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, +, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, +, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, +, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, +, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, +, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, +, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, +, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, +, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u + p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u + p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u + p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R_u + p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u + p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u + p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u + p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u + p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u + p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u + p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u + p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u + p_other_mesh_Vector3_u, - "error: operands are defined on different meshes"); - } - - SECTION("Vh + X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, +, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, +, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, +, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, +, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, +, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, +, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, +, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u + (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u + (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u + (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X + Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, +, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, +, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), +, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), +, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), +, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), +, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), +, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - +, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) + p_R_u, - "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) + p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) + p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) + p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) + p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) + p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) + p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("difference") - { - SECTION("Vh - Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, -, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1_u, -, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2_u, -, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3_u, -, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, -, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, -, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, -, p_R3x3_v); - - CHECK_VECTOR_VH2_TO_VH(p_Vector3_u, -, p_Vector3_v); - - REQUIRE_THROWS_WITH(p_R_u - p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u - p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u - p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u - p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_R_v, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_Vector2_w, "error: Vh(P0Vector:R) spaces have different sizes"); - - REQUIRE_THROWS_WITH(p_R_u - p_other_mesh_R_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1_u - p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2_u - p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3_u - p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u - p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u - p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u - p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_Vector3_u - p_other_mesh_Vector3_u, - "error: operands are defined on different meshes"); - } - - SECTION("Vh - X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, -, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1_u, -, (TinyVector<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2_u, -, (TinyVector<2>{1.2, 2.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R3_u, -, (TinyVector<3>{3.2, 7.1, 5.2})); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, -, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, -, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, -, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R) and R^1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<2>{1, 2}), "error: incompatible operand types Vh(P0:R) and R^2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R) and R^3"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<1>{2}), "error: incompatible operand types Vh(P0:R) and R^1x1"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R) and R^2x2"); - REQUIRE_THROWS_WITH(p_R_u - (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u - (double{1}), "error: incompatible operand types Vh(P0Vector:R) and R"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<1>{1}), - "error: incompatible operand types Vh(P0Vector:R) and R^1"); - REQUIRE_THROWS_WITH(p_Vector3_u - (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0Vector:R) and R^2"); - } - - SECTION("X - Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, -, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, -, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyVector<1>{1.3}), -, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<2>{1.2, 2.3}), -, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyVector<3>{3.2, 7.1, 5.2}), -, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), -, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), -, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - -, p_R3x3_u); - - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_R_u, "error: incompatible operand types R^1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_R_u, "error: incompatible operand types R^2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyVector<3>{2, 3, 2}) - p_R_u, - "error: incompatible operand types R^3 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) - p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) - p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) - p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((double{1}) - p_Vector3_u, "error: incompatible operand types R and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<1>{1}) - p_Vector3_u, - "error: incompatible operand types R^1 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyVector<2>{1, 2}) - p_Vector3_u, - "error: incompatible operand types R^2 and Vh(P0Vector:R)"); - } - } - - SECTION("product") - { - SECTION("Vh * Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3x3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R1x1_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R2x2_v); - CHECK_SCALAR_VH2_TO_VH(p_R_u, *, p_R3x3_v); - - CHECK_SCALAR_VH2_TO_VH(p_R1x1_u, *, p_R1_v); - CHECK_SCALAR_VH2_TO_VH(p_R2x2_u, *, p_R2_v); - CHECK_SCALAR_VH2_TO_VH(p_R3x3_u, *, p_R3_v); - - { - std::shared_ptr p_fuv = p_R_u * p_Vector3_v; - - REQUIRE(p_fuv.use_count() > 0); - REQUIRE_NOTHROW(dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv)); - - const auto& fuv = dynamic_cast<const DiscreteFunctionP0Vector<Dimension, double>&>(*p_fuv); - - auto lhs_values = p_R_u->cellValues(); - auto rhs_arrays = p_Vector3_v->cellArrays(); - bool is_same = true; - for (CellId cell_id = 0; cell_id < lhs_values.numberOfItems(); ++cell_id) { - for (size_t i = 0; i < fuv.size(); ++i) { - if (fuv[cell_id][i] != (lhs_values[cell_id] * rhs_arrays[cell_id][i])) { - is_same = false; - break; - } - } - } - - REQUIRE(is_same); - } - - REQUIRE_THROWS_WITH(p_R1_u * p_R1_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u * p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u * p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R1_u * p_R2x2_v, "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^2x2)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2x2_v, - "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3x3_v, - "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1x1_v, - "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH(p_R1x1_u * p_R2_v, "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_R3_v, "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_R1_v, "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH(p_R1_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^1x1) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^2x2) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0:R^3x3) and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH(p_Vector3_u * p_Vector3_v, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0Vector:R)"); - - REQUIRE_THROWS_WITH(p_Vector3_v * p_R_u, "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R1x1_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R2x2_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH(p_Vector3_v * p_R3x3_u, - "error: incompatible operand types Vh(P0Vector:R) and Vh(P0:R^3x3)"); - - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R1x1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R2x2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_R3x3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R1x1_u * p_other_mesh_R1_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R2x2_u * p_other_mesh_R2_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R3x3_u * p_other_mesh_R3_u, "error: operands are defined on different meshes"); - REQUIRE_THROWS_WITH(p_R_u * p_other_mesh_Vector3_u, "error: operands are defined on different meshes"); - } - - SECTION("Vh * X -> Vh") - { - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, bool{true}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, uint64_t{1}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, int64_t{2}); - CHECK_SCALAR_VHxX_TO_VH(p_R_u, *, double{1.3}); - - CHECK_SCALAR_VHxX_TO_VH(p_R1x1_u, *, (TinyMatrix<1>{1.3})); - CHECK_SCALAR_VHxX_TO_VH(p_R2x2_u, *, (TinyMatrix<2>{1.2, 2.3, 4.2, 5.1})); - CHECK_SCALAR_VHxX_TO_VH(p_R3x3_u, *, - (TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8})); - - REQUIRE_THROWS_WITH(p_R1_u * (TinyVector<1>{1}), "error: incompatible operand types Vh(P0:R^1) and R^1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyVector<2>{1, 2}), - "error: incompatible operand types Vh(P0:R^2) and R^2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyVector<3>{2, 3, 2}), - "error: incompatible operand types Vh(P0:R^3) and R^3"); - REQUIRE_THROWS_WITH(p_R1_u * (TinyMatrix<1>{2}), - "error: incompatible operand types Vh(P0:R^1) and R^1x1"); - REQUIRE_THROWS_WITH(p_R2_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^2) and R^2x2"); - REQUIRE_THROWS_WITH(p_R3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^3) and R^3x3"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<1>{2}), - "error: incompatible operand types Vh(P0:R^2x2) and R^1x1"); - REQUIRE_THROWS_WITH(p_R1x1_u * (TinyMatrix<2>{2, 3, 1, 4}), - "error: incompatible operand types Vh(P0:R^1x1) and R^2x2"); - REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); - - REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), - "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); - REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); - } - - SECTION("X * Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R1x1_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R2x2_u); - - CHECK_SCALAR_XxVH_TO_VH(bool{true}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, *, p_R3x3_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, *, p_R3x3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - *, p_R3_u); - - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<1>{1.3}), *, p_R1x1_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<2>{1.2, 2.3, 4.2, 5.1}), *, p_R2x2_u); - CHECK_SCALAR_XxVH_TO_VH((TinyMatrix<3>{3.2, 7.1, 5.2, // - 4.7, 2.3, 7.1, // - 9.7, 3.2, 6.8}), - *, p_R3x3_u); - - CHECK_VECTOR_XxVH_TO_VH(bool{true}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(uint64_t{1}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(int64_t{2}, *, p_Vector3_u); - CHECK_VECTOR_XxVH_TO_VH(double{1.3}, *, p_Vector3_u); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R_u, "error: incompatible operand types R^1x1 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R_u, - "error: incompatible operand types R^2x2 and Vh(P0:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R_u, - "error: incompatible operand types R^3x3 and Vh(P0:R)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2_u, - "error: incompatible operand types R^1x1 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R1_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_R2x2_u, - "error: incompatible operand types R^1x1 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R3x3_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^3x3)"); - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_R2x2_u, - "error: incompatible operand types R^3x3 and Vh(P0:R^2x2)"); - REQUIRE_THROWS_WITH((TinyMatrix<2>{2, 3, 1, 4}) * p_R1x1_u, - "error: incompatible operand types R^2x2 and Vh(P0:R^1x1)"); - - REQUIRE_THROWS_WITH((TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}) * p_Vector3_u, - "error: incompatible operand types R^3x3 and Vh(P0Vector:R)"); - REQUIRE_THROWS_WITH((TinyMatrix<1>{2}) * p_Vector3_u, - "error: incompatible operand types R^1x1 and Vh(P0Vector:R)"); - } - } - - SECTION("ratio") - { - SECTION("Vh / Vh -> Vh") - { - CHECK_SCALAR_VH2_TO_VH(p_R_u, /, p_R_v); - - REQUIRE_THROWS_WITH(p_R_u / p_R1_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R2_u / p_R1_v, "error: incompatible operand types Vh(P0:R^2) and Vh(P0:R^1)"); - REQUIRE_THROWS_WITH(p_R3_u / p_R1x1_v, "error: incompatible operand types Vh(P0:R^3) and Vh(P0:R^1x1)"); - REQUIRE_THROWS_WITH(p_R_u / p_R2x2_v, "error: incompatible operand types Vh(P0:R) and Vh(P0:R^2x2)"); - - REQUIRE_THROWS_WITH(p_R_u / p_other_mesh_R_u, "error: operands are defined on different meshes"); - } - - SECTION("X / Vh -> Vh") - { - CHECK_SCALAR_XxVH_TO_VH(bool{true}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(uint64_t{1}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(int64_t{2}, /, p_R_u); - CHECK_SCALAR_XxVH_TO_VH(double{1.3}, /, p_R_u); - } - } - } - } - } - } - - SECTION("unary operators") - { - SECTION("1D") - { - constexpr size_t Dimension = 1; - - using Rd = TinyVector<Dimension>; - - std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh = named_mesh.mesh(); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return TinyVector<2>{x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<2>{x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<2>{x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<3>{x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<3>{x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - SECTION("unary minus") - { - SECTION("- Vh -> Vh") - { - CHECK_SCALAR_VH_TO_VH(-, p_R_u); - - CHECK_SCALAR_VH_TO_VH(-, p_R1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3_u); - - CHECK_SCALAR_VH_TO_VH(-, p_R1x1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2x2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3x3_u); - - CHECK_VECTOR_VH_TO_VH(-, p_Vector3_u); - } - } - } - } - } - - SECTION("2D") - { - constexpr size_t Dimension = 2; - - using Rd = TinyVector<Dimension>; - - std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh = named_mesh.mesh(); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return TinyVector<2>{x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<2>{x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<2>{x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<3>{x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<3>{x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - SECTION("unary minus") - { - SECTION("- Vh -> Vh") - { - CHECK_SCALAR_VH_TO_VH(-, p_R_u); - - CHECK_SCALAR_VH_TO_VH(-, p_R1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3_u); - - CHECK_SCALAR_VH_TO_VH(-, p_R1x1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2x2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3x3_u); - - CHECK_VECTOR_VH_TO_VH(-, p_Vector3_u); - } - } - } - } - } - - SECTION("3D") - { - constexpr size_t Dimension = 3; - - using Rd = TinyVector<Dimension>; - - std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh = named_mesh.mesh(); - - CellValue<const Rd> xj = MeshDataManager::instance().getMeshData(*mesh).xj(); - - CellValue<double> u_R_values = [=] { - CellValue<double> build_values{mesh->connectivity()}; - parallel_for( - build_values.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { build_values[cell_id] = 0.2 + std::cos(l2Norm(xj[cell_id])); }); - return build_values; - }(); - - std::shared_ptr p_R_u = std::make_shared<const DiscreteFunctionP0<Dimension, double>>(mesh, u_R_values); - - std::shared_ptr p_R1_u = [=] { - CellValue<TinyVector<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { uj[cell_id][0] = 2 * xj[cell_id][0] + 1; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<1>>>(mesh, uj); - }(); - - constexpr auto to_2d = [&](const TinyVector<Dimension>& x) -> TinyVector<2> { - if constexpr (Dimension == 1) { - return TinyVector<2>{x[0], 1 + x[0] * x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<2>{x[0], x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<2>{x[0], x[1] + x[2]}; - } - }; - - std::shared_ptr p_R2_u = [=] { - CellValue<TinyVector<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - uj[cell_id] = TinyVector<2>{2 * x[0] + 1, 1 - x[1]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<2>>>(mesh, uj); - }(); - - constexpr auto to_3d = [&](const TinyVector<Dimension>& x) -> TinyVector<3> { - if constexpr (Dimension == 1) { - return TinyVector<3>{x[0], 1 + x[0] * x[0], 2 - x[0]}; - } else if constexpr (Dimension == 2) { - return TinyVector<3>{x[0], x[1], x[0] + x[1]}; - } else if constexpr (Dimension == 3) { - return TinyVector<3>{x[0], x[1], x[2]}; - } - }; - - std::shared_ptr p_R3_u = [=] { - CellValue<TinyVector<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj[cell_id] = TinyVector<3>{2 * x[0] + 1, 1 - x[1] * x[2], x[0] + x[2]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyVector<3>>>(mesh, uj); - }(); - - std::shared_ptr p_R1x1_u = [=] { - CellValue<TinyMatrix<1>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), - PUGS_LAMBDA(const CellId cell_id) { uj[cell_id] = TinyMatrix<1>{2 * xj[cell_id][0] + 1}; }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<1>>>(mesh, uj); - }(); - - std::shared_ptr p_R2x2_u = [=] { - CellValue<TinyMatrix<2>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<2> x = to_2d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<2>{2 * x[0] + 1, 1 - x[1], // - 2 * x[1], -x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<2>>>(mesh, uj); - }(); - - std::shared_ptr p_R3x3_u = [=] { - CellValue<TinyMatrix<3>> uj{mesh->connectivity()}; - parallel_for( - uj.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - - uj[cell_id] = TinyMatrix<3>{2 * x[0] + 1, 1 - x[1], 3, // - 2 * x[1], -x[0], x[0] - x[1], // - 3 * x[2] - x[1], x[1] - 2 * x[2], x[2] - x[0]}; - }); - - return std::make_shared<const DiscreteFunctionP0<Dimension, TinyMatrix<3>>>(mesh, uj); - }(); - - std::shared_ptr p_Vector3_u = [=] { - CellArray<double> uj_vector{mesh->connectivity(), 3}; - parallel_for( - uj_vector.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { - const TinyVector<3> x = to_3d(xj[cell_id]); - uj_vector[cell_id][0] = 2 * x[0] + 1; - uj_vector[cell_id][1] = 1 - x[1] * x[2]; - uj_vector[cell_id][2] = x[0] + x[2]; - }); - - return std::make_shared<const DiscreteFunctionP0Vector<Dimension, double>>(mesh, uj_vector); - }(); - - SECTION("unary minus") - { - SECTION("- Vh -> Vh") - { - CHECK_SCALAR_VH_TO_VH(-, p_R_u); - - CHECK_SCALAR_VH_TO_VH(-, p_R1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3_u); - - CHECK_SCALAR_VH_TO_VH(-, p_R1x1_u); - CHECK_SCALAR_VH_TO_VH(-, p_R2x2_u); - CHECK_SCALAR_VH_TO_VH(-, p_R3x3_u); - - CHECK_VECTOR_VH_TO_VH(-, p_Vector3_u); - } - } - } - } - } - } -} - -#ifdef __clang__ -#pragma clang optimize on -#endif // __clang__ diff --git a/tests/test_EmbeddedIDiscreteFunctionUtils.cpp b/tests/test_EmbeddedIDiscreteFunctionUtils.cpp deleted file mode 100644 index 476103c42897ca8f86f2a5515f110e87b2ac0d9c..0000000000000000000000000000000000000000 --- a/tests/test_EmbeddedIDiscreteFunctionUtils.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include <catch2/catch_test_macros.hpp> -#include <catch2/matchers/catch_matchers_all.hpp> - -#include <language/utils/EmbeddedIDiscreteFunctionUtils.hpp> -#include <scheme/DiscreteFunctionP0.hpp> -#include <scheme/DiscreteFunctionP0Vector.hpp> - -#include <MeshDataBaseForTests.hpp> - -// clazy:excludeall=non-pod-global-static - -TEST_CASE("EmbeddedIDiscreteFunctionUtils", "[language]") -{ - using R1 = TinyVector<1, double>; - using R2 = TinyVector<2, double>; - using R3 = TinyVector<3, double>; - - using R1x1 = TinyMatrix<1, 1, double>; - using R2x2 = TinyMatrix<2, 2, double>; - using R3x3 = TinyMatrix<3, 3, double>; - - SECTION("operand type name") - { - SECTION("basic types") - { - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(double{1}) == "R"); - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(std::make_shared<double>(1)) == "R"); - } - - SECTION("discrete P0 function") - { - std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh_1d = named_mesh.mesh(); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, double>{mesh_1d}) == - "Vh(P0:R)"); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R1>{mesh_1d}) == - "Vh(P0:R^1)"); - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R2>{mesh_1d}) == - "Vh(P0:R^2)"); - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R3>{mesh_1d}) == - "Vh(P0:R^3)"); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R1x1>{mesh_1d}) == - "Vh(P0:R^1x1)"); - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R2x2>{mesh_1d}) == - "Vh(P0:R^2x2)"); - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0<1, R3x3>{mesh_1d}) == - "Vh(P0:R^3x3)"); - } - } - } - - SECTION("discrete P0Vector function") - { - std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh_1d = named_mesh.mesh(); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(DiscreteFunctionP0Vector<1, double>{mesh_1d, 2}) == - "Vh(P0Vector:R)"); - } - } - } - } - - SECTION("check if is same discretization") - { - SECTION("from shared_ptr") - { - std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh_1d = named_mesh.mesh(); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(std::make_shared<DiscreteFunctionP0<1, double>>( - mesh_1d), - std::make_shared<DiscreteFunctionP0<1, double>>( - mesh_1d))); - - REQUIRE(not EmbeddedIDiscreteFunctionUtils:: - isSameDiscretization(std::make_shared<DiscreteFunctionP0<1, double>>(mesh_1d), - std::make_shared<DiscreteFunctionP0Vector<1, double>>(mesh_1d, 1))); - } - } - } - - SECTION("from value") - { - std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh_1d = named_mesh.mesh(); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, double>{mesh_1d}, - DiscreteFunctionP0<1, double>{mesh_1d})); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R1>{mesh_1d}, - DiscreteFunctionP0<1, R1>{mesh_1d})); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R2>{mesh_1d}, - DiscreteFunctionP0<1, R2>{mesh_1d})); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R3>{mesh_1d}, - DiscreteFunctionP0<1, R3>{mesh_1d})); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R1x1>{mesh_1d}, - DiscreteFunctionP0<1, R1x1>{mesh_1d})); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R2x2>{mesh_1d}, - DiscreteFunctionP0<1, R2x2>{mesh_1d})); - - REQUIRE(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R3x3>{mesh_1d}, - DiscreteFunctionP0<1, R3x3>{mesh_1d})); - - REQUIRE(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, double>{mesh_1d}, - DiscreteFunctionP0<1, R1>{mesh_1d})); - - REQUIRE(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R2>{mesh_1d}, - DiscreteFunctionP0<1, R2x2>{mesh_1d})); - - REQUIRE(not EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, R3x3>{mesh_1d}, - DiscreteFunctionP0<1, R2x2>{mesh_1d})); - } - } - } - - SECTION("invalid data type") - { - std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); - - for (const auto& named_mesh : mesh_list) { - SECTION(named_mesh.name()) - { - auto mesh_1d = named_mesh.mesh(); - - REQUIRE_THROWS_WITH(EmbeddedIDiscreteFunctionUtils::isSameDiscretization(DiscreteFunctionP0<1, - int64_t>{mesh_1d}, - DiscreteFunctionP0<1, int64_t>{ - mesh_1d}), - "unexpected error: invalid data type Vh(P0:Z)"); - } - } - } - } - -#ifndef NDEBUG - SECTION("errors") - { - REQUIRE_THROWS_WITH(EmbeddedIDiscreteFunctionUtils::getOperandTypeName(std::shared_ptr<double>()), - "dangling shared_ptr"); - } - -#endif // NDEBUG -} diff --git a/tests/test_MedianDualConnectivityBuilder.cpp b/tests/test_MedianDualConnectivityBuilder.cpp index a95e6ad22f8a9b2605dec5c28e7c7704d40aed6f..6d091bd037e4ac57635757b98671eff9fe6eb643 100644 --- a/tests/test_MedianDualConnectivityBuilder.cpp +++ b/tests/test_MedianDualConnectivityBuilder.cpp @@ -5,6 +5,7 @@ #include <mesh/DualConnectivityManager.hpp> #include <mesh/Connectivity.hpp> +#include <mesh/ConnectivityUtils.hpp> #include <mesh/ItemValueUtils.hpp> #include <mesh/Mesh.hpp> @@ -50,6 +51,8 @@ TEST_CASE("MedianDualConnectivityBuilder", "[mesh]") DualConnectivityManager::instance().getMedianDualConnectivity(primal_connectivity); const ConnectivityType& dual_connectivity = *p_median_dual_connectivity; + REQUIRE(checkConnectivityOrdering(dual_connectivity)); + REQUIRE(dual_connectivity.numberOfNodes() == 192); REQUIRE(dual_connectivity.numberOfFaces() == 244); REQUIRE(dual_connectivity.numberOfCells() == 53);