diff --git a/src/language/modules/BinaryOperatorRegisterForVh.cpp b/src/language/modules/BinaryOperatorRegisterForVh.cpp index 675d84772cc9764df42be29b8be9a03de77c6858..1af57fc9e7e6308a7d96540245d66246c1977e00 100644 --- a/src/language/modules/BinaryOperatorRegisterForVh.cpp +++ b/src/language/modules/BinaryOperatorRegisterForVh.cpp @@ -14,89 +14,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 +105,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 +196,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 +292,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..17f005e88c5c6ed9ec35ed4b9021c51899f69972 100644 --- a/src/language/modules/MathFunctionRegisterForVh.cpp +++ b/src/language/modules/MathFunctionRegisterForVh.cpp @@ -3,360 +3,373 @@ #include <language/modules/SchemeModule.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp> -#include <scheme/IDiscreteFunction.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/IDiscreteFunctionDescriptor.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); } - [](std::shared_ptr<const IDiscreteFunction> A) - -> std::shared_ptr<const IDiscreteFunction> { return inverse(A); } + )); - )); + scheme_module._addBuiltinFunction("min", + std::function( + + [](std::shared_ptr<const DiscreteFunctionVariant> a) -> double { return min(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 +378,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 +387,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 +396,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 +405,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 +414,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 +423,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/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp index e3c6f1b96bf5ae660f7e3648ab70858edd4c20a3..cf1212e088bfda45f4e3030d5822b2d3f1b40da6 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> @@ -42,6 +43,8 @@ SchemeModule::SchemeModule() { + this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const DiscreteFunctionVariant>>); +#warning remove after reworked this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IDiscreteFunction>>); this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IDiscreteFunctionDescriptor>>); this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IQuadratureDescriptor>>); @@ -96,11 +99,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()); } )); @@ -112,34 +115,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()); } )); @@ -151,21 +160,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"); @@ -175,30 +185,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( diff --git a/src/language/modules/SchemeModule.hpp b/src/language/modules/SchemeModule.hpp index 6c1f0324aa2858437ec8d7f49434c2d8ac718a45..868c681af6468ac667456d977c5f62814f1ba93e 100644 --- a/src/language/modules/SchemeModule.hpp +++ b/src/language/modules/SchemeModule.hpp @@ -10,10 +10,16 @@ template <> inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IBoundaryConditionDescriptor>> = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("boundary_condition"); +class DiscreteFunctionVariant; +template <> +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const DiscreteFunctionVariant>> = + ASTNodeDataType::build<ASTNodeDataType::type_id_t>("Vh"); + +#warning remove after reworked class IDiscreteFunction; template <> inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IDiscreteFunction>> = - ASTNodeDataType::build<ASTNodeDataType::type_id_t>("Vh"); + ASTNodeDataType::build<ASTNodeDataType::type_id_t>("Vh_legacy"); class IDiscreteFunctionDescriptor; template <> diff --git a/src/language/modules/UnaryOperatorRegisterForVh.cpp b/src/language/modules/UnaryOperatorRegisterForVh.cpp index b1dc85aa9dd11be2f5a6d159d8f1a70254d68c7b..db3b61058e51dc615088e34108667b5b82c6f7de 100644 --- a/src/language/modules/UnaryOperatorRegisterForVh.cpp +++ b/src/language/modules/UnaryOperatorRegisterForVh.cpp @@ -14,8 +14,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/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt index 0fe1c798ba77d98b4453ded4d4c3334c0d2199e5..0254d25cafda269cb94cb7008e893ed16635b7e1 100644 --- a/src/language/utils/CMakeLists.txt +++ b/src/language/utils/CMakeLists.txt @@ -25,7 +25,6 @@ add_library(PugsLanguageUtils EmbeddedData.cpp EmbeddedIDiscreteFunctionMathFunctions.cpp EmbeddedIDiscreteFunctionOperators.cpp - EmbeddedIDiscreteFunctionUtils.cpp FunctionSymbolId.cpp IncDecOperatorRegisterForN.cpp IncDecOperatorRegisterForZ.cpp diff --git a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp index 67622f4a7c2ebbc7284f7305be98aeb3beb8768f..63b7d47b462c3c73932c43a3435c0a9382630624 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.cpp @@ -5,1003 +5,587 @@ #include <scheme/DiscreteFunctionP0.hpp> #include <scheme/DiscreteFunctionP0Vector.hpp> #include <scheme/DiscreteFunctionUtils.hpp> +#include <scheme/DiscreteFunctionVariant.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) +#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(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); \ + } \ + } else { \ + throw NormalError(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::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 IDiscreteFunction> -abs(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -sin(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -cos(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -tan(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -asin(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -acos(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -atan(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -atan2(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +atan2(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - 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)); - } + DISCRETE_VH_VH_TO_VH_REAL_FUNCTION_CALL(atan2, f_v, g_v); } -std::shared_ptr<const IDiscreteFunction> -atan2(const double a, const std::shared_ptr<const IDiscreteFunction>& f) +std::shared_ptr<const DiscreteFunctionVariant> +atan2(const double a, const std::shared_ptr<const DiscreteFunctionVariant>& 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)); - } + DISCRETE_R_VH_TO_VH_REAL_FUNCTION_CALL(atan2, a, f); } -std::shared_ptr<const IDiscreteFunction> -atan2(const std::shared_ptr<const IDiscreteFunction>& f, const double a) +std::shared_ptr<const DiscreteFunctionVariant> +atan2(const std::shared_ptr<const DiscreteFunctionVariant>& 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)); - } + DISCRETE_VH_R_TO_VH_REAL_FUNCTION_CALL(atan2, f, a); } -std::shared_ptr<const IDiscreteFunction> -sinh(const std::shared_ptr<const IDiscreteFunction>& f) +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 IDiscreteFunction> -cosh(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -tanh(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -asinh(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -acosh(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -atanh(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -exp(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -log(const std::shared_ptr<const IDiscreteFunction>& 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 IDiscreteFunction> -pow(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +pow(const std::shared_ptr<const DiscreteFunctionVariant>& f, const std::shared_ptr<const DiscreteFunctionVariant>& 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)); - } + DISCRETE_VH_VH_TO_VH_REAL_FUNCTION_CALL(pow, f, g); } -std::shared_ptr<const IDiscreteFunction> -pow(const double a, const std::shared_ptr<const IDiscreteFunction>& f) +std::shared_ptr<const DiscreteFunctionVariant> +pow(const double a, const std::shared_ptr<const DiscreteFunctionVariant>& 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)); - } + DISCRETE_R_VH_TO_VH_REAL_FUNCTION_CALL(pow, a, f); } -std::shared_ptr<const IDiscreteFunction> -pow(const std::shared_ptr<const IDiscreteFunction>& f, const double a) +std::shared_ptr<const DiscreteFunctionVariant> +pow(const std::shared_ptr<const DiscreteFunctionVariant>& 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)); - } + DISCRETE_VH_R_TO_VH_REAL_FUNCTION_CALL(pow, 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) +std::shared_ptr<const DiscreteFunctionVariant> +dot(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - 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 - } + if (not hasSameMesh({f_v, g_v})) { + throw NormalError("operands are defined on different meshes"); } -} - -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)); - } + 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(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); + } + } + }, + f_v->discreteFunction(), g_v->discreteFunction()); } -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 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); + } + }, + f->discreteFunction()); } 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)); - } +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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::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(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(A)); + } + }, + A->discreteFunction()); } -template <size_t Dimension, size_t VectorDimension> -std::shared_ptr<const IDiscreteFunction> -dot(const TinyVector<VectorDimension>& a, const std::shared_ptr<const IDiscreteFunction>& f) +double +min(const std::shared_ptr<const DiscreteFunctionVariant>& 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))); + DISCRETE_VH_TO_R_CALL(min, f); } -template <size_t VectorDimension> -std::shared_ptr<const IDiscreteFunction> -dot(const TinyVector<VectorDimension>& a, const std::shared_ptr<const IDiscreteFunction>& f) +std::shared_ptr<const DiscreteFunctionVariant> +min(const std::shared_ptr<const DiscreteFunctionVariant>& f, const std::shared_ptr<const DiscreteFunctionVariant>& g) { - 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)); - } + DISCRETE_VH_VH_TO_VH_REAL_FUNCTION_CALL(min, f, g); } -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) +std::shared_ptr<const DiscreteFunctionVariant> +min(const double a, const std::shared_ptr<const DiscreteFunctionVariant>& f) { - 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"); - } - } + DISCRETE_R_VH_TO_VH_REAL_FUNCTION_CALL(min, a, f); } -std::shared_ptr<const IDiscreteFunction> -det(const std::shared_ptr<const IDiscreteFunction>& A) +std::shared_ptr<const DiscreteFunctionVariant> +min(const std::shared_ptr<const DiscreteFunctionVariant>& f, const double 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)); - } + DISCRETE_VH_R_TO_VH_REAL_FUNCTION_CALL(min, f, a); } -template <typename MatrixType> -std::shared_ptr<const IDiscreteFunction> -trace(const std::shared_ptr<const IDiscreteFunction>& A) +double +max(const std::shared_ptr<const DiscreteFunctionVariant>& f) { - 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"); - } - } + DISCRETE_VH_TO_R_CALL(max, f); } -std::shared_ptr<const IDiscreteFunction> -trace(const std::shared_ptr<const IDiscreteFunction>& A) +std::shared_ptr<const DiscreteFunctionVariant> +max(const std::shared_ptr<const DiscreteFunctionVariant>& f, const std::shared_ptr<const DiscreteFunctionVariant>& g) { - 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)); - } + DISCRETE_VH_VH_TO_VH_REAL_FUNCTION_CALL(max, f, g); } -template <typename MatrixType> -std::shared_ptr<const IDiscreteFunction> -inverse(const std::shared_ptr<const IDiscreteFunction>& A) +std::shared_ptr<const DiscreteFunctionVariant> +max(const double a, const std::shared_ptr<const DiscreteFunctionVariant>& f) { - 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"); - } - } + DISCRETE_R_VH_TO_VH_REAL_FUNCTION_CALL(max, a, f); } -std::shared_ptr<const IDiscreteFunction> -inverse(const std::shared_ptr<const IDiscreteFunction>& A) +std::shared_ptr<const DiscreteFunctionVariant> +max(const std::shared_ptr<const DiscreteFunctionVariant>& f, const double 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)); - } + DISCRETE_VH_R_TO_VH_REAL_FUNCTION_CALL(max, f, 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"); - } - } -} +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(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); + } + }, + f->discreteFunction()); -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)); - } + return value; } -double -min(const std::shared_ptr<const IDiscreteFunction>& f) +std::shared_ptr<const DiscreteFunctionVariant> +sum_of_Vh_components(const std::shared_ptr<const DiscreteFunctionVariant>& 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)); - } + 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(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); + } + }, + f->discreteFunction()); } -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 +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(EmbeddedIDiscreteFunctionUtils::invalidOperandType(discrete_function)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(discrete_function)); + } + }, + discrete_function_list[i_discrete_function]->discreteFunction()); } - } 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)); + throw NormalError("discrete functions are not defined on the same mesh"); } } -std::shared_ptr<const IDiscreteFunction> -min(const std::shared_ptr<const IDiscreteFunction>& f, const double a) +std::shared_ptr<const DiscreteFunctionVariant> +vectorize(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_list) { - 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)); - } -} + if (hasSameMesh(discrete_function_list)) { + std::shared_ptr p_i_mesh = getCommonMesh(discrete_function_list); + Assert(p_i_mesh.use_count() > 0); -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()) { + switch (p_i_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)); - } -} + 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); -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}); + DiscreteFunctionVectorType vector_function(p_mesh, discrete_function_list.size()); + vectorize_to(discrete_function_list, *p_mesh, vector_function); - 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))); + return std::make_shared<DiscreteFunctionVariant>(vector_function); } 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)); - } -} + 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); -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)); - } -} + DiscreteFunctionVectorType vector_function(p_mesh, discrete_function_list.size()); + vectorize_to(discrete_function_list, *p_mesh, vector_function); -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)); + return std::make_shared<DiscreteFunctionVariant>(vector_function); } 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)); - } -} + 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); -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)); - } -} + DiscreteFunctionVectorType vector_function(p_mesh, discrete_function_list.size()); + vectorize_to(discrete_function_list, *p_mesh, vector_function); -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))); + return std::make_shared<DiscreteFunctionVariant>(vector_function); } // LCOV_EXCL_START default: { @@ -1010,148 +594,55 @@ sum_of_Vh_components(const std::shared_ptr<const IDiscreteFunction>& f) // 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 + throw NormalError("discrete functions are not defined on the same mesh"); } } -template double sum_of<double>(const std::shared_ptr<const IDiscreteFunction>&); +template double sum_of<double>(const std::shared_ptr<const DiscreteFunctionVariant>&); -template TinyVector<1> sum_of<TinyVector<1>>(const std::shared_ptr<const IDiscreteFunction>&); +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 IDiscreteFunction>&); +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 IDiscreteFunction>&); +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 IDiscreteFunction>&); +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 IDiscreteFunction>&); +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 IDiscreteFunction>&); +template TinyMatrix<3> sum_of<TinyMatrix<3>>(const std::shared_ptr<const DiscreteFunctionVariant>&); 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)); - } +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(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); + } + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::invalidOperandType(f)); + } + }, + f->discreteFunction()); } -template double integral_of<double>(const std::shared_ptr<const IDiscreteFunction>&); +template double integral_of<double>(const std::shared_ptr<const DiscreteFunctionVariant>&); -template TinyVector<1> integral_of<TinyVector<1>>(const std::shared_ptr<const IDiscreteFunction>&); +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 IDiscreteFunction>&); +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 IDiscreteFunction>&); +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 IDiscreteFunction>&); +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 IDiscreteFunction>&); +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 IDiscreteFunction>&); +template TinyMatrix<3> integral_of<TinyMatrix<3>>(const std::shared_ptr<const DiscreteFunctionVariant>&); diff --git a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp index 24994c743428d98befb8d34cc18c2cbbf12a2ba4..9a310d0998f962ea02f7010c0b47dfd49e34fde2 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionMathFunctions.hpp @@ -6,100 +6,105 @@ #include <memory> -class IDiscreteFunction; +class DiscreteFunctionVariant; -std::shared_ptr<const IDiscreteFunction> sqrt(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> sqrt(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> abs(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> sqrt(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> sin(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> abs(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> cos(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> sin(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> tan(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> cos(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> asin(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> tan(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> acos(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> asin(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> atan(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> acos(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> atan2(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> atan(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> atan2(const double, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> atan2(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> atan2(const std::shared_ptr<const IDiscreteFunction>&, const double); +std::shared_ptr<const DiscreteFunctionVariant> atan2(const double, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> sinh(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> atan2(const std::shared_ptr<const DiscreteFunctionVariant>&, + const double); -std::shared_ptr<const IDiscreteFunction> cosh(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> sinh(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> tanh(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> cosh(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> asinh(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> tanh(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> acosh(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> asinh(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> atanh(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> acosh(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> exp(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> atanh(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> log(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> exp(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> pow(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> log(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> pow(const double, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> pow(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> pow(const std::shared_ptr<const IDiscreteFunction>&, const double); +std::shared_ptr<const DiscreteFunctionVariant> pow(const double, const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> dot(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); +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 IDiscreteFunction> dot(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<VectorDimension>&); +std::shared_ptr<const DiscreteFunctionVariant> dot(const std::shared_ptr<const DiscreteFunctionVariant>&, + 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 DiscreteFunctionVariant> dot(const TinyVector<VectorDimension>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> det(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> det(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> trace(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> trace(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> inverse(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> inverse(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> transpose(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> transpose(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> sum_of_Vh_components(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> sum_of_Vh_components( + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> vectorize( - const std::vector<std::shared_ptr<const IDiscreteFunction>>& discrete_function_list); +std::shared_ptr<const DiscreteFunctionVariant> vectorize( + const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_list); -double min(const std::shared_ptr<const IDiscreteFunction>&); +double min(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> min(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> min(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> min(const double, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> min(const double, const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> min(const std::shared_ptr<const IDiscreteFunction>&, const double); +std::shared_ptr<const DiscreteFunctionVariant> min(const std::shared_ptr<const DiscreteFunctionVariant>&, const double); -double max(const std::shared_ptr<const IDiscreteFunction>&); +double max(const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> max(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> max(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> max(const double, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> max(const double, const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> max(const std::shared_ptr<const IDiscreteFunction>&, const double); +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 IDiscreteFunction>&); +ValueT sum_of(const std::shared_ptr<const DiscreteFunctionVariant>&); template <typename ValueT> -ValueT integral_of(const std::shared_ptr<const IDiscreteFunction>&); +ValueT integral_of(const std::shared_ptr<const DiscreteFunctionVariant>&); #endif // EMBEDDED_I_DISCRETE_FUNCTION_MATH_FUNCTIONS_HPP diff --git a/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp b/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp index 656164d6fc012ef2469f846d3e54f32a9c1d4927..bc4dabaabc76f5e5c5e83928b5174d3e3d36c640 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionOperators.cpp @@ -6,759 +6,262 @@ #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> +std::shared_ptr<const DiscreteFunctionVariant> 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 - } + return std::make_shared<DiscreteFunctionVariant>(UnaryOp<UnaryOperatorT>{}.eval(f)); } -std::shared_ptr<const IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v) { - return applyUnaryOperation<language::unary_minus>(f); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyUnaryOperation<language::unary_minus>(f); + }, + f_v->discreteFunction()); } // binary operators -template <typename BinOperatorT, typename DiscreteFunctionT> -std::shared_ptr<const IDiscreteFunction> -innerCompositionLaw(const DiscreteFunctionT& lhs, const DiscreteFunctionT& rhs) +template <typename DiscreteFunctionT, typename BinOperatorT> +std::shared_ptr<const DiscreteFunctionVariant> +innerCompositionLaw(const DiscreteFunctionT& f, const DiscreteFunctionT& g) { - Assert(lhs.mesh() == rhs.mesh()); - using data_type = typename DiscreteFunctionT::data_type; + 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(lhs, rhs)); + throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); } 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); + if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionT>) { + if (f.size() != g.size()) { + std::ostringstream error_msg; + error_msg << EmbeddedIDiscreteFunctionUtils::getOperandTypeName(f) << " spaces have different sizes"; + throw NormalError(error_msg.str()); } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(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)); + return std::make_shared<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(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) +template <typename DiscreteFunctionT1, typename DiscreteFunctionT2, typename BinOperatorT> +std::shared_ptr<const DiscreteFunctionVariant> +applyBinaryOperation(const DiscreteFunctionT1& f, const DiscreteFunctionT2& 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); + 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(fh, g)); + throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, 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(f, g)); } } 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<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - std::shared_ptr mesh = getCommonMesh({f, g}); - if (mesh.use_count() == 0) { + if (not hasSameMesh({f_v, g_v})) { 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 - } + 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f_v, g_v)); + } + }, + f_v->discreteFunction(), g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - if (EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)) { - return innerCompositionLaw<language::plus_op>(f, g); - } else { - throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, g)); + if (not hasSameMesh({f_v, g_v})) { + throw NormalError("operands are defined on different meshes"); } -} -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)); - } + 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f_v, g_v)); + } + }, + f_v->discreteFunction(), g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - if (EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)) { - return innerCompositionLaw<language::multiply_op>(f, g); - } else { - return applyBinaryOperation<language::multiply_op>(f, g); + 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 IDiscreteFunction> -operator/(const std::shared_ptr<const IDiscreteFunction>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator/(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, + const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - if (EmbeddedIDiscreteFunctionUtils::isSameDiscretization(f, g)) { - return innerCompositionLaw<language::divide_op>(f, g); - } else { - return applyBinaryOperation<language::divide_op>(f, g); + 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f_v, g_v)); + } + }, + f_v->discreteFunction(), g_v->discreteFunction()); } template <typename BinOperatorT, typename DataType, typename DiscreteFunctionT> -std::shared_ptr<const IDiscreteFunction> +std::shared_ptr<const DiscreteFunctionVariant> 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 (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<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)); + 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(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_same_v<rhs_data_type, double>) { + return std::make_shared<DiscreteFunctionVariant>(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<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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(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 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(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) +std::shared_ptr<const DiscreteFunctionVariant> +applyBinaryOperationWithRightConstant(const DiscreteFunctionT& f, const DataType& a) { - 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)); - } -} + 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>; -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); + 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); + throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); } - } - 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 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(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); + 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<DiscreteFunctionVariant>(BinOp<BinOperatorT>{}.eval(f, a)); + } else { + throw NormalError(EmbeddedIDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); } - // 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 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(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)); } @@ -767,331 +270,402 @@ applyBinaryOperationWithRightConstant(const DiscreteFunctionT& f, const DataType } } -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) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const double& f, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const std::shared_ptr<const IDiscreteFunction>& f, const double& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyVector<1>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(v, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const TinyVector<1>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyVector<2>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(v, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const TinyVector<2>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyVector<3>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(v, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const TinyVector<3>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyMatrix<1>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(A, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const TinyMatrix<1>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyMatrix<2>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(A, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const TinyMatrix<2>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const TinyMatrix<3>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::plus_op>(A, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const TinyMatrix<3>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const double& g) { - return applyBinaryOperationWithLeftConstant<language::plus_op>(f, 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 IDiscreteFunction> -operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<1>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<1>& v) { - return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, v); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<2>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<2>& v) { - return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, v); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<3>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<3>& v) { - return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, v); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<1>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<1>& A) { - return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, A); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<2>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<2>& A) { - return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, A); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator+(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<3>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator+(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<3>& A) { - return applyBinaryOperationWithRightConstant<language::plus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::plus_op>(f, A); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const double& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const double& f, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f, const double& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyVector<1>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(v, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const TinyVector<1>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyVector<2>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(v, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const TinyVector<2>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyVector<3>& v, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(v, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const TinyVector<3>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyMatrix<1>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(A, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const TinyMatrix<1>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyMatrix<2>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(A, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const TinyMatrix<2>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const TinyMatrix<3>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::minus_op>(A, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const TinyMatrix<3>& f, const std::shared_ptr<const IDiscreteFunction>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const double& g) { - return applyBinaryOperationWithLeftConstant<language::minus_op>(f, 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 IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<1>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<1>& v) { - return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, v); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<2>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<2>& v) { - return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, v); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyVector<3>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<3>& v) { - return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, v); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<1>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<1>& A) { - return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, A); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<2>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<2>& A) { - return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, A); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator-(const std::shared_ptr<const IDiscreteFunction>& f, const TinyMatrix<3>& g) +std::shared_ptr<const DiscreteFunctionVariant> +operator-(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<3>& A) { - return applyBinaryOperationWithRightConstant<language::minus_op>(f, g); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::minus_op>(f, A); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const double& a, const std::shared_ptr<const IDiscreteFunction>& f) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const double& f, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::multiply_op>(a, f); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::multiply_op>(f, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& f, const double& a) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const TinyMatrix<1>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithRightConstant<language::multiply_op>(f, a); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const TinyMatrix<1>& A, const std::shared_ptr<const IDiscreteFunction>& B) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const TinyMatrix<2>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, B); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const TinyMatrix<2>& A, const std::shared_ptr<const IDiscreteFunction>& B) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const TinyMatrix<3>& A, const std::shared_ptr<const DiscreteFunctionVariant>& g_v) { - return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, B); + return std::visit( + [&](auto&& g) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, g); + }, + g_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const TinyMatrix<3>& A, const std::shared_ptr<const IDiscreteFunction>& B) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const double& g) { - return applyBinaryOperationWithLeftConstant<language::multiply_op>(A, B); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, g); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyVector<1>& u) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<1>& v) { - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, u); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, v); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyVector<2>& u) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<2>& v) { - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, u); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, v); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyVector<3>& u) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyVector<3>& v) { - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, u); + return std::visit( + [&](auto&& f) -> std::shared_ptr<const DiscreteFunctionVariant> { // + return applyBinaryOperationWithRightConstant<language::multiply_op>(f, v); + }, + f_v->discreteFunction()); } -std::shared_ptr<const IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyMatrix<1>& A) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<1>& A) { - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, 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 IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyMatrix<2>& A) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<2>& A) { - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, 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 IDiscreteFunction> -operator*(const std::shared_ptr<const IDiscreteFunction>& a, const TinyMatrix<3>& A) +std::shared_ptr<const DiscreteFunctionVariant> +operator*(const std::shared_ptr<const DiscreteFunctionVariant>& f_v, const TinyMatrix<3>& A) { - return applyBinaryOperationWithRightConstant<language::multiply_op>(a, 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 IDiscreteFunction> -operator/(const double& a, const std::shared_ptr<const IDiscreteFunction>& f) +std::shared_ptr<const DiscreteFunctionVariant> +operator/(const double& a, const std::shared_ptr<const DiscreteFunctionVariant>& f_v) { - return applyBinaryOperationWithLeftConstant<language::divide_op>(a, f); + 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/EmbeddedIDiscreteFunctionOperators.hpp b/src/language/utils/EmbeddedIDiscreteFunctionOperators.hpp index f797a95d03e19a796d9af965d81bbd3970c6cddd..e1291e08136f5945404807da33516fd8d8b4604c 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionOperators.hpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionOperators.hpp @@ -6,138 +6,146 @@ #include <memory> -class IDiscreteFunction; +class DiscreteFunctionVariant; // unary minus -std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&); // sum -std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator+(const double&, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const double&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, const double&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const double&); -std::shared_ptr<const IDiscreteFunction> operator+(const TinyVector<1>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyVector<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator+(const TinyVector<2>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyVector<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator+(const TinyVector<3>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyVector<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator+(const TinyMatrix<1>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyMatrix<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator+(const TinyMatrix<2>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyMatrix<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator+(const TinyMatrix<3>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const TinyMatrix<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<1>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<1>&); -std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<2>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<2>&); -std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<3>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<3>&); -std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, - const TinyMatrix<1>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<1>&); -std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, - const TinyMatrix<2>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<2>&); -std::shared_ptr<const IDiscreteFunction> operator+(const std::shared_ptr<const IDiscreteFunction>&, - const TinyMatrix<3>&); +std::shared_ptr<const DiscreteFunctionVariant> operator+(const std::shared_ptr<const DiscreteFunctionVariant>&, + 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 DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator-(const double&, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const double&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, const double&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const double&); -std::shared_ptr<const IDiscreteFunction> operator-(const TinyVector<1>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyVector<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator-(const TinyVector<2>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyVector<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator-(const TinyVector<3>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyVector<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator-(const TinyMatrix<1>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyMatrix<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator-(const TinyMatrix<2>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyMatrix<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator-(const TinyMatrix<3>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const TinyMatrix<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<1>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<1>&); -std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<2>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<2>&); -std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<3>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<3>&); -std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, - const TinyMatrix<1>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<1>&); -std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, - const TinyMatrix<2>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<2>&); -std::shared_ptr<const IDiscreteFunction> operator-(const std::shared_ptr<const IDiscreteFunction>&, - const TinyMatrix<3>&); +std::shared_ptr<const DiscreteFunctionVariant> operator-(const std::shared_ptr<const DiscreteFunctionVariant>&, + 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 DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator*(const double&, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const double&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, const double&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const double&); -std::shared_ptr<const IDiscreteFunction> operator*(const TinyMatrix<1>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const TinyMatrix<1>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator*(const TinyMatrix<2>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const TinyMatrix<2>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator*(const TinyMatrix<3>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const TinyMatrix<3>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<1>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<1>&); -std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<2>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<2>&); -std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, - const TinyVector<3>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyVector<3>&); -std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, - const TinyMatrix<1>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<1>&); -std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, - const TinyMatrix<2>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<2>&); -std::shared_ptr<const IDiscreteFunction> operator*(const std::shared_ptr<const IDiscreteFunction>&, - const TinyMatrix<3>&); +std::shared_ptr<const DiscreteFunctionVariant> operator*(const std::shared_ptr<const DiscreteFunctionVariant>&, + const TinyMatrix<3>&); // ratio -std::shared_ptr<const IDiscreteFunction> operator/(const double&, const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator/(const double&, + const std::shared_ptr<const DiscreteFunctionVariant>&); -std::shared_ptr<const IDiscreteFunction> operator/(const std::shared_ptr<const IDiscreteFunction>&, - const std::shared_ptr<const IDiscreteFunction>&); +std::shared_ptr<const DiscreteFunctionVariant> operator/(const std::shared_ptr<const DiscreteFunctionVariant>&, + const std::shared_ptr<const DiscreteFunctionVariant>&); +# #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/language/utils/EmbeddedIDiscreteFunctionUtils.hpp b/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp index 1e61f917dfa448add18b562dd403a70101dbec3b..e8ba3a3840722a5d08736651cd35cc8b6b52a6a8 100644 --- a/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp +++ b/src/language/utils/EmbeddedIDiscreteFunctionUtils.hpp @@ -2,9 +2,11 @@ #define EMBEDDED_I_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 @@ -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) diff --git a/src/scheme/DiscreteFunctionIntegrator.cpp b/src/scheme/DiscreteFunctionIntegrator.cpp index 93c836461ce14ae05b51b879cf90525f73a793eb..f5aa2829a88c17ea5e2a941de4815ee5db27d979 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,7 +168,7 @@ DiscreteFunctionIntegrator::_integrate() const } } -std::shared_ptr<IDiscreteFunction> +DiscreteFunctionVariant DiscreteFunctionIntegrator::integrate() const { std::shared_ptr<IDiscreteFunction> discrete_function; 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..762330d77080f8fe82c1d7923fbfe89db8156654 100644 --- a/src/scheme/DiscreteFunctionP0.hpp +++ b/src/scheme/DiscreteFunctionP0.hpp @@ -33,7 +33,7 @@ class DiscreteFunctionP0 : public IDiscreteFunction ASTNodeDataType dataType() const final { - return ast_node_data_type_from<DataType>; + return ast_node_data_type_from<std::remove_const_t<DataType>>; } PUGS_INLINE @@ -450,7 +450,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 +463,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 +475,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 +487,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 +500,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 +512,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 +527,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 +539,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 +548,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 +577,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 +590,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 +602,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 +620,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 +633,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 +645,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 +666,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 +679,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 +691,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 +720,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 +745,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..351b6e4ec6e8249791c15524cef883be67cec547 100644 --- a/src/scheme/DiscreteFunctionP0Vector.hpp +++ b/src/scheme/DiscreteFunctionP0Vector.hpp @@ -38,7 +38,7 @@ class DiscreteFunctionP0Vector : public IDiscreteFunction ASTNodeDataType dataType() const final { - return ast_node_data_type_from<data_type>; + return ast_node_data_type_from<std::remove_const_t<data_type>>; } PUGS_INLINE diff --git a/src/scheme/DiscreteFunctionUtils.cpp b/src/scheme/DiscreteFunctionUtils.cpp index fe861c0868b6bf620696cba09d8ac72bcf6aa948..f9b6873406adc409a438ba2164b6ac637e1fa2d4 100644 --- a/src/scheme/DiscreteFunctionUtils.cpp +++ b/src/scheme/DiscreteFunctionUtils.cpp @@ -4,8 +4,55 @@ #include <mesh/IMesh.hpp> #include <mesh/Mesh.hpp> #include <scheme/DiscreteFunctionP0.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <utils/Stringify.hpp> +std::shared_ptr<const IMesh> +getCommonMesh(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()); + } + 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 is_same_mesh; +} + template <size_t Dimension, typename DataType> std::shared_ptr<const IDiscreteFunction> shallowCopy(const std::shared_ptr<const Mesh<Connectivity<Dimension>>>& mesh, diff --git a/src/scheme/DiscreteFunctionUtils.hpp b/src/scheme/DiscreteFunctionUtils.hpp index e01437f2b0e0d1c7dc9468bea6f63aa0b14aae74..c788e3768fc11266601e9e90614893a0ac7b7388 100644 --- a/src/scheme/DiscreteFunctionUtils.hpp +++ b/src/scheme/DiscreteFunctionUtils.hpp @@ -2,6 +2,7 @@ #define DISCRETE_FUNCTION_UTILS_HPP #include <scheme/DiscreteFunctionType.hpp> +#include <scheme/DiscreteFunctionVariant.hpp> #include <scheme/IDiscreteFunction.hpp> #include <scheme/IDiscreteFunctionDescriptor.hpp> @@ -37,6 +38,11 @@ getCommonMesh(const std::vector<std::shared_ptr<const IDiscreteFunction>>& discr 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); 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/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/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3f174398186c2b5fd0bcc56aef017f40936f9704..10995de788daf3ece543c47a7c8adb7aa6cb74f0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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_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_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_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..5760703b91f79ccef3a32d23b76e9f4d2ace48b8 --- /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/EmbeddedIDiscreteFunctionMathFunctions.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..958b3bd5701dce9af9cda9dc7b869c37bf5a2f16 --- /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/EmbeddedIDiscreteFunctionMathFunctions.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..9fd3ad39f7f016c37e9a18f219998d694f4411ec --- /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/EmbeddedIDiscreteFunctionMathFunctions.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..8cb58b09e692ea2764f735d01ca4d566af818cfa --- /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/EmbeddedIDiscreteFunctionOperators.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_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 index 476103c42897ca8f86f2a5515f110e87b2ac0d9c..8e3f65030ada56f4de3891a5506b55850aa52d40 100644 --- a/tests/test_EmbeddedIDiscreteFunctionUtils.cpp +++ b/tests/test_EmbeddedIDiscreteFunctionUtils.cpp @@ -72,90 +72,6 @@ TEST_CASE("EmbeddedIDiscreteFunctionUtils", "[language]") } } - 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") {