diff --git a/cmake/modules/DuneXtMacros.cmake b/cmake/modules/DuneXtMacros.cmake index 3399d2aa8fdb57f907fd79294a30bdc740edaf24..b52731c495b2c328e03eadbd96861621b1abd7b4 100644 --- a/cmake/modules/DuneXtMacros.cmake +++ b/cmake/modules/DuneXtMacros.cmake @@ -100,7 +100,7 @@ if(HAVE_MPI) # this only works in dependent modules dune_register_package_flags(INCLUDE_DIRS "${MPI4PY_INCLUDE_DIR}") # this only works in dune-xt itself - include_directories("${MPI4PY_INCLUDE_DIR}" ${PYTHON_INCLUDE_DIRS}) + include_directories(SYSTEM "${MPI4PY_INCLUDE_DIR}" ${PYTHON_INCLUDE_DIRS}) else() message(FATAL_ERROR kaput) endif() diff --git a/cmake/modules/FindClangTidy.cmake b/cmake/modules/FindClangTidy.cmake index 9bde293f4914bc03741d0945a264ddfd94aa5692..cf595db5debf543931f784e8bfa25d31b55b6663 100644 --- a/cmake/modules/FindClangTidy.cmake +++ b/cmake/modules/FindClangTidy.cmake @@ -33,7 +33,7 @@ find_program(ClangTidy_EXECUTABLE if(EXISTS ${ClangTidy_EXECUTABLE}) execute_process(COMMAND ${ClangTidy_EXECUTABLE} -version OUTPUT_VARIABLE clang_out) string(REGEX - REPLACE ".*LLVM version ([0-9]+\\.[0-9]+).*" + REPLACE ".*LLVM version ([0-9]+)\.[0-9]+\.[0-9]*.*" "\\1" ClangTidy_VERSION ${clang_out}) diff --git a/cmake/modules/XtCompilerSupport.cmake b/cmake/modules/XtCompilerSupport.cmake index eff7904c94b1e944bcf06ff9f66a26fa606d32cd..b649a881b771dba4d57f381395335995cf66d0ec 100644 --- a/cmake/modules/XtCompilerSupport.cmake +++ b/cmake/modules/XtCompilerSupport.cmake @@ -25,13 +25,8 @@ endmacro(ADD_IF_SUPPORTED) macro(INCLUDE_SYS_DIR) foreach(ARG ${ARGN}) if(IS_DIRECTORY ${ARG}) - include_directories(${ARG}) # due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129 we have to filter what - # to sys-include includes - if(${ARG} MATCHES "/usr/include") - message(AUTHOR_WARNING "-isystem not supported for ${ARG}") - else() - add_definitions("-isystem ${ARG}") - endif() + include_directories(SYSTEM ${ARG}) # due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129 we have to filter + # what to sys-include includes else(IS_DIRECTORY ${ARG}) message(STATUS "Include directory ${ARG} does not exist") endif(IS_DIRECTORY ${ARG}) diff --git a/cmake/modules/XtTooling.cmake b/cmake/modules/XtTooling.cmake index 1347da95a2de9a6396b9d25ef6177cfcf6105603..74b1b6c13703c8a18846119aaa935e95428f5bdc 100644 --- a/cmake/modules/XtTooling.cmake +++ b/cmake/modules/XtTooling.cmake @@ -94,20 +94,56 @@ macro(add_format glob_dir) endmacro(add_format) find_package(ClangTidy 8) -macro(add_tidy glob_dir) +macro(add_tidy) if(ClangTidy_FOUND) dune_symlink_to_source_files(FILES .clang-tidy) message(STATUS "adding tidy target") - set(TIDY_ARGS -config= -style=file -p=${CMAKE_CURRENT_BINARY_DIR} -j ${DXT_TEST_PROCS}) - add_custom_target("tidy" - ${RunTidy_EXECUTABLE} - ${TIDY_ARGS} - -export-fixes=${CMAKE_CURRENT_BINARY_DIR}/clang-tidy.fixes) - add_custom_target("fix_tidy" ${RunTidy_EXECUTABLE} ${TIDY_ARGS} -fix) + add_custom_target(tidy) + add_custom_target(fix_tidy) + add_tidy_subdir(common) + add_tidy_subdir(grid) + add_tidy_subdir(la) + add_tidy_subdir(functions) else() message(WARNING "not adding tidy target because clang-tidy is missing or" "wrong version: ${ClangTidy_EXECUTABLE} ${ClangTidy_VERSION}") endif(ClangTidy_FOUND) +endmacro() + +macro(add_tidy_subdir _dxt_subdir) + set(BASE ${PROJECT_SOURCE_DIR}/dune/xt/${_dxt_subdir}) + # including the headercheck sources works around our headers needing included config.h to function adding "-extra- + # arg-before='-include config.h'" to TIDY_ARGS results in a tidy error despite the arg actually being applied + # correctly + file(GLOB_RECURSE _files + "${PROJECT_BINARY_DIR}/headercheck/dune/xt/${_dxt_subdir}/*.cc" + "${BASE}/*.cc" + "${BASE}/*.cxx" + "${BASE}/*.cpp" + "${BASE}/*.c") + set(BASE ${PROJECT_SOURCE_DIR}/python/dune/xt/${_dxt_subdir}) + file(GLOB_RECURSE _pyfiles + "${PROJECT_BINARY_DIR}/headercheck/python/dune/xt/${_dxt_subdir}/*.cc" + "${BASE}/*.cc" + "${BASE}/*.cxx" + "${BASE}/*.cpp" + "${BASE}/*.c") + list(APPEND _files ${_pyfiles}) + list(REMOVE_DUPLICATES _files) + set(TIDY_ARGS + -config= + -format-style=file + -p=${CMAKE_CURRENT_BINARY_DIR} + -header-filter=\".*/dune/xt/${_dxt_subdir}.*\") + add_custom_target(tidy_${_dxt_subdir} + COMMAND ${ClangTidy_EXECUTABLE} ${TIDY_ARGS} + -export-fixes=${CMAKE_CURRENT_BINARY_DIR}/clang-tidy.fixes ${_files} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + add_custom_target(fix_tidy_${_dxt_subdir} + COMMAND ${ClangTidy_EXECUTABLE} ${TIDY_ARGS} -fix ${_files} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + add_dependencies(tidy tidy_${_dxt_subdir}) + add_dependencies(fix_tidy fix_tidy_${_dxt_subdir}) endmacro(add_tidy) macro(add_forced_doxygen_target) diff --git a/dune/xt/common/configuration.cc b/dune/xt/common/configuration.cc index 1c2296dd1149b25fb9fe364709b7ac13627d082e..5254ad12c5dd75a51602a22fc702397e0835225b 100644 --- a/dune/xt/common/configuration.cc +++ b/dune/xt/common/configuration.cc @@ -126,7 +126,7 @@ bool Configuration::has_key(const std::string& key) const return BaseType::hasKey(key); } -Configuration Configuration::sub(const std::string sub_id, bool fail_if_missing, Configuration default_value) const +Configuration Configuration::sub(const std::string& sub_id, bool fail_if_missing, Configuration default_value) const { if ((empty() || !has_sub(sub_id)) && !fail_if_missing) return default_value; @@ -146,7 +146,7 @@ Configuration Configuration::sub(const std::string sub_id, bool fail_if_missing, return Configuration(BaseType::sub(sub_id)); } // ... sub(...) -bool Configuration::has_sub(const std::string subTreeName) const +bool Configuration::has_sub(const std::string& subTreeName) const { return BaseType::hasSub(subTreeName); } diff --git a/dune/xt/common/configuration.hh b/dune/xt/common/configuration.hh index b2db3b92e18f14f88cfba7ecd2b4b0766eb5289b..e71dcf44df16c0eb6c504ffa693b1a060f5c2d2f 100644 --- a/dune/xt/common/configuration.hh +++ b/dune/xt/common/configuration.hh @@ -124,7 +124,7 @@ some_function_which_expects_a_config({{"type", "custom"}, {"tolerance", "1e-10"} bool has_key(const std::string& key) const; //! check if sub is existing in tree_ - bool has_sub(const std::string subTreeName) const; + bool has_sub(const std::string& subTreeName) const; /** \brief print the ParameterTree * \param out output stream @@ -136,7 +136,7 @@ some_function_which_expects_a_config({{"type", "custom"}, {"tolerance", "1e-10"} * @attention Please note the difference to Dune::ParameterTree::sub (return: value vs. reference)! */ Configuration - sub(const std::string sub_id, bool fail_if_missing = true, Configuration default_value = Configuration()) const; + sub(const std::string& sub_id, bool fail_if_missing = true, Configuration default_value = Configuration()) const; /** * \} diff --git a/dune/xt/common/fmatrix-2.7.hh b/dune/xt/common/fmatrix-2.7.hh index 145533bfc7bc7398ce7ec29ca67c38b869138842..c8cc7e37eea9f006db03c023aa510f8c4d71c575 100644 --- a/dune/xt/common/fmatrix-2.7.hh +++ b/dune/xt/common/fmatrix-2.7.hh @@ -973,6 +973,17 @@ void rightmultiply(Dune::FieldMatrix<K, L_ROWS, R_COLS>& ret, } } + +template <class K, int rows, int cols> +XT::Common::FieldVector<K, rows> operator*(const Dune::FieldMatrix<K, rows, cols>& mat, + const Dune::FieldVector<K, cols>& vec) +{ + XT::Common::FieldVector<K, rows> ret; + mat.mv(vec, ret); + return ret; +} + + // versions that do not allocate matrices on the stack (for large matrices) template <class K, int L_ROWS, int L_COLS, int R_COLS> std::unique_ptr<Dune::XT::Common::FieldMatrix<K, L_ROWS, R_COLS>> diff --git a/dune/xt/common/lapacke.cc b/dune/xt/common/lapacke.cc index 8cbb03340b95f5421ed1909ed8d6dfae4055ffde..11370f27703ceb2553d54b14a6534af8e81f2ebc 100644 --- a/dune/xt/common/lapacke.cc +++ b/dune/xt/common/lapacke.cc @@ -275,7 +275,7 @@ int dgesvd(int DXTC_LAPACKE_ONLY(matrix_layout), #endif } -double dlamch(char cmach) +double dlamch(char DXTC_LAPACKE_ONLY(cmach)) { #if HAVE_MKL || HAVE_LAPACKE return LAPACKE_dlamch(cmach); diff --git a/dune/xt/common/matrix.hh b/dune/xt/common/matrix.hh index d931557fde93f92bc9ee9f7512edddcc365f5632..1e8727cd10794b25365359ff7a43bf4d0962bc03 100644 --- a/dune/xt/common/matrix.hh +++ b/dune/xt/common/matrix.hh @@ -323,13 +323,15 @@ auto set_matrix_entry(MatrixType& matrix, const size_t ii, const size_t jj, cons } +// The enable_if has to stay, there is an alternative in vector.hh! template <class MatrixType, size_t ROWS = MatrixAbstraction<MatrixType>::static_rows, size_t COLS = MatrixAbstraction<MatrixType>::static_cols, class FieldType = typename MatrixAbstraction<MatrixType>::S, class SparsityPatternType = FullPattern> -typename std::enable_if_t<is_matrix<MatrixType>::value, - typename MatrixAbstraction<MatrixType>::template MatrixTypeTemplate<ROWS, COLS, FieldType>> +typename std::enable_if< + is_matrix<MatrixType>::value, + typename MatrixAbstraction<MatrixType>::template MatrixTypeTemplate<ROWS, COLS, FieldType>>::type create(const size_t rows, const size_t cols, const FieldType& val = 0, @@ -343,8 +345,10 @@ create(const size_t rows, } +// The enable_if has to stay, there is an alternative in vector.hh! template <class TargetMatrixType, class SourceMatrixType> -typename std::enable_if_t<is_matrix<TargetMatrixType>::value && is_matrix<SourceMatrixType>::value, TargetMatrixType> +typename std::enable_if<is_matrix<TargetMatrixType>::value && is_matrix<SourceMatrixType>::value, + TargetMatrixType>::type zeros_like(const SourceMatrixType& source) { return create<TargetMatrixType>( @@ -352,8 +356,9 @@ zeros_like(const SourceMatrixType& source) } +// The enable_if has to stay, there is an alternative in vector.hh! template <class MatrixType> -typename std::enable_if_t<is_matrix<MatrixType>::value, MatrixType> zeros_like(const MatrixType& source) +typename std::enable_if<is_matrix<MatrixType>::value, MatrixType>::type zeros_like(const MatrixType& source) { return zeros_like<MatrixType, MatrixType>(source); } diff --git a/dune/xt/common/parallel/communicator.hh b/dune/xt/common/parallel/communicator.hh index e883412c51685429f0af05eed46e784776c5891e..3f1e2718a1bb58c3d9919d62190c5ed6f380e650 100644 --- a/dune/xt/common/parallel/communicator.hh +++ b/dune/xt/common/parallel/communicator.hh @@ -16,6 +16,9 @@ #if !HAVE_MPI +// defines No_Comm + CollectiveCommunication +# include <dune/common/parallel/communication.hh> + namespace Dune { diff --git a/dune/xt/common/parallel/helper.hh b/dune/xt/common/parallel/helper.hh index 6123550df6bdf0c0680c4747336aa662649c802d..30ab7245cb295a0ac6d66dfef1476dd79f1f3643 100644 --- a/dune/xt/common/parallel/helper.hh +++ b/dune/xt/common/parallel/helper.hh @@ -22,6 +22,9 @@ # include <dune/common/parallel/collectivecommunication.hh> #endif +// pinfo does not source deprecated.hh and therefore errors out on tidy/headercheck +#include <dune/common/deprecated.hh> +#include <dune/common/parallel/communicator.hh> #include <dune/istl/paamg/pinfo.hh> namespace Dune { diff --git a/dune/xt/common/print.hh b/dune/xt/common/print.hh index 740984b0cd7fd6b6e3be377c32082ef37be4fac2..ce349ea101eb52adc5cebf9558b549975e3d3196 100644 --- a/dune/xt/common/print.hh +++ b/dune/xt/common/print.hh @@ -40,6 +40,8 @@ namespace internal { /// \note Should be used to derive from (except for vectors and matrices), when specializing Printer. +/// \todo Drop silenced warnings once all operator<< overloads in dune-xt and dune-gdt which are deprecated due to this +/// DefaultPrinter are removed! /// \sa Printer /// \sa VectorPrinter template <class T, bool use_repr = false> @@ -66,7 +68,10 @@ public: virtual void repr(std::ostream& out) const { if constexpr (is_printable<T>::value) { + // There are some of our operator<< overloads that are deprecated due to the introduction of this Printer. +#include <dune/xt/common/disable_warnings.hh> out << value; +#include <dune/xt/common/reenable_warnings.hh> } else { out << "missing specialization for Printer<T> with T=" << Typename<T>::value(); } @@ -157,17 +162,17 @@ public: const auto rows = M::rows(this->value); const auto cols = M::cols(this->value); if (rows * cols > 0) { - out << "{"; + out << "["; const std::string delim = (std::use_facet<std::numpunct<char>>(std::cout.getloc()).decimal_point() == ',') ? ";" : ","; const std::string newline = "\n"; for (auto&& ii : value_range(rows)) { - out << (ii == 0 ? "{" : " ") << "{" << print(M::get_entry(this->value, ii, 0), this->opts); + out << (ii == 0 ? "[" : " ") << "[" << print(M::get_entry(this->value, ii, 0), this->opts); for (auto&& jj : value_range(decltype(cols)(1), cols)) out << delim << " " << print(M::get_entry(this->value, ii, jj), this->opts); - out << "}" << ((ii == rows - 1) ? "" : ",") << ((ii == rows - 1) ? "" : newline); + out << "]" << ((ii == rows - 1) ? "" : ",") << ((ii == rows - 1) ? "" : newline); } - out << "}"; + out << "]"; } out << ")"; } // ... repr(...) @@ -264,6 +269,41 @@ public: }; // class Printer +template <bool use_repr, typename anything> +class Printer<Configuration, use_repr, anything> : public internal::DefaultPrinter<Configuration, use_repr> +{ +public: + Printer(const Configuration& val, const Configuration& param = {{"oneline", "false"}}) + : internal::DefaultPrinter<Configuration, use_repr>(val, param) + {} + + // let repr() default to operator<<, handled in internal::DefaultPrinter + + void str(std::ostream& out) const override + { + if (!this->opts.get("oneline", false)) + this->repr(out); + else { + const auto key_value_map = this->value.flatten(); + const auto sz = key_value_map.size(); + if (sz == 0) + out << "{}"; + else { + out << "{"; + size_t counter = 0; + for (const auto& key_value_pair : key_value_map) { + out << "\"" << key_value_pair.first << "\": \"" << key_value_pair.second << "\""; + if (counter < sz - 1) + out << ", "; + ++counter; + } + out << "}"; + } + } + } // ... str(...) +}; // class Printer + + /// \sa Printer template <class T, bool use_repr> std::ostream& operator<<(std::ostream& out, const Printer<T, use_repr>& printer) diff --git a/dune/xt/common/timedlogging.cc b/dune/xt/common/timedlogging.cc index e1245eb3daba394bff8db9ef0d34dc63c4afe65b..1bcf5a23417f49eb7ee39084a2cccafcc740e9c7 100644 --- a/dune/xt/common/timedlogging.cc +++ b/dune/xt/common/timedlogging.cc @@ -27,22 +27,23 @@ namespace XT { namespace Common { -DefaultLogger::DefaultLogger(const std::string& prefix, +DefaultLogger::DefaultLogger(const std::string& prfx, bool start_disabled, const std::array<std::string, 3>& colors, bool global_timer) - : timer_() - , prefix_(prefix) + : prefix(prfx) + , copy_count(0) + , timer_() , colors_(colors) , global_timer_(global_timer) , info_(std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, - build_prefix(prefix_.empty() ? "info" : prefix_, colors_[0]), + build_prefix(prfx.empty() ? "info" : prfx, copy_count, colors_[0]), std::cout)) , debug_(std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, - build_prefix(prefix_.empty() ? "debug" : prefix_, colors_[1]), + build_prefix(prfx.empty() ? "debug" : prfx, copy_count, colors_[1]), std::cout)) , warn_(std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, - build_prefix(prefix_.empty() ? "warn" : prefix_, colors_[2]), + build_prefix(prfx.empty() ? "warn" : prfx, copy_count, colors_[2]), std::cerr)) , info_enabled(!start_disabled) , debug_enabled(!start_disabled) @@ -50,19 +51,23 @@ DefaultLogger::DefaultLogger(const std::string& prefix, {} DefaultLogger::DefaultLogger(const DefaultLogger& other) - : timer_() - , prefix_(other.prefix_) + : prefix(other.prefix) + , copy_count(other.copy_count + 1) + , timer_() , colors_(other.colors_) , global_timer_(other.global_timer_) - , info_(std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, - build_prefix(prefix_.empty() ? "info" : prefix_, colors_[0]), - std::cout)) - , debug_(std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, - build_prefix(prefix_.empty() ? "debug" : prefix_, colors_[1]), - std::cout)) - , warn_(std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, - build_prefix(prefix_.empty() ? "warn" : prefix_, colors_[2]), - std::cerr)) + , info_( + std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, + build_prefix(prefix.empty() ? "info" : prefix, copy_count, colors_[0]), + std::cout)) + , debug_(std::make_shared<TimedPrefixedLogStream>( + global_timer_ ? SecondsSinceStartup() : timer_, + build_prefix(prefix.empty() ? "debug" : prefix, copy_count, colors_[1]), + std::cout)) + , warn_( + std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, + build_prefix(prefix.empty() ? "warn" : prefix, copy_count, colors_[2]), + std::cerr)) , info_enabled(other.info_enabled) , debug_enabled(other.debug_enabled) , warn_enabled(other.warn_enabled) @@ -71,19 +76,23 @@ DefaultLogger::DefaultLogger(const DefaultLogger& other) DefaultLogger& DefaultLogger::operator=(const DefaultLogger& other) { if (&other != this) { + prefix = other.prefix; + copy_count = other.copy_count; timer_ = other.timer_; - prefix_ = other.prefix_; colors_ = other.colors_; global_timer_ = other.global_timer_; - info_ = std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, - build_prefix(prefix_.empty() ? "info" : prefix_, colors_[0]), - std::cout); - debug_ = std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, - build_prefix(prefix_.empty() ? "debug" : prefix_, colors_[1]), - std::cout); - warn_ = std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, - build_prefix(prefix_.empty() ? "warn" : prefix_, colors_[2]), - std::cerr); + info_ = + std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, + build_prefix(prefix.empty() ? "info" : prefix, copy_count, colors_[0]), + std::cout); + debug_ = std::make_shared<TimedPrefixedLogStream>( + global_timer_ ? SecondsSinceStartup() : timer_, + build_prefix(prefix.empty() ? "debug" : prefix, copy_count, colors_[1]), + std::cout); + warn_ = + std::make_shared<TimedPrefixedLogStream>(global_timer_ ? SecondsSinceStartup() : timer_, + build_prefix(prefix.empty() ? "warn" : prefix, copy_count, colors_[2]), + std::cerr); info_enabled = other.info_enabled; debug_enabled = other.debug_enabled; warn_enabled = other.warn_enabled; @@ -91,19 +100,20 @@ DefaultLogger& DefaultLogger::operator=(const DefaultLogger& other) return *this; } // ... operator=(...) -void DefaultLogger::enable(const std::string& prefix) +void DefaultLogger::enable(const std::string& prfx) { info_enabled = true; debug_enabled = true; warn_enabled = true; - if (!prefix.empty()) { - prefix_ = prefix; + if (!prfx.empty()) { + prefix = prfx; + copy_count = 0; info_ = std::make_shared<TimedPrefixedLogStream>( - global_timer_ ? SecondsSinceStartup() : timer_, build_prefix(prefix_, colors_[0]), std::cout); + global_timer_ ? SecondsSinceStartup() : timer_, build_prefix(prfx, copy_count, colors_[0]), std::cout); debug_ = std::make_shared<TimedPrefixedLogStream>( - global_timer_ ? SecondsSinceStartup() : timer_, build_prefix(prefix_, colors_[1]), std::cout); + global_timer_ ? SecondsSinceStartup() : timer_, build_prefix(prfx, copy_count, colors_[1]), std::cout); warn_ = std::make_shared<TimedPrefixedLogStream>( - global_timer_ ? SecondsSinceStartup() : timer_, build_prefix(prefix_, colors_[2]), std::cerr); + global_timer_ ? SecondsSinceStartup() : timer_, build_prefix(prfx, copy_count, colors_[2]), std::cerr); } } // ... enable(...) @@ -206,9 +216,9 @@ void TimedLogging::create(const ssize_t max_info_level, const ssize_t max_debug_level, const bool enable_warnings, const bool enable_colors, - const std::string info_color, - const std::string debug_color, - const std::string warning_color) + const std::string& info_color, + const std::string& debug_color, + const std::string& warning_color) { DUNE_UNUSED std::lock_guard<std::mutex> guard(mutex_); DUNE_THROW_IF(created_, Exceptions::logger_error, "Do not call create() more than once!"); @@ -224,7 +234,7 @@ void TimedLogging::create(const ssize_t max_info_level, update_colors(); } // ... create(...) -TimedLogManager TimedLogging::get(const std::string id) +TimedLogManager TimedLogging::get(const std::string& id) { DUNE_UNUSED std::lock_guard<std::mutex> guard(mutex_); ++current_level_; diff --git a/dune/xt/common/timedlogging.hh b/dune/xt/common/timedlogging.hh index 7804b9efa51cd818b2bf1b9955ce99b222e82ab2..54ebcc75945e0143407e23123073549869d63cdd 100644 --- a/dune/xt/common/timedlogging.hh +++ b/dune/xt/common/timedlogging.hh @@ -56,17 +56,26 @@ DUNE_EXPORT inline const Timer& SecondsSinceStartup() */ class DefaultLogger { - static std::string build_prefix(const std::string& prefix, const std::string& clr) + static std::string build_prefix(const std::string& prfx, const size_t cnt, const std::string& clr) { const std::string actual_color = terminal_supports_color() ? color(clr) : ""; + std::string copy_count_str = ""; + if (cnt > 0) + copy_count_str += "[" + to_string(cnt) + "]"; + std::string ret; if (actual_color.empty()) - return prefix + ": "; + ret = prfx + copy_count_str + ": "; else - return actual_color + StreamModifiers::bold + prefix + ": " + StreamModifiers::normal; - } + ret = actual_color + StreamModifiers::bold + prfx + StreamModifiers::normal + copy_count_str + + StreamModifiers::bold + ": " + StreamModifiers::normal; + return ret; + } // ... build_prefix(...) public: - DefaultLogger(const std::string& prefix = "", + std::string prefix; + size_t copy_count; + + DefaultLogger(const std::string& prfx = "", bool start_disabled = false, const std::array<std::string, 3>& colors = {"blue", "darkgray", "red"}, bool global_timer = true); @@ -77,7 +86,6 @@ public: private: Timer timer_; - std::string prefix_; std::array<std::string, 3> colors_; bool global_timer_; std::shared_ptr<std::ostream> info_; @@ -89,7 +97,14 @@ public: bool debug_enabled; bool warn_enabled; - void enable(const std::string& prefix = ""); + void enable(const std::string& prfx = ""); + + void enable_like(const DefaultLogger& other) + { + this->info_enabled = this->info_enabled || other.info_enabled; + this->debug_enabled = this->debug_enabled || other.debug_enabled; + this->warn_enabled = this->warn_enabled || other.warn_enabled; + } void disable(); @@ -102,13 +117,21 @@ public: #ifdef LOG_ -# error Macro LOG_ already defined, open an issue at https://github.com/dune-community/dune-xt/issues/new ! +# error Macro LOG_ already defined, open an issue at https://zivgitlab.uni-muenster.de/ag-ohlberger/dune-community/dune-xt/-/issues ! #else # define LOG_(type) \ if (this->logger.type##_enabled) \ this->logger.type() #endif +#ifdef LOG__ +# error Macro LOG_ already defined, open an issue at https://zivgitlab.uni-muenster.de/ag-ohlberger/dune-community/dune-xt/-/issues ! +#else +# define LOG__(base, type) \ + if (base ::logger.type##_enabled) \ + base ::logger.type() +#endif + template <typename T = void> class WithLogger @@ -118,47 +141,58 @@ class WithLogger public: mutable DefaultLogger logger; -protected: - const std::string logging_id; + [[deprecated("Use this.logger.prefix instead (12.08.2020)!")]] static const std::string logging_id; -public: - WithLogger(const std::string& prefix, const std::string& id, const bool start_enabled = false) - : logger(prefix, start_enabled) - , logging_id(id) + [[deprecated("Use WithLogger(id, start_enabled) instead (12.08.2020)!")]] WithLogger(const std::string& /*prefix*/, + const std::string& id, + const bool start_enabled = false) + : logger(id, start_enabled) { - LOG_(debug) << logging_id << "(this=" << this << ")" << std::endl; + LOG_(debug) << "WithLogger(this=" << this << ")" << std::endl; + } + + WithLogger(const std::string& id, const bool start_enabled = false) + : logger(id, start_enabled) + { + LOG_(debug) << "WithLogger(this=" << this << ")" << std::endl; } WithLogger(const ThisType& other) : logger(other.logger) - , logging_id(other.logging_id) { - LOG_(debug) << logging_id << "(this=" << this << ", other=" << &other << ")" << std::endl; + LOG_(debug) << "WithLogger(this=" << this << ", other=" << &other << ")" << std::endl; } WithLogger(ThisType&& source) : logger(std::move(source.logger)) - , logging_id(std::move(source.logging_id)) { - LOG_(debug) << logging_id << "(this=" << this << ", source=" << &source << ")" << std::endl; + LOG_(debug) << "WithLogger(this=" << this << ", source=" << &source << ")" << std::endl; } ~WithLogger() { - LOG_(debug) << "~" << logging_id << "(this=" << this << ")" << std::endl; + LOG_(debug) << "~WithLogger(this=" << this << ")" << std::endl; } ThisType& operator=(const ThisType& other) { - LOG_(debug) << logging_id << "operator=(this=" << this << ", other=" << &other << ")" << std::endl; + LOG_(debug) << "WithLogger.operator=(this=" << this << ", other=" << &other << ")" << std::endl; } ThisType& operator=(ThisType&& source) { - LOG_(debug) << logging_id << "operator=(this=" << this << ", source=" << &source << ")" << std::endl; + LOG_(debug) << "WithLogger.operator=(this=" << this << ", source=" << &source << ")" << std::endl; + } + + [[deprecated("Use this.logger.enable_like(other.logger) instead (12.08.2020)!")]] void + enable_logging_like(const ThisType& other) + { + this->logger.enable_like(other.logger); } }; // class WithLogger +template <class T> +const std::string WithLogger<T>::logging_id = "Use this.logger.prefix instead"; /** * \brief A logging manager that provides info, debug and warning streams @@ -228,7 +262,7 @@ public: /** * \brief sets the state * - * This methos is mainly intended to be used on the global TimedLogger() instance. Before calling this method + * This method is mainly intended to be used on the global TimedLogger() instance. Before calling this method * the state is set according to the defaults default_max_info_level, default_max_debug_level and * default_enable_warnings. * \note Calling this method more than once will throw an Exceptions::you_are_using_this_wrong, following the idea of @@ -238,11 +272,11 @@ public: const ssize_t max_debug_level = default_max_debug_level, const bool enable_warnings = default_enable_warnings, const bool enable_colors = default_enable_colors, - const std::string info_color = default_info_color(), - const std::string debug_color = default_debug_color(), - const std::string warning_color = default_warning_color()); + const std::string& info_color = default_info_color(), + const std::string& debug_color = default_debug_color(), + const std::string& warning_color = default_warning_color()); - TimedLogManager get(const std::string id); + TimedLogManager get(const std::string& id); private: void update_colors(); @@ -388,89 +422,81 @@ int main() { * The same holds for the move ctor as well as move and assignment operators. */ template <typename T = void> -class EnableDebugLoggingForCtors +class NoOpEnableDebugLoggingForCtors { - typedef EnableDebugLoggingForCtors<T> ThisType; + using ThisType = NoOpEnableDebugLoggingForCtors<T>; public: - EnableDebugLoggingForCtors(const std::string& -#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG - prefix -#endif - , - const std::string& -#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG - class_id -#endif - ) -#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG + NoOpEnableDebugLoggingForCtors(const std::string&, const std::string&) {} + + NoOpEnableDebugLoggingForCtors(const ThisType& other) = default; + + NoOpEnableDebugLoggingForCtors(ThisType&& source) = default; + + ~NoOpEnableDebugLoggingForCtors() = default; + + ThisType& operator=(const ThisType& other) = default; + + ThisType& operator=(ThisType&& source) = default; + +}; // class NoOpEnableDebugLoggingForCtors + +template <typename T = void> +class ActiveEnableDebugLoggingForCtors +{ + using ThisType = ActiveEnableDebugLoggingForCtors<T>; + +public: + ActiveEnableDebugLoggingForCtors(const std::string& prefix, const std::string& class_id) : logger_(TimedLogger().get(prefix)) , class_id_(class_id) { logger_.debug() << class_id_ << "(this=" << this << ")" << std::endl; } -#else - {} -#endif - EnableDebugLoggingForCtors(const ThisType& other) -#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG + ActiveEnableDebugLoggingForCtors(const ThisType& other) : logger_(other.logger_) , class_id_(other.class_id_) { logger_.debug() << class_id_ << "(this=" << this << ", other=" << &other << ")" << std::endl; } -#else - = default; -#endif - EnableDebugLoggingForCtors(ThisType&& source) -#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG + ActiveEnableDebugLoggingForCtors(ThisType&& source) : logger_(std::move(source.logger_)) , class_id_(std::move(source.class_id_)) { logger_.debug() << class_id_ << "(this=" << this << ", source=" << &source << ")" << std::endl; } -#else - = default; -#endif - ~EnableDebugLoggingForCtors() -#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG + ~ActiveEnableDebugLoggingForCtors() { logger_.debug() << "~" << class_id_ << "(this=" << this << ")" << std::endl; } -#else - = default; -#endif ThisType& operator=(const ThisType& other) -#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG { logger_.debug() << class_id_ << "operator=(this=" << this << ", other=" << &other << ")" << std::endl; } -#else - = default; -#endif ThisType& operator=(ThisType&& source) -#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG { logger_.debug() << class_id_ << "operator=(this=" << this << ", source=" << &source << ")" << std::endl; } -#else - = default; -#endif -#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG protected: TimedLogManager logger_; private: const std::string class_id_; -#endif -}; // class EnableDebugLoggingForCtors +}; // class ActiveEnableDebugLoggingForCtors +#if DUNE_XT_COMMON_TIMEDLOGGING_ENABLE_DEBUG +template <class T> +using EnableDebugLoggingForCtors = ActiveEnableDebugLoggingForCtors<T>; +#else +template <class T> +using EnableDebugLoggingForCtors = NoOpEnableDebugLoggingForCtors<T>; +#endif } // namespace Common } // namespace XT diff --git a/dune/xt/functions/ESV2007.hh b/dune/xt/functions/ESV2007.hh index 7e78047b7964068bd335d79707110c2ed10a7bac..a03839fb3db79acf26af31bebb96f5ff1c302afd 100644 --- a/dune/xt/functions/ESV2007.hh +++ b/dune/xt/functions/ESV2007.hh @@ -26,6 +26,7 @@ #include <dune/xt/common/configuration.hh> #include <dune/xt/la/eigen-solver.hh> +#include <dune/xt/functions/grid-function.hh> #include <dune/xt/functions/interfaces/grid-function.hh> #include <dune/xt/functions/interfaces/function.hh> @@ -74,14 +75,26 @@ public: } // ... defaults(...) Testcase1Force(const size_t ord = defaults().template get<int>("integration_order"), - const std::string nm = static_id()) + const std::string nm = "ESV2007Testcase1Force") : order_(static_cast<int>(ord)) , name_(nm) {} - Testcase1Force(const ThisType& /*other*/) = default; + Testcase1Force(const ThisType&) = default; - ThisType& operator=(const ThisType& /*other*/) = delete; + Testcase1Force(ThisType&&) = default; + +private: + ThisType* copy_as_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } std::string name() const override final { @@ -160,14 +173,26 @@ public: } // ... defaults(...) Testcase1ExactSolution(const size_t ord = defaults().template get<int>("integration_order"), - const std::string nm = static_id()) + const std::string nm = "ESV2007Testcase1ExactSolution") : order_(static_cast<int>(ord)) , name_(nm) {} - Testcase1ExactSolution(const ThisType& /*other*/) = default; + Testcase1ExactSolution(const ThisType&) = default; - ThisType& operator=(const ThisType& /*other*/) = delete; + Testcase1ExactSolution(ThisType&&) = default; + +private: + ThisType* copy_as_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } std::string name() const override final { @@ -223,7 +248,7 @@ private: class LocalCutoffFunction : public ElementFunctionInterface<E, 1, 1, R> { using BaseType = ElementFunctionInterface<E, 1, 1, R>; - + using DiffusionType = GridFunctionInterface<E, d, d, R>; public: using typename BaseType::DerivativeRangeReturnType; @@ -234,10 +259,11 @@ private: using typename BaseType::RangeReturnType; LocalCutoffFunction(const DiffusionType& diffusion, const RangeFieldType poincare_constant) - : BaseType() - , value_(0) - , local_diffusion_(diffusion.local_function()) + : BaseType(diffusion.parameter_type()) + , diffusion_(diffusion.copy_as_grid_function()) + , local_diffusion_(diffusion_->local_function()) , poincare_constant_(poincare_constant) + , value_(0) {} protected: @@ -313,9 +339,10 @@ private: } }; - RangeFieldType value_; + const std::unique_ptr<DiffusionType> diffusion_; std::unique_ptr<typename DiffusionType::LocalFunctionType> local_diffusion_; const RangeFieldType poincare_constant_; + RangeFieldType value_; }; // class LocalCutoffFunction public: @@ -328,18 +355,36 @@ public: return BaseType::static_id() + ".ESV2007.cutoff"; } - CutoffFunction(const DiffusionType& diffusion, + CutoffFunction(GridFunction<E, d, d, R> diffusion, const RangeFieldType poincare_constant = 1.0 / (M_PI * M_PI), - const std::string nm = static_id()) - : diffusion_(diffusion) + const std::string nm = "ESV2007CutoffFunction") + : BaseType(diffusion.parameter_type()) + , diffusion_(diffusion.copy_as_grid_function()) , poincare_constant_(poincare_constant) , name_(nm) {} - CutoffFunction(const ThisType& other) = default; + CutoffFunction(const ThisType& other) + : BaseType(other) + , diffusion_(other.diffusion_->copy_as_grid_function()) + , poincare_constant_(other.poincare_constant_) + , name_(other.name_) + {} + + CutoffFunction(ThisType&&) = default; - ThisType& operator=(const ThisType& other) = delete; +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } std::string name() const override final { return name_; @@ -347,11 +392,11 @@ public: std::unique_ptr<LocalFunctionType> local_function() const override final { - return std::make_unique<LocalCutoffFunction>(diffusion_, poincare_constant_); + return std::make_unique<LocalCutoffFunction>(*diffusion_, poincare_constant_); } private: - const DiffusionType& diffusion_; + std::unique_ptr<GridFunctionInterface<E, d, d, R>> diffusion_; const RangeFieldType poincare_constant_; std::string name_; }; // class Cutoff diff --git a/dune/xt/functions/base/combined-element-functions.hh b/dune/xt/functions/base/combined-element-functions.hh index 96639515083029ff0acf8a6c4e0899f0c8cd1202..5e99c103a87eb768da6a9673127d3678501969ef 100644 --- a/dune/xt/functions/base/combined-element-functions.hh +++ b/dune/xt/functions/base/combined-element-functions.hh @@ -12,371 +12,36 @@ #ifndef DUNE_XT_FUNCTIONS_BASE_COMBINED_ELEMENT_FUNCTIONS_HH #define DUNE_XT_FUNCTIONS_BASE_COMBINED_ELEMENT_FUNCTIONS_HH -#include <dune/xt/common/memory.hh> +#include <dune/xt/common/type_traits.hh> +#include <dune/xt/functions/exceptions.hh> #include <dune/xt/functions/interfaces/element-functions.hh> #include <dune/xt/functions/type_traits.hh> +#include "combined.hh" + namespace Dune { namespace XT { namespace Functions { -namespace internal { -/** - * \brief Helper class defining types of combined functions, if available. - * - * \note Most likely you do not want to use this class directly, but CombinedConstElementFunction or - * CombinedElementFunction. - */ -template <class LeftType, class RightType, CombinationType comb> -class CombinedElementFunctionHelper +template <class LeftType, class RightType, typename comb> +class CombinedConstElementFunction + : public ElementFunctionInterface<typename LeftType::E, + internal::CombinedHelper<LeftType, RightType, comb>::r, + internal::CombinedHelper<LeftType, RightType, comb>::rC, + typename internal::CombinedHelper<LeftType, RightType, comb>::R> { static_assert(is_element_function<LeftType>::value, ""); static_assert(is_element_function<RightType>::value, ""); + static_assert(std::is_same<typename LeftType::E, typename RightType::E>::value, ""); -public: - using E = typename LeftType::E; - using R = typename LeftType::R; - -private: - using D = typename LeftType::D; - static constexpr size_t d = LeftType::d; - -private: - static_assert(std::is_same<typename RightType::E, E>::value, ""); - static_assert(std::is_same<typename RightType::D, D>::value, ""); - static_assert(RightType::d == d, ""); - static_assert(std::is_same<typename RightType::R, R>::value, ""); - - template <class L, class R> - class dim_switch - { - //! last tpl arg cannot be dropped due to gcc bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282 - template <CombinationType cc = comb, - size_t rL = L::r, - size_t rCL = L::rC, - size_t rR = R::r, - size_t rCR = R::rC, - bool anything = true> - class Dimension - { - public: - static constexpr bool available = false; - }; - - template <size_t r_, size_t rC_, bool anything> - class Dimension<CombinationType::difference, r_, rC_, r_, rC_, anything> - { - public: - static constexpr bool available = true; - static constexpr size_t r = r_; - static constexpr size_t rC = rC_; - }; - - template <size_t r_, size_t rC_, bool anything> - class Dimension<CombinationType::sum, r_, rC_, r_, rC_, anything> - { - public: - static constexpr bool available = true; - static constexpr size_t r = r_; - static constexpr size_t rC = rC_; - }; - - template <bool anything> - class Dimension<CombinationType::product, 1, 1, 1, 1, anything> - { - public: - static constexpr bool available = true; - static constexpr size_t r = 1; - static constexpr size_t rC = 1; - }; - - template <size_t r_, size_t rC_, bool anything> - class Dimension<CombinationType::product, r_, rC_, 1, 1, anything> - { - public: - static constexpr bool available = true; - static constexpr size_t r = r_; - static constexpr size_t rC = rC_; - }; - - template <size_t r_, size_t rC_, bool anything> - class Dimension<CombinationType::product, 1, 1, r_, rC_, anything> - { - public: - static constexpr bool available = true; - static constexpr size_t r = r_; - static constexpr size_t rC = rC_; - }; - - template <size_t rL, size_t c, size_t rR, bool anything> - class Dimension<CombinationType::product, rL, c, c, rR, anything> - { - public: - static constexpr bool available = true; - static constexpr size_t r = rL; - static constexpr size_t rC = rR; - }; - - public: - static constexpr bool available = Dimension<>::available; - static constexpr size_t r = Dimension<>::r; - static constexpr size_t rC = Dimension<>::rC; - }; // class dim_switch - -public: - static constexpr size_t r = dim_switch<LeftType, RightType>::r; - static constexpr size_t rC = dim_switch<LeftType, RightType>::rC; - static constexpr bool available = dim_switch<LeftType, RightType>::available; - -private: - using DomainType = typename ElementFunctionInterface<E, r, rC, R>::DomainType; - using RangeReturnType = typename RangeTypeSelector<R, r, rC>::return_type; - using DerivativeRangeReturnType = typename DerivativeRangeTypeSelector<d, R, r, rC>::return_type; - - template <CombinationType cc = comb, - size_t rL = LeftType::r, - size_t rCL = LeftType::rC, - size_t rR = RightType::r, - size_t rCR = RightType::rC, - bool anything = true> - class CombinationTypeSwitch - { - static_assert(!anything, "Nothing available for these CombinationType!"); - }; - - template <size_t r_, size_t rC_, bool anything> - class CombinationTypeSwitch<CombinationType::difference, r_, rC_, r_, rC_, anything> - { - public: - static int order(const int left_order, const int right_order) - { - return std::max(left_order, right_order); - } - - static RangeReturnType evaluate(const LeftType& left_local, - const RightType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.evaluate(point_in_reference_element, param) - - right_local.evaluate(point_in_reference_element, param); - } - - static DerivativeRangeReturnType jacobian(const LeftType& left_local, - const RightType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.jacobian(point_in_reference_element, param) - - right_local.jacobian(point_in_reference_element, param); - } - }; // class CombinationTypeSwitch< ..., difference > - - template <size_t r_, size_t rC_, bool anything> - class CombinationTypeSwitch<CombinationType::sum, r_, rC_, r_, rC_, anything> - { - public: - static int order(const int left_order, const int right_order) - { - return std::max(left_order, right_order); - } - - static RangeReturnType evaluate(const LeftType& left_local, - const RightType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.evaluate(point_in_reference_element, param) - + right_local.evaluate(point_in_reference_element, param); - } - - static DerivativeRangeReturnType jacobian(const LeftType& left_local, - const RightType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.jacobian(point_in_reference_element, param) - + right_local.jacobian(point_in_reference_element, param); - } - }; // class CombinationTypeSwitch< ..., sum > - - template <bool anything> - class CombinationTypeSwitch<CombinationType::product, 1, 1, 1, 1, anything> - { - public: - static int order(const int left_order, const int right_order) - { - return left_order + right_order; - } - - static RangeReturnType evaluate(const LeftType& left_local, - const RightType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.evaluate(point_in_reference_element, param) - * right_local.evaluate(point_in_reference_element, param); - } - - static DerivativeRangeReturnType jacobian(const LeftType& /*left_local*/, - const RightType& /*right_local*/, - const DomainType& /*point_in_reference_element*/, - const Common::Parameter& /*param*/) - { - DUNE_THROW(NotImplemented, "If you need this, implement it!"); - return DerivativeRangeReturnType(); - } - }; // class CombinationTypeSwitch< ..., product > - - template <size_t r_, size_t rC_, bool anything> - class CombinationTypeSwitch<CombinationType::product, r_, rC_, 1, 1, anything> - { - public: - static int order(const int left_order, const int right_order) - { - return left_order + right_order; - } - - static RangeReturnType evaluate(const LeftType& left_local, - const RightType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - auto result = left_local.evaluate(point_in_reference_element, param); - result *= right_local.evaluate(point_in_reference_element, param); - return result; - } - - static DerivativeRangeReturnType jacobian(const LeftType& /*left_local*/, - const RightType& /*right_local*/, - const DomainType& /*point_in_reference_element*/, - const Common::Parameter& /*param*/) - { - DUNE_THROW(NotImplemented, "If you need this, implement it!"); - return DerivativeRangeReturnType(); - } - }; // class CombinationTypeSwitch< ..., product > - - template <size_t r_, size_t rC_, bool anything> - class CombinationTypeSwitch<CombinationType::product, 1, 1, r_, rC_, anything> - { - public: - static int order(const int left_order, const int right_order) - { - return left_order + right_order; - } - - static RangeReturnType evaluate(const LeftType& left_local, - const RightType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - auto result = right_local.evaluate(point_in_reference_element, param); - result *= left_local.evaluate(point_in_reference_element, param); - return result; - } - - static DerivativeRangeReturnType jacobian(const LeftType& /*left_local*/, - const RightType& /*right_local*/, - const DomainType& /*point_in_reference_element*/, - const Common::Parameter& /*param*/) - { - DUNE_THROW(NotImplemented, "If you need this, implement it!"); - return DerivativeRangeReturnType(); - } - }; // class CombinationTypeSwitch< ..., product > - - template <size_t rL, size_t c_, size_t rR_, bool anything> - class CombinationTypeSwitch<CombinationType::product, rL, c_, c_, rR_, anything> - { - public: - static int order(const int left_order, const int right_order) - { - return left_order + right_order; - } - - static RangeReturnType evaluate(const LeftType& left_local, - const RightType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.evaluate(point_in_reference_element, param) - * right_local.evaluate(point_in_reference_element, param); - } - - static DerivativeRangeReturnType jacobian(const LeftType& /*left*/, - const RightType& /*right*/, - const DomainType& /*xx*/, - const Common::Parameter& /*param*/) - { - DUNE_THROW(NotImplemented, "If you need this, implement it!"); - return DerivativeRangeReturnType(); - } - }; // class CombinationTypeSwitch< ..., product > - -public: - static int order(const LeftType& left, const RightType& right, const Common::Parameter& param) - { - return CombinationTypeSwitch<>::order(left.order(param), right.order(param)); - } - - static RangeReturnType - evaluate(const LeftType& left, const RightType& right, const DomainType& xx, const Common::Parameter& param) - { - return CombinationTypeSwitch<>::evaluate(left, right, xx, param); - } - - static DerivativeRangeReturnType - jacobian(const LeftType& left, const RightType& right, const DomainType& xx, const Common::Parameter& param) - { - return CombinationTypeSwitch<>::jacobian(left, right, xx, param); - } -}; // class CombinedElementFunctionHelper - - -template <class LeftType, class RightType> -struct DualStorageProvider -{ - XT::Common::StorageProvider<LeftType> left; - XT::Common::StorageProvider<RightType> right; - - DualStorageProvider(LeftType& lft, RightType& rght) - : left(lft) - , right(rght) - {} - - DualStorageProvider(std::shared_ptr<LeftType> lft, std::shared_ptr<RightType> rght) - : left(lft) - , right(rght) - {} - - DualStorageProvider(std::unique_ptr<LeftType>&& lft, std::unique_ptr<RightType>&& rght) - : left(std::move(lft)) - , right(std::move(rght)) - {} -}; // struct DualStorageProvider - - -} // namespace internal - - -template <class LeftType, class RightType, CombinationType combination> -class CombinedConstElementFunction - : public ElementFunctionInterface< - typename internal::CombinedElementFunctionHelper<LeftType, RightType, combination>::E, - internal::CombinedElementFunctionHelper<LeftType, RightType, combination>::r, - internal::CombinedElementFunctionHelper<LeftType, RightType, combination>::rC, - typename internal::CombinedElementFunctionHelper<LeftType, RightType, combination>::R> -{ - using BaseType = - ElementFunctionInterface<typename internal::CombinedElementFunctionHelper<LeftType, RightType, combination>::E, - internal::CombinedElementFunctionHelper<LeftType, RightType, combination>::r, - internal::CombinedElementFunctionHelper<LeftType, RightType, combination>::rC, - typename internal::CombinedElementFunctionHelper<LeftType, RightType, combination>::R>; - - using Select = internal::CombinedElementFunctionHelper<LeftType, RightType, combination>; + using ThisType = CombinedConstElementFunction; + using BaseType = ElementFunctionInterface<typename LeftType::E, + internal::CombinedHelper<LeftType, RightType, comb>::r, + internal::CombinedHelper<LeftType, RightType, comb>::rC, + typename internal::CombinedHelper<LeftType, RightType, comb>::R>; + using Helper = internal::CombinedHelper<LeftType, RightType, comb>; public: using typename BaseType::DerivativeRangeReturnType; @@ -387,7 +52,7 @@ public: using typename BaseType::RangeType; CombinedConstElementFunction(const LeftType& left, const RightType& right) - : BaseType() + : BaseType(left.parameter_type() + right.parameter_type()) , left_(left) , right_(right) , bind_is_temporarily_ok_(false) @@ -395,8 +60,17 @@ public: bind_if_arguments_were_bound(); } + CombinedConstElementFunction(const LeftType& left, RightType&& right) + : BaseType(left.parameter_type() + right.parameter_type()) + , left_(left) + , right_(std::move(right)) + , bind_is_temporarily_ok_(false) + { + bind_if_arguments_were_bound(); + } + CombinedConstElementFunction(std::shared_ptr<const LeftType> left, std::shared_ptr<const RightType> right) - : BaseType() + : BaseType(left->parameter_type() + right->parameter_type()) , left_(left) , right_(right) , bind_is_temporarily_ok_(false) @@ -405,7 +79,7 @@ public: } CombinedConstElementFunction(std::unique_ptr<const LeftType>&& left, std::unique_ptr<const RightType>&& right) - : BaseType() + : BaseType(left->parameter_type() + right->parameter_type()) , left_(std::move(left)) , right_(std::move(right)) , bind_is_temporarily_ok_(false) @@ -413,6 +87,10 @@ public: bind_if_arguments_were_bound(); } + CombinedConstElementFunction(const ThisType&) = default; + + CombinedConstElementFunction(ThisType&&) = default; + protected: void post_bind(const ElementType& /*element*/) override { @@ -422,19 +100,19 @@ protected: public: int order(const XT::Common::Parameter& param = {}) const override final { - return Select::order(left_.access(), right_.access(), param); + return Helper::order(left_.access(), right_.access(), param); } RangeReturnType evaluate(const DomainType& point_in_reference_element, const Common::Parameter& param = {}) const override final { - return Select::evaluate(left_.access(), right_.access(), point_in_reference_element, param); + return Helper::evaluate(left_.access(), right_.access(), point_in_reference_element, param); } DerivativeRangeReturnType jacobian(const DomainType& point_in_reference_element, const Common::Parameter& param = {}) const override final { - return Select::jacobian(left_.access(), right_.access(), point_in_reference_element, param); + return Helper::jacobian(left_.access(), right_.access(), point_in_reference_element, param); } private: @@ -468,32 +146,42 @@ private: }; // class CombinedConstElementFunction -template <class LeftType, class RightType, CombinationType combination> +template <class LeftType, class RightType, class combination> class CombinedElementFunction - : internal::DualStorageProvider<LeftType, RightType> + : internal::CombinedStorageProvider<LeftType, RightType> , public CombinedConstElementFunction<LeftType, RightType, combination> { - using Storage = internal::DualStorageProvider<LeftType, RightType>; + using ThisType = CombinedElementFunction; + using Storage = internal::CombinedStorageProvider<LeftType, RightType>; using BaseType = CombinedConstElementFunction<LeftType, RightType, combination>; public: using typename BaseType::ElementType; - CombinedElementFunction(LeftType& left, RightType& right) - : Storage(left, right) + CombinedElementFunction(LeftType& lft, RightType& rght) + : Storage(lft, rght) , BaseType(Storage::left.access(), Storage::right.access()) {} - CombinedElementFunction(std::shared_ptr<LeftType> left, std::shared_ptr<RightType> right) - : Storage(left, right) + CombinedElementFunction(LeftType& lft, RightType&& rght) + : Storage(lft, std::move(rght)) , BaseType(Storage::left.access(), Storage::right.access()) {} - CombinedElementFunction(std::unique_ptr<LeftType>&& left, std::unique_ptr<RightType>&& right) - : Storage(std::move(left), std::move(right)) + CombinedElementFunction(std::shared_ptr<LeftType> lft, std::shared_ptr<RightType> rght) + : Storage(lft, rght) , BaseType(Storage::left.access(), Storage::right.access()) {} + CombinedElementFunction(std::unique_ptr<LeftType>&& lft, std::unique_ptr<RightType>&& rght) + : Storage(std::move(lft), std::move(rght)) + , BaseType(Storage::left.access(), Storage::right.access()) + {} + + CombinedElementFunction(const ThisType&) = default; + + CombinedElementFunction(ThisType&&) = default; + protected: void post_bind(const ElementType& element) override final { @@ -504,7 +192,7 @@ protected: /** - * \brief Element function representing the difference between two element functions. + * \brief Element function representing the difference between two element functions (const variant). * * \sa CombinedConstElementFunction */ @@ -542,7 +230,7 @@ public: /** - * \brief Element function representing the sum of two element functions. + * \brief Element function representing the sum of two element functions (const variant). * * \sa CombinedConstElementFunction */ @@ -578,6 +266,25 @@ public: }; +/** + * \brief Element function representing the product of two element functions (const variant). + * + * \sa CombinedElementFunction + */ +template <class LeftFactorType, class RightFactorType> +class ConstProductElementFunction + : public CombinedConstElementFunction<LeftFactorType, RightFactorType, CombinationType::product> +{ + using BaseType = CombinedConstElementFunction<LeftFactorType, RightFactorType, CombinationType::product>; + +public: + template <class... Args> + explicit ConstProductElementFunction(Args&&... args) + : BaseType(std::forward<Args>(args)...) + {} +}; + + /** * \brief Element function representing the product of two element functions. * @@ -596,6 +303,44 @@ public: }; +/** + * \brief Element function representing the fraction of two element functions (const variant). + * + * \sa CombinedElementFunction + */ +template <class LeftFactorType, class RightFactorType> +class ConstFractionElementFunction + : public CombinedConstElementFunction<LeftFactorType, RightFactorType, CombinationType::fraction> +{ + using BaseType = CombinedConstElementFunction<LeftFactorType, RightFactorType, CombinationType::fraction>; + +public: + template <class... Args> + explicit ConstFractionElementFunction(Args&&... args) + : BaseType(std::forward<Args>(args)...) + {} +}; + + +/** + * \brief Element function representing the fraction of two element functions. + * + * \sa CombinedElementFunction + */ +template <class LeftFactorType, class RightFactorType> +class FractionElementFunction + : public CombinedElementFunction<LeftFactorType, RightFactorType, CombinationType::fraction> +{ + using BaseType = CombinedElementFunction<LeftFactorType, RightFactorType, CombinationType::fraction>; + +public: + template <class... Args> + explicit FractionElementFunction(Args&&... args) + : BaseType(std::forward<Args>(args)...) + {} +}; + + } // namespace Functions } // namespace XT } // namespace Dune diff --git a/dune/xt/functions/base/combined-functions.hh b/dune/xt/functions/base/combined-functions.hh index d8ffaf9cc513b9940c69ad26ab1cd5182a672ed4..a429159963e5973d467c71cbbf67728d708a22c5 100644 --- a/dune/xt/functions/base/combined-functions.hh +++ b/dune/xt/functions/base/combined-functions.hh @@ -13,225 +13,19 @@ #ifndef DUNE_XT_FUNCTIONS_BASE_COMBINED_FUNCTIONS_HH #define DUNE_XT_FUNCTIONS_BASE_COMBINED_FUNCTIONS_HH -#include <dune/xt/common/memory.hh> - #include <dune/xt/functions/interfaces/function.hh> #include <dune/xt/functions/type_traits.hh> +#include "combined.hh" + namespace Dune { namespace XT { namespace Functions { -namespace internal { /** - * \brief Helper class defining types of combined functions, if available. - * - * \note Most likely you do not want to use this class directly, but Combined. - * - * \todo Update product handling as in CombinedElementFunctionHelper to allow for more combinations! - */ -template <class LeftType, class RightType, CombinationType comb> -class SelectCombined -{ - -public: - using D = typename LeftType::DomainFieldType; - static constexpr size_t d = LeftType::domain_dim; - using R = typename LeftType::RangeFieldType; - -private: - static_assert(std::is_same<typename RightType::DomainFieldType, D>::value, "Types do not match!"); - static_assert(RightType::domain_dim == d, "Dimensions do not match!"); - static_assert(std::is_same<typename RightType::RangeFieldType, R>::value, "Types do not match!"); - - template <class L, class R> - class Choose - { - //! last tpl arg cannot be dropped due to gcc bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282 - template <size_t rL, size_t rR, size_t rCL, size_t rcR, CombinationType cc, bool anything = true> - class Dimension - { - static_assert(!anything, "No combination for these dimensions available!"); - }; - - template <size_t r_in, size_t rC_in, bool anything> - class Dimension<r_in, r_in, rC_in, rC_in, CombinationType::difference, anything> - { - public: - static constexpr size_t r = r_in; - static constexpr size_t rC = rC_in; - }; - - template <size_t r_in, size_t rC_in, bool anything> - class Dimension<r_in, r_in, rC_in, rC_in, CombinationType::sum, anything> - { - public: - static constexpr size_t r = r_in; - static constexpr size_t rC = rC_in; - }; - - template <size_t r_in, size_t rC_in, bool anything> - class Dimension<1, r_in, 1, rC_in, CombinationType::product, anything> - { - public: - static constexpr size_t r = r_in; - static constexpr size_t rC = rC_in; - }; - - public: - static constexpr size_t r = Dimension<L::range_dim, R::range_dim, L::range_dim_cols, R::range_dim_cols, comb>::r; - static constexpr size_t rC = Dimension<L::range_dim, R::range_dim, L::range_dim_cols, R::range_dim_cols, comb>::rC; - }; // class Choose - -public: - static constexpr size_t r = Choose<LeftType, RightType>::r; - static constexpr size_t rC = Choose<LeftType, RightType>::rC; - - using DomainType = typename FunctionInterface<d, r, rC, R>::DomainType; - using RangeReturnType = typename RightType::RangeReturnType; - using ScalarRangeReturnType = typename LeftType::RangeReturnType; - using DerivativeRangeReturnType = typename FunctionInterface<d, r, rC, R>::DerivativeRangeReturnType; - -private: - template <CombinationType cc, bool anything = true> - class Call - { - static_assert(!anything, "Nothing available for these combinations!"); - }; // class Call - - template <bool anything> - class Call<CombinationType::difference, anything> - { - public: - static std::string type() - { - return "difference"; - } - - static size_t order(const size_t left_order, const size_t right_order) - { - return std::max(left_order, right_order); - } - - static RangeReturnType evaluate(const LeftType& left_, - const RightType& right_, - const DomainType& point_in_global_coordinates, - const Common::Parameter& param) - { - return left_.evaluate(point_in_global_coordinates, param) - right_.evaluate(point_in_global_coordinates, param); - } - - static DerivativeRangeReturnType jacobian(const LeftType& left_, - const RightType& right_, - const DomainType& point_in_global_coordinates, - const Common::Parameter& param) - { - return left_.jacobian(point_in_global_coordinates, param) - right_.jacobian(point_in_global_coordinates, param); - } // ... jacobian(...) - }; // class Call< ..., difference > - - template <bool anything> - class Call<CombinationType::sum, anything> - { - public: - static std::string type() - { - return "sum"; - } - - static size_t order(const size_t left_order, const size_t right_order) - { - return std::max(left_order, right_order); - } - - static RangeReturnType evaluate(const LeftType& left_, - const RightType& right_, - const DomainType& point_in_global_coordinates, - const Common::Parameter& param) - { - return left_.evaluate(point_in_global_coordinates, param) + right_.evaluate(point_in_global_coordinates, param); - } // ... evaluate(...) - - static DerivativeRangeReturnType jacobian(const LeftType& left_, - const RightType& right_, - const DomainType& point_in_global_coordinates, - const Common::Parameter& param) - { - return left_.jacobian(point_in_global_coordinates, param) + right_.jacobian(point_in_global_coordinates, param); - } // ... jacobian(...) - }; // class Call< ..., sum > - - // left only scalar atm - template <bool anything> - class Call<CombinationType::product, anything> - { - public: - static std::string type() - { - return "product"; - } - - static size_t order(const size_t left_order, const size_t right_order) - { - return left_order + right_order; - } - - static RangeReturnType evaluate(const LeftType& left_, - const RightType& right_, - const DomainType& point_in_global_coordinates, - const Common::Parameter& param) - { - ScalarRangeReturnType left_eval = left_.evaluate(point_in_global_coordinates, param); - RangeReturnType right_eval = right_.evaluate(point_in_global_coordinates, param); - if (left_eval.size() != 1) - DUNE_THROW(NotImplemented, "Only available for scalar left type!"); - right_eval *= left_eval[0]; - return right_eval; - } // ... evaluate(...) - - static DerivativeRangeReturnType jacobian(const LeftType& /*left_*/, - const RightType& /*right_*/, - const DomainType& /*point_in_global_coordinates*/, - const Common::Parameter& /*param*/) - { - DUNE_THROW(NotImplemented, "If you need this, implement it!"); - return DerivativeRangeReturnType(); - } - }; // class Call< ..., product > - -public: - static std::string type() - { - return Call<comb>::type(); - } - - static size_t order(const size_t left_order, const size_t right_order) - { - return Call<comb>::order(left_order, right_order); - } - - static RangeReturnType evaluate(const LeftType& left_, - const RightType& right_, - const DomainType& point_in_global_coordinates, - const Common::Parameter& param) - { - return Call<comb>::evaluate(left_, right_, point_in_global_coordinates, param); - } - - static DerivativeRangeReturnType jacobian(const LeftType& left_, - const RightType& right_, - const DomainType& point_in_global_coordinates, - const Common::Parameter& param) - { - return Call<comb>::jacobian(left_, right_, point_in_global_coordinates, param); - } -}; // class SelectCombined - - -/** - * \brief Generic combined function. + * \brief Combined function. * * This class combines two given functions of type LeftType and RightType using the given combination @@ -282,122 +76,95 @@ Difference< ConstantType, ConstantType > stupid_difference() * \note Most likely you do not want to use this class diretly, but one of Difference, Sum or Product. */ -template <class LeftType, class RightType, CombinationType comb> +template <class LeftType, class RightType, class comb> class CombinedFunction - : public FunctionInterface<LeftType::domain_dim, - SelectCombined<LeftType, RightType, comb>::r, - SelectCombined<LeftType, RightType, comb>::rC, - typename SelectCombined<LeftType, RightType, comb>::R> + : public FunctionInterface<LeftType::d, + internal::CombinedHelper<LeftType, RightType, comb>::r, + internal::CombinedHelper<LeftType, RightType, comb>::rC, + typename internal::CombinedHelper<LeftType, RightType, comb>::R> { - using BaseType = FunctionInterface<LeftType::domain_dim, - SelectCombined<LeftType, RightType, comb>::r, - SelectCombined<LeftType, RightType, comb>::rC, - typename SelectCombined<LeftType, RightType, comb>::R>; - + static_assert(is_function<LeftType>::value, ""); + static_assert(is_function<RightType>::value, ""); + static_assert(LeftType::d == RightType::d, ""); + + using BaseType = FunctionInterface<LeftType::d, + internal::CombinedHelper<LeftType, RightType, comb>::r, + internal::CombinedHelper<LeftType, RightType, comb>::rC, + typename internal::CombinedHelper<LeftType, RightType, comb>::R>; using ThisType = CombinedFunction; - using Select = SelectCombined<LeftType, RightType, comb>; - - using LeftStorageType = Common::ConstStorageProvider<LeftType>; - using RightStorageType = Common::ConstStorageProvider<RightType>; + using Helper = internal::CombinedHelper<LeftType, RightType, comb>; public: - CombinedFunction(const LeftType& left, const RightType& right, const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(left)) - , right_(std::make_unique<RightStorageType>(right)) - , name_(get_name(left, right, nm)) - {} - - CombinedFunction(const std::shared_ptr<const LeftType> left, - const std::shared_ptr<const RightType> right, - const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(left)) - , right_(std::make_unique<RightStorageType>(right)) - , name_(get_name(*left, *right, nm)) - {} - - CombinedFunction(const LeftType& left, const std::shared_ptr<const RightType> right, const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(left)) - , right_(std::make_unique<RightStorageType>(right)) - , name_(get_name(left, *right, nm)) - {} + using typename BaseType::DerivativeRangeReturnType; + using typename BaseType::DomainType; + using typename BaseType::RangeReturnType; - CombinedFunction(const std::shared_ptr<const LeftType> left, const RightType& right, const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(left)) - , right_(std::make_unique<RightStorageType>(right)) - , name_(get_name(*left, right, nm)) + CombinedFunction(const LeftType& left, const RightType& right, const std::string nm = "") + : left_(std::move(left.copy_as_function())) + , right_(std::move(right.copy_as_function())) + , name_(nm.empty() ? "(" + left_->name() + " " + GetCombination<comb>::symbol() + " " + right_->name() + ")" : nm) {} - CombinedFunction(LeftType*&& left, RightType*&& right, const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(std::move(left))) - , right_(std::make_unique<RightStorageType>(std::move(right))) - , name_(nm.empty() ? SelectCombined<LeftType, RightType, comb>::type() + " of '" + left_->access().name() - + "' and '" + right_->access().name() + "'" - : nm) + CombinedFunction(const ThisType& other) + : BaseType(other) + , left_(other.left_->copy_as_function()) + , right_(other.right_->copy_as_function()) + , name_(other.name_) {} CombinedFunction(ThisType&& source) = default; - CombinedFunction(const ThisType& other) = delete; - - ThisType& operator=(const ThisType& other) = delete; +private: + ThisType* copy_as_function_impl() const override + { + return new ThisType(*this); + } - ThisType& operator=(ThisType&& other) = delete; +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } std::string name() const override final { return name_; } - using typename BaseType::DerivativeRangeReturnType; - using typename BaseType::DomainType; - using typename BaseType::RangeReturnType; - int order(const XT::Common::Parameter& param = {}) const override final { - auto ret = Select::order(left_->access().order(param), right_->access().order(param)); - assert(ret < std::numeric_limits<int>::max()); - return static_cast<int>(ret); + return Helper::order(*left_, *right_, param); } RangeReturnType evaluate(const DomainType& point_in_global_coordinates, const Common::Parameter& param = {}) const override final { - return Select::evaluate(left_->access(), right_->access(), point_in_global_coordinates, param); + return Helper::evaluate(*left_, *right_, point_in_global_coordinates, param); } DerivativeRangeReturnType jacobian(const DomainType& point_in_global_coordinates, const Common::Parameter& param = {}) const override final { - return Select::jacobian(left_->access(), right_->access(), point_in_global_coordinates, param); + return Helper::jacobian(*left_, *right_, point_in_global_coordinates, param); } private: - static std::string get_name(const LeftType& left, const RightType& right, const std::string& nm) - { - return nm.empty() ? SelectCombined<LeftType, RightType, comb>::type() + " of '" + left.name() + "' and '" - + right.name() + "'" - : nm; - } - - std::unique_ptr<const LeftStorageType> left_; - std::unique_ptr<const RightStorageType> right_; + std::unique_ptr<LeftType> left_; + std::unique_ptr<RightType> right_; const std::string name_; }; // class Combined -} // namespace internal - - /** * \brief Function representing the difference between two functions. * * \see internal::Combined */ template <class MinuendType, class SubtrahendType> -class DifferenceFunction : public internal::CombinedFunction<MinuendType, SubtrahendType, CombinationType::difference> +class DifferenceFunction : public CombinedFunction<MinuendType, SubtrahendType, CombinationType::difference> { - using BaseType = internal::CombinedFunction<MinuendType, SubtrahendType, CombinationType::difference>; + using BaseType = CombinedFunction<MinuendType, SubtrahendType, CombinationType::difference>; public: template <class... Args> @@ -413,9 +180,9 @@ public: * \see internal::Combined */ template <class LeftSummandType, class RightSummandType> -class SumFunction : public internal::CombinedFunction<LeftSummandType, RightSummandType, CombinationType::sum> +class SumFunction : public CombinedFunction<LeftSummandType, RightSummandType, CombinationType::sum> { - using BaseType = internal::CombinedFunction<LeftSummandType, RightSummandType, CombinationType::sum>; + using BaseType = CombinedFunction<LeftSummandType, RightSummandType, CombinationType::sum>; public: template <class... Args> @@ -426,65 +193,39 @@ public: /** - * \brief Function representing the product of two functions. + * \brief Function representing the fraction of two functions. * - * \see internal::Combined + * \see CombinedFunction */ -template <class LeftSummandType, class RightSummandType> -class ProductFunction : public internal::CombinedFunction<LeftSummandType, RightSummandType, CombinationType::product> +template <class NominatorType, class DenominatorType> +class FractionFunction : public CombinedFunction<NominatorType, DenominatorType, CombinationType::fraction> { - using BaseType = internal::CombinedFunction<LeftSummandType, RightSummandType, CombinationType::product>; + using BaseType = CombinedFunction<NominatorType, DenominatorType, CombinationType::fraction>; public: template <class... Args> - explicit ProductFunction(Args&&... args) + explicit FractionFunction(Args&&... args) : BaseType(std::forward<Args>(args)...) {} -}; // class ProductFunction +}; // class FractionFunction -template <class T1, class T2, class... Args> -std::shared_ptr<DifferenceFunction<T1, T2>> make_difference(const T1& left, const T2& right, Args&&... args) -{ - return std::make_shared<DifferenceFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} - - -template <class T1, class T2, class... Args> -std::shared_ptr<DifferenceFunction<T1, T2>> -make_difference(std::shared_ptr<T1> left, std::shared_ptr<T2> right, Args&&... args) -{ - return std::make_shared<DifferenceFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} - - -template <class T1, class T2, class... Args> -std::shared_ptr<SumFunction<T1, T2>> make_sum(const T1& left, const T2& right, Args&&... args) -{ - return std::make_shared<SumFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} - - -template <class T1, class T2, class... Args> -std::shared_ptr<SumFunction<T1, T2>> make_sum(std::shared_ptr<T1> left, std::shared_ptr<T2> right, Args&&... args) -{ - return std::make_shared<SumFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} - - -template <class T1, class T2, class... Args> -std::shared_ptr<ProductFunction<T1, T2>> make_product(const T1& left, const T2& right, Args&&... args) +/** + * \brief Function representing the product of two functions. + * + * \see internal::Combined + */ +template <class LeftFactorType, class RightFactorType> +class ProductFunction : public CombinedFunction<LeftFactorType, RightFactorType, CombinationType::product> { - return std::make_shared<ProductFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} + using BaseType = CombinedFunction<LeftFactorType, RightFactorType, CombinationType::product>; - -template <class T1, class T2, class... Args> -std::shared_ptr<ProductFunction<T1, T2>> -make_product(std::shared_ptr<T1> left, std::shared_ptr<T2> right, Args&&... args) -{ - return std::make_shared<ProductFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} +public: + template <class... Args> + explicit ProductFunction(Args&&... args) + : BaseType(std::forward<Args>(args)...) + {} +}; // class ProductFunction } // namespace Functions diff --git a/dune/xt/functions/base/combined-grid-functions.hh b/dune/xt/functions/base/combined-grid-functions.hh index e5cd8ef7409c6745f0f0496cc6915632ff9e5f73..bd14f18021959e1642d8f86b59e0ad33d7370bf2 100644 --- a/dune/xt/functions/base/combined-grid-functions.hh +++ b/dune/xt/functions/base/combined-grid-functions.hh @@ -14,306 +14,21 @@ #define DUNE_XT_FUNCTIONS_BASE_COMBINED_GRID_FUNCTIONS_HH #include <dune/xt/functions/interfaces/grid-function.hh> -#include <dune/xt/functions/type_traits.hh> + +#include "combined.hh" namespace Dune { namespace XT { namespace Functions { -namespace internal { - - -/** - * \brief Helper class defining types of combined functions, if available. - * - * \note Most likely you do not want to use this class directly, but Combined. - * - * \todo Update product handling as in CombinedElementFunctionHelper to allow for more combinations! - */ -template <class LeftType, class RightType, CombinationType comb> -class SelectCombinedGridFunction -{ - static_assert(is_grid_function<LeftType>::value, ""); - static_assert(is_grid_function<RightType>::value, ""); - -public: - using E = typename LeftType::ElementType; - using D = typename LeftType::DomainFieldType; - static constexpr size_t d = LeftType::domain_dim; - using R = typename LeftType::RangeFieldType; - -private: - static_assert(std::is_same<typename RightType::ElementType, E>::value, "Types do not match!"); - static_assert(std::is_same<typename RightType::DomainFieldType, D>::value, "Types do not match!"); - static_assert(RightType::domain_dim == d, "Dimensions do not match!"); - static_assert(std::is_same<typename RightType::RangeFieldType, R>::value, "Types do not match!"); - - template <class L, class R> - class Choose - { - template <size_t rL, size_t rR, size_t rCL, size_t rcR, CombinationType cc, bool anything = true> - class Dimension - { - static_assert(!anything, "No combination for these dimensions available!"); - }; - - template <size_t r_in, size_t rC_in, bool anything> - class Dimension<r_in, r_in, rC_in, rC_in, CombinationType::difference, anything> - { - public: - static constexpr size_t r = r_in; - static constexpr size_t rC = rC_in; - }; - - template <size_t r_in, size_t rC_in, bool anything> - class Dimension<r_in, r_in, rC_in, rC_in, CombinationType::sum, anything> - { - public: - static constexpr size_t r = r_in; - static constexpr size_t rC = rC_in; - }; - - template <size_t r_in, size_t rC_in, bool anything> - class Dimension<1, r_in, 1, rC_in, CombinationType::product, anything> - { - public: - static constexpr size_t r = r_in; - static constexpr size_t rC = rC_in; - }; - - public: - static constexpr size_t r = Dimension<L::range_dim, R::range_dim, L::range_dim_cols, R::range_dim_cols, comb>::r; - static constexpr size_t rC = Dimension<L::range_dim, R::range_dim, L::range_dim_cols, R::range_dim_cols, comb>::rC; - }; // class Choose - -public: - static constexpr size_t r = Choose<LeftType, RightType>::r; - static constexpr size_t rC = Choose<LeftType, RightType>::rC; - - using LeftLocalFunctionType = typename LeftType::LocalFunctionType; - using RightLocalFunctionType = typename RightType::LocalFunctionType; - using DomainType = typename ElementFunctionInterface<E, r, rC, R>::DomainType; - using RangeType = typename RightType::LocalFunctionType::RangeType; - using ScalarRangeType = typename LeftType::LocalFunctionType::RangeType; - using DerivativeRangeType = typename ElementFunctionInterface<E, r, rC, R>::DerivativeRangeType; - using DerivativeRangeReturnType = typename ElementFunctionInterface<E, r, rC, R>::DerivativeRangeReturnType; - -private: - template <CombinationType cc, bool anything = true> - class Call - { - static_assert(!anything, "Nothing available for these combinations!"); - }; // class Call - - template <bool anything> - class Call<CombinationType::difference, anything> - { - public: - static std::string type() - { - return "difference"; - } - - static size_t order(const size_t left_order, const size_t right_order) - { - return std::max(left_order, right_order); - } - - static RangeType evaluate(const LeftLocalFunctionType& left_local, - const RightLocalFunctionType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.evaluate(point_in_reference_element, param) - - right_local.evaluate(point_in_reference_element, param); - } - - static DerivativeRangeReturnType jacobian(const LeftLocalFunctionType& left_local, - const RightLocalFunctionType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.jacobian(point_in_reference_element, param) - - right_local.jacobian(point_in_reference_element, param); - } // ... jacobian(...) - }; // class Call< ..., difference > - - template <bool anything> - class Call<CombinationType::sum, anything> - { - public: - static std::string type() - { - return "sum"; - } - - static size_t order(const size_t left_order, const size_t right_order) - { - return std::max(left_order, right_order); - } - - static RangeType evaluate(const LeftLocalFunctionType& left_local, - const RightLocalFunctionType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.evaluate(point_in_reference_element, param) - + right_local.evaluate(point_in_reference_element, param); - } // ... evaluate(...) - - static DerivativeRangeReturnType jacobian(const LeftLocalFunctionType& left_local, - const RightLocalFunctionType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return left_local.jacobian(point_in_reference_element, param) - + right_local.jacobian(point_in_reference_element, param); - } // ... jacobian(...) - }; // class Call< ..., sum > - - // left only scalar atm - template <bool anything> - class Call<CombinationType::product, anything> - { - public: - static std::string type() - { - return "product"; - } - - static size_t order(const size_t left_order, const size_t right_order) - { - return left_order + right_order; - } - - static RangeType evaluate(const LeftLocalFunctionType& left_local, - const RightLocalFunctionType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - ScalarRangeType left_eval = left_local.evaluate(point_in_reference_element, param); - RangeType right_eval = right_local.evaluate(point_in_reference_element, param); - if (left_eval.size() != 1) - DUNE_THROW(NotImplemented, "Only available for scalar left type!"); - right_eval *= left_eval[0]; - return right_eval; - } // ... evaluate(...) - - static DerivativeRangeReturnType jacobian(const LeftLocalFunctionType& /*left_local*/, - const RightLocalFunctionType& /*right_local*/, - const DomainType& /*point_in_reference_element*/, - const Common::Parameter& /*param*/) - { - DUNE_THROW(NotImplemented, "If you need this, implement it!"); - return DerivativeRangeReturnType(); - } - }; // class Call< ..., product > - -public: - static std::string type() - { - return Call<comb>::type(); - } - - static size_t order(const size_t left_order, const size_t right_order) - { - return Call<comb>::order(left_order, right_order); - } - - static RangeType evaluate(const LeftLocalFunctionType& left_local, - const RightLocalFunctionType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return Call<comb>::evaluate(left_local, right_local, point_in_reference_element, param); - } - - static DerivativeRangeReturnType jacobian(const LeftLocalFunctionType& left_local, - const RightLocalFunctionType& right_local, - const DomainType& point_in_reference_element, - const Common::Parameter& param) - { - return Call<comb>::jacobian(left_local, right_local, point_in_reference_element, param); - } -}; // class SelectCombinedGridFunction /** - * \brief Generic combined local function. + * \brief Base combined grid function. * - * \note Most likely you do not want to use this class directly, but Combined. - */ -template <class LeftType, class RightType, CombinationType type> -class CombinedLocalFunction - : public ElementFunctionInterface<typename SelectCombinedGridFunction<LeftType, RightType, type>::E, - SelectCombinedGridFunction<LeftType, RightType, type>::r, - SelectCombinedGridFunction<LeftType, RightType, type>::rC, - typename SelectCombinedGridFunction<LeftType, RightType, type>::R> -{ - using BaseType = ElementFunctionInterface<typename SelectCombinedGridFunction<LeftType, RightType, type>::E, - SelectCombinedGridFunction<LeftType, RightType, type>::r, - SelectCombinedGridFunction<LeftType, RightType, type>::rC, - typename SelectCombinedGridFunction<LeftType, RightType, type>::R>; - - using Select = SelectCombinedGridFunction<LeftType, RightType, type>; - -public: - using typename BaseType::DerivativeRangeReturnType; - using typename BaseType::DerivativeRangeType; - using typename BaseType::DomainType; - using typename BaseType::ElementType; - using typename BaseType::RangeReturnType; - using typename BaseType::RangeType; - - CombinedLocalFunction(const LeftType& left, const RightType& right) - : BaseType() - , left_local_(left.local_function()) - , right_local_(right.local_function()) - {} - -protected: - void post_bind(const ElementType& element) override final - { - left_local_->bind(element); - right_local_->bind(element); - } - -public: - int order(const XT::Common::Parameter& param = {}) const override final - { - const auto ret = Select::order(left_local_->order(param), right_local_->order(param)); - assert(ret < std::numeric_limits<int>::max()); - return static_cast<int>(ret); - } - - RangeReturnType evaluate(const DomainType& point_in_reference_element, - const Common::Parameter& param = {}) const override final - { - return Select::evaluate(*left_local_, *right_local_, point_in_reference_element, param); - } - - DerivativeRangeReturnType jacobian(const DomainType& point_in_reference_element, - const Common::Parameter& param = {}) const override final - { - return Select::jacobian(*left_local_, *right_local_, point_in_reference_element, param); - } - -private: - std::unique_ptr<typename LeftType::LocalFunctionType> left_local_; - std::unique_ptr<typename RightType::LocalFunctionType> right_local_; -}; // class CombinedLocalFunction - - -/** - * \brief Generic combined function. - * - * This class combines two given functions of type LeftType and RightType -using the given combination - * Combination. This class (and any derived class, like Difference, Sum -or Product) can be used in two ways: - * - You can pass references of the left and right operand to this class. -This is done for instance when calling - * operator+, operator- or operator* on any function deriving from -GridFunctionInterface: + * This class combines two given grid functions of type LeftType and RightType using the given combination + * Combination. This class (and any derived class, like Difference, Sum or Product) can be used in two ways: + * - You can pass references of the left and right operand to this class. This is done for instance when calling + * operator+, operator- or operator* on any function deriving from GridFunctionInterface: \code using IndicatorType = Functions::IndicatorFunction< ..., double>; IndicatorType one( ... ); @@ -323,11 +38,9 @@ auto difference = one - two; // is equivalent to Difference< IndicatorType, IndicatorType > difference(one, two); // and -internal::Combined< IndicatorType, IndicatorType, CombinationType::difference > -difference(one, tow); +internal::Combined< IndicatorType, IndicatorType, CombinationType::difference > difference(one, tow); \endcode - * In this situation you are responsible to ensure that the arguments -given are valid throughout the lifetime + * In this situation you are responsible to ensure that the arguments given are valid throughout the lifetime * of this class. The following will lead to a segfault: \code using IndicatorType = Functions::IndicatorFunction< ..., double >; @@ -339,89 +52,106 @@ Difference< IndicatorType, IndicatorType > stupid_difference() return one - two; } \endcode - * - You can pass shared_ptr of the left and right operands to this -class. In this case the following is valid: + * - You can pass shared_ptr of the left and right operands to this class. In this case the following is valid: \code using IndicatorType = Functions::IndicatorFunction< ..., double >; -Difference< IndicatorType, IndicatorType > stupid_difference() +Difference<IndicatorType, IndicatorType> stupid_difference() { - auto one = std::make_shared< IndicatorType >(1); - auto two = std::make_shared< IndicatorType >(2); - return Difference< IndicatorType, IndicatorType >(one, two) + auto one = std::make_shared<IndicatorType>(1); + auto two = std::make_shared<IndicatorType>(2); + return Difference<IndicatorType, IndicatorType>(one, two) } \endcode * - * \note Most likely you do not want to use this class diretly, but one of -Difference, Sum or Product. + * \note Most likely you do not want to use this class diretly, but one of Difference, Fraction, Sum or Product. + * + * \todo Implement custom local function to hold a copy of this! */ -template <class LeftType, class RightType, CombinationType comb> +template <class LeftType, class RightType, class comb> class CombinedGridFunction - : public GridFunctionInterface<typename SelectCombinedGridFunction<LeftType, RightType, comb>::E, - SelectCombinedGridFunction<LeftType, RightType, comb>::r, - SelectCombinedGridFunction<LeftType, RightType, comb>::rC, - typename SelectCombinedGridFunction<LeftType, RightType, comb>::R> + : public GridFunctionInterface<typename LeftType::E, + internal::CombinedHelper<LeftType, RightType, comb>::r, + internal::CombinedHelper<LeftType, RightType, comb>::rC, + typename internal::CombinedHelper<LeftType, RightType, comb>::R> { - using BaseType = GridFunctionInterface<typename SelectCombinedGridFunction<LeftType, RightType, comb>::E, - SelectCombinedGridFunction<LeftType, RightType, comb>::r, - SelectCombinedGridFunction<LeftType, RightType, comb>::rC, - typename SelectCombinedGridFunction<LeftType, RightType, comb>::R>; + static_assert(is_grid_function<LeftType>::value, ""); + static_assert(is_grid_function<RightType>::value, ""); + static_assert(std::is_same<typename LeftType::E, typename RightType::E>::value, ""); - using LeftStorageType = Common::ConstStorageProvider<LeftType>; - using RightStorageType = Common::ConstStorageProvider<RightType>; using ThisType = CombinedGridFunction; + using BaseType = GridFunctionInterface<typename LeftType::E, + internal::CombinedHelper<LeftType, RightType, comb>::r, + internal::CombinedHelper<LeftType, RightType, comb>::rC, + typename internal::CombinedHelper<LeftType, RightType, comb>::R>; public: using ElementType = typename BaseType::ElementType; using LocalFunctionType = typename BaseType::LocalFunctionType; - CombinedGridFunction(const LeftType& left, const RightType& right, const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(left)) - , right_(std::make_unique<RightStorageType>(right)) - , name_(get_name(left_->access(), right_->access(), nm)) - {} - - CombinedGridFunction(const std::shared_ptr<const LeftType> left, - const std::shared_ptr<const RightType> right, - const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(left)) - , right_(std::make_unique<RightStorageType>(right)) - , name_(get_name(left_->access(), right_->access(), nm)) - {} - - CombinedGridFunction(const LeftType& left, const std::shared_ptr<const RightType> right, const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(left)) - , right_(std::make_unique<RightStorageType>(right)) - , name_(get_name(left_->access(), right_->access(), nm)) - {} + CombinedGridFunction(const LeftType& left, + const RightType& right, + const std::string nm = "", + const std::string& logging_prefix = "") + : BaseType(left.parameter_type() + right.parameter_type(), + logging_prefix.empty() ? Common::to_camel_case(get_combination_name(comb{}) + "GridFunction") + : logging_prefix, + logging_prefix.empty()) + , left_(left.copy_as_grid_function()) + , right_(right.copy_as_grid_function()) + , name_(nm.empty() ? "(" + left_->name() + GetCombination<comb>::symbol() + right_->name() + ")" : nm) + { + LOG_(debug) << Common::to_camel_case(get_combination_name(comb{}) + "GridFunction") << "(left=" << &left + << ", right=" << &right << ", nm=\"" << nm << "\")" << std::endl; + } - CombinedGridFunction(const std::shared_ptr<const LeftType> left, const RightType& right, const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(left)) - , right_(std::make_unique<RightStorageType>(right)) - , name_(get_name(left_->access(), right_->access(), nm)) - {} + CombinedGridFunction(LeftType*&& left, + RightType*&& right, + const std::string nm = "", + const std::string& logging_prefix = "") + : BaseType(left->parameter_type() + right->parameter_type(), + logging_prefix.empty() ? Common::to_camel_case(get_combination_name(comb{}) + "GridFunction") + : logging_prefix, + logging_prefix.empty()) + , left_(std::move(left)) + , right_(std::move(right)) + , name_(nm.empty() ? "(" + left_->name() + GetCombination<comb>::symbol() + right_->name() + ")" : nm) + { + LOG_(debug) << Common::to_camel_case(get_combination_name(comb{}) + "GridFunction") << "(left=" << left + << ", right=" << right << ", nm=\"" << nm << "\")" << std::endl; + } - CombinedGridFunction(LeftType*&& left, RightType*&& right, const std::string nm = "") - : left_(std::make_unique<LeftStorageType>(std::move(left))) - , right_(std::make_unique<RightStorageType>(std::move(right))) - , name_(get_name(left_->access(), right_->access(), nm)) + CombinedGridFunction(const ThisType& other) + : BaseType(other) + , left_(other.left_->copy_as_grid_function()) + , right_(other.right_->copy_as_grid_function()) + , name_(other.name_) {} CombinedGridFunction(ThisType&& source) = default; - CombinedGridFunction(const ThisType& other) = delete; + std::unique_ptr<LocalFunctionType> local_function() const override final + { + LOG_(debug) << Common::to_camel_case(get_combination_name(comb{}) + "GridFunction") + "::local_function()" + << std::endl; + using LeftLF = typename LeftType::LocalFunctionType; + using RightLF = typename RightType::LocalFunctionType; + return std::make_unique<CombinedElementFunction<LeftLF, RightLF, comb>>(std::move(left_->local_function()), + std::move(right_->local_function())); + } // ... local_function(...) - ThisType& operator=(const ThisType& other) = delete; - ThisType& operator=(ThisType&& other) = delete; +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } - std::unique_ptr<LocalFunctionType> local_function() const override final +public: + std::unique_ptr<ThisType> copy_as_grid_function() const { - using RealLocalFunctionType = CombinedLocalFunction<LeftType, RightType, comb>; - assert(left_); - assert(right_); - return std::make_unique<RealLocalFunctionType>(left_->access(), right_->access()); - } // ... local_function(...) + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } std::string name() const override final { @@ -429,32 +159,22 @@ public: } private: - static std::string get_name(const LeftType& left, const RightType& right, const std::string& nm) - { - return nm.empty() ? SelectCombinedGridFunction<LeftType, RightType, comb>::type() + " of '" + left.name() - + "' and '" + right.name() + "'" - : nm; - } - - std::unique_ptr<const LeftStorageType> left_; - std::unique_ptr<const RightStorageType> right_; + std::unique_ptr<GridFunctionInterface<typename LeftType::E, LeftType::r, LeftType::rC, typename LeftType::R>> left_; + std::unique_ptr<GridFunctionInterface<typename RightType::E, RightType::r, RightType::rC, typename RightType::R>> + right_; const std::string name_; }; // class CombinedGridFunction -} // namespace internal - - /** * \brief Function representing the difference between two functions. * - * \see internal::CombinedGridFunction + * \see CombinedGridFunction */ template <class MinuendType, class SubtrahendType> -class DifferenceGridFunction - : public internal::CombinedGridFunction<MinuendType, SubtrahendType, CombinationType::difference> +class DifferenceGridFunction : public CombinedGridFunction<MinuendType, SubtrahendType, CombinationType::difference> { - using BaseType = internal::CombinedGridFunction<MinuendType, SubtrahendType, CombinationType::difference>; + using BaseType = CombinedGridFunction<MinuendType, SubtrahendType, CombinationType::difference>; public: template <class... Args> @@ -467,12 +187,12 @@ public: /** * \brief Function representing the sum of two functions. * - * \see internal::CombinedGridFunction + * \see CombinedGridFunction */ template <class LeftSummandType, class RightSummandType> -class SumGridFunction : public internal::CombinedGridFunction<LeftSummandType, RightSummandType, CombinationType::sum> +class SumGridFunction : public CombinedGridFunction<LeftSummandType, RightSummandType, CombinationType::sum> { - using BaseType = internal::CombinedGridFunction<LeftSummandType, RightSummandType, CombinationType::sum>; + using BaseType = CombinedGridFunction<LeftSummandType, RightSummandType, CombinationType::sum>; public: template <class... Args> @@ -483,82 +203,39 @@ public: /** - * \brief Grid function representing the product of two grid functions. + * \brief Function representing the fraction of two functions. * - * \see internal::CombinedGridFunction + * \see CombinedGridFunction */ -template <class LeftSummandType, class RightSummandType> -class ProductGridFunction - : public internal::CombinedGridFunction<LeftSummandType, RightSummandType, CombinationType::product> +template <class NominatorType, class DenominatorType> +class FractionGridFunction : public CombinedGridFunction<NominatorType, DenominatorType, CombinationType::fraction> { - using BaseType = internal::CombinedGridFunction<LeftSummandType, RightSummandType, CombinationType::product>; + using BaseType = CombinedGridFunction<NominatorType, DenominatorType, CombinationType::fraction>; public: template <class... Args> - explicit ProductGridFunction(Args&&... args) + explicit FractionGridFunction(Args&&... args) : BaseType(std::forward<Args>(args)...) {} -}; // class ProductGridFunction +}; // class FractionGridFunction -template <class T1, class T2, class... Args> -std::shared_ptr<DifferenceGridFunction<T1, T2>> make_difference(const T1& left, const T2& right, Args&&... args) -{ - return std::make_shared<DifferenceGridFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} - -template <class T1, class T2, class... Args> -std::shared_ptr<DifferenceGridFunction<T1, T2>> -make_difference(std::shared_ptr<T1> left, std::shared_ptr<T2> right, Args&&... args) -{ - return std::make_shared<DifferenceGridFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} - -template <class T1, class T2, class... Args> -std::shared_ptr<DifferenceGridFunction<T1, T2>> make_difference(T1*&& left, T2*&& right, Args&&... args) -{ - return std::make_shared<DifferenceGridFunction<T1, T2>>( - std::move(left), std::move(right), std::forward<Args>(args)...); -} - - -template <class T1, class T2, class... Args> -std::shared_ptr<SumGridFunction<T1, T2>> make_sum(const T1& left, const T2& right, Args&&... args) -{ - return std::make_shared<SumGridFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} - -template <class T1, class T2, class... Args> -std::shared_ptr<SumGridFunction<T1, T2>> make_sum(std::shared_ptr<T1> left, std::shared_ptr<T2> right, Args&&... args) -{ - return std::make_shared<SumGridFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} - -template <class T1, class T2, class... Args> -std::shared_ptr<SumGridFunction<T1, T2>> make_sum(T1*&& left, T2*&& right, Args&&... args) -{ - return std::make_shared<SumGridFunction<T1, T2>>(std::move(left), std::move(right), std::forward<Args>(args)...); -} - - -template <class T1, class T2, class... Args> -std::shared_ptr<ProductGridFunction<T1, T2>> make_product(const T1& left, const T2& right, Args&&... args) -{ - return std::make_shared<ProductGridFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} - -template <class T1, class T2, class... Args> -std::shared_ptr<ProductGridFunction<T1, T2>> -make_product(std::shared_ptr<T1> left, std::shared_ptr<T2> right, Args&&... args) +/** + * \brief Grid function representing the product of two grid functions. + * + * \see CombinedGridFunction + */ +template <class LeftFactorType, class RightFactorType> +class ProductGridFunction : public CombinedGridFunction<LeftFactorType, RightFactorType, CombinationType::product> { - return std::make_shared<ProductGridFunction<T1, T2>>(left, right, std::forward<Args>(args)...); -} + using BaseType = CombinedGridFunction<LeftFactorType, RightFactorType, CombinationType::product>; -template <class T1, class T2, class... Args> -std::shared_ptr<ProductGridFunction<T1, T2>> make_product(T1*&& left, T2*&& right, Args&&... args) -{ - return std::make_shared<ProductGridFunction<T1, T2>>(std::move(left), std::move(right), std::forward<Args>(args)...); -} +public: + template <class... Args> + explicit ProductGridFunction(Args&&... args) + : BaseType(std::forward<Args>(args)...) + {} +}; // class ProductGridFunction } // namespace Functions diff --git a/dune/xt/functions/base/combined.hh b/dune/xt/functions/base/combined.hh new file mode 100644 index 0000000000000000000000000000000000000000..395293e87dc52ae39059e82d4d244fee2a4c22b9 --- /dev/null +++ b/dune/xt/functions/base/combined.hh @@ -0,0 +1,340 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#ifndef DUNE_XT_FUNCTIONS_BASE_COMBINED_HH +#define DUNE_XT_FUNCTIONS_BASE_COMBINED_HH + +#include <dune/xt/common/memory.hh> +#include <dune/xt/common/parameter.hh> +#include <dune/xt/common/type_traits.hh> +#include <dune/xt/functions/exceptions.hh> +#include <dune/xt/functions/type_traits.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace internal { + + +template <typename comb, size_t L_r, size_t L_rC, size_t R_r, size_t R_rC> +struct CombinedDim +{ + static constexpr bool available() + { + return true; + }; + static constexpr size_t r() + { + return L_r; + } + static constexpr size_t rC() + { + return L_rC; + } +}; + +// general case: non-scalar matrix * non-scalar {matrix or vector} +template <size_t L_r, size_t L_rC, size_t R_r, size_t R_rC> +struct CombinedDim<CombinationType::product, L_r, L_rC, R_r, R_rC> +{ + static constexpr size_t r() + { + if constexpr (R_rC == 1 && L_rC == 1 && L_r != 1) { + return 1; + } else if constexpr (L_r == 1 && L_rC == 1 && R_r * R_rC != 1) { + return R_r; + } else if constexpr (R_r == 1 && R_rC == 1) { + return L_r; + } else if constexpr (L_rC * R_rC != 1) { + return L_r; + } + return 0; + } + + static constexpr size_t rC() + { + if constexpr (R_rC == 1 && L_rC == 1 && L_r != 1) { + return 1; + } else if constexpr (L_r == 1 && L_rC == 1 && R_r * R_rC != 1) { + return R_rC; + } else if constexpr (R_r == 1 && R_rC == 1) { + return L_rC; + } else if constexpr (L_rC * R_rC != 1) { + return R_rC; + } + return 0; + } + + static constexpr bool available() + { + return r() != 0 && rC() != 0; + } +}; + +template <class L, class R> +static int +compute_combined_order(const L& left, const R& right, const Common::Parameter& param, CombinationType::difference) +{ + return std::max(left.order(param), right.order(param)); +} + +template <class L, class R> +static int +compute_combined_order(const L& left, const R& right, const Common::Parameter& param, CombinationType::fraction) +{ + return left.order(param) + right.order(param); +} +template <class L, class R> +static int +compute_combined_order(const L& left, const R& right, const Common::Parameter& param, CombinationType::product) +{ + return left.order(param) + right.order(param); +} +template <class L, class R> +static int compute_combined_order(const L& left, const R& right, const Common::Parameter& param, CombinationType::sum) +{ + return std::max(left.order(param), right.order(param)); +} + +template <class Left, class Right, class D> +static auto compute_combined_eval( + const Left& left, const Right& right, const D& point, const Common::Parameter& param, CombinationType::difference) +{ + return left.evaluate(point, param) - right.evaluate(point, param); +} + +template <class Left, class Right, class D> +static auto compute_combined_eval( + const Left& left, const Right& right, const D& point, const Common::Parameter& param, CombinationType::fraction) +{ + auto left_value = left.evaluate(point, param); + const auto right_value = right.evaluate(point, param)[0]; + left_value /= right_value; + return left_value; +} + +template <class Left, class Right, class D> +static auto compute_combined_eval( + const Left& left, const Right& right, const D& point, const Common::Parameter& param, CombinationType::sum) +{ + return left.evaluate(point, param) + right.evaluate(point, param); +} + +template <typename comb, class L_R, class R_R, size_t L_r, size_t L_rC, size_t R_r, size_t R_rC> +struct CombinedEval +{ + using R = typename std::conditional<std::is_same<CombinationType::fraction, comb>::value, + typename Common::multiplication_promotion<L_R, R_R>::type, + typename Common::plus_promotion<L_R, R_R>::type>::type; + static const constexpr size_t r = CombinedDim<comb, L_r, L_rC, R_r, R_rC>::r(); + static const constexpr size_t rC = CombinedDim<comb, L_r, L_rC, R_r, R_rC>::rC(); + + template <class Left, class Right, class D> + static auto compute(const Left& left, const Right& right, const D& point, const Common::Parameter& param) + { + return compute_combined_eval(left, right, point, param, comb{}); + } +}; + +template <class L_R, class R_R, size_t L_r, size_t L_rC, size_t R_r, size_t R_rC> +struct CombinedEval<CombinationType::product, L_R, R_R, L_r, L_rC, R_r, R_rC> +{ + static const constexpr size_t r = CombinedDim<CombinationType::product, L_r, L_rC, R_r, R_rC>::r(); + static const constexpr size_t rC = CombinedDim<CombinationType::product, L_r, L_rC, R_r, R_rC>::rC(); + using R = typename Common::multiplication_promotion<L_R, R_R>::type; + using RangeReturnType = typename RangeTypeSelector<R, r, rC>::return_type; + template <class Left, class Right, class D> + static RangeReturnType compute(const Left& left, const Right& right, const D& point, const Common::Parameter& param) + { + // general case: non-scalar matrix * non-scalar {matrix or vector} + if constexpr (R_r == L_rC && L_rC * R_rC != 1) { + if constexpr (L_rC == 1) { + // need to wrap the left vector into a matrix, for * to do the right thing + XT::Common::FieldMatrix<R, 1, L_r> left_value; + left_value[0] = left.evaluate(point, param); + return left_value.transpose() * right.evaluate(point, param); + } else + return left.evaluate(point, param) * right.evaluate(point, param); + } + + // special case: non-scalar elementwise multiplication by scalar from the left + else if constexpr (L_r == 1 && L_rC == 1 && R_r * R_rC != 1) { + const auto left_value = left.evaluate(point, param)[0]; + RangeReturnType right_value = right.evaluate(point, param); + right_value *= left_value; + return right_value; + } + // special case: elementwise multiplication by scalar from the right AND all scalar case + else if constexpr (std::is_convertible<decltype(left.evaluate(point, param)), RangeReturnType>::value && R_r == 1 + && R_rC == 1) { + RangeReturnType left_value = left.evaluate(point, param); + const auto right_value = right.evaluate(point, param)[0]; + left_value *= right_value; + return left_value; + } + // special case: non-scalar vectors + else if constexpr (L_r == R_r && R_rC == 1 && L_rC == 1 && L_r != 1) { + return left.evaluate(point, param) * right.evaluate(point, param); + } + DUNE_THROW(NotImplemented, "no product compute combination available"); + } +}; + +template <class comb, + class L_R, + class R_R, + size_t d, + size_t L_r, + size_t L_rC, + size_t R_r, + size_t R_rC, + typename anything = void> +struct CombinedJac +{ + static const constexpr size_t r = CombinedDim<comb, L_r, L_rC, R_r, R_rC>::r(); + static const constexpr size_t rC = CombinedDim<comb, L_r, L_rC, R_r, R_rC>::rC(); + + using R = typename CombinedEval<comb, L_R, R_R, L_r, L_rC, R_r, R_rC>::R; + using DerivativeRangeReturnType = typename DerivativeRangeTypeSelector<d, R, r, rC>::return_type; + + template <class Left, class Right, class D> + static DerivativeRangeReturnType + compute(const Left& /*left*/, const Right& /*right*/, const D& /*point*/, const Common::Parameter& /*param*/) + { + DUNE_THROW(Exceptions::combined_error, + "Not available for a " << get_combination_name(comb{}) << "of " << L_r << "x" << L_rC << " and " << R_r + << "x" << R_rC << "!"); + return DerivativeRangeReturnType(); + } +}; + +template <class L_R, class R_R, size_t d, size_t L_r, size_t L_rC, typename a> +struct CombinedJac<CombinationType::difference, L_R, R_R, d, L_r, L_rC, L_r, L_rC, a> +{ + static const constexpr size_t r = CombinedDim<CombinationType::difference, L_r, L_rC, L_r, L_rC>::r(); + static const constexpr size_t rC = CombinedDim<CombinationType::difference, L_r, L_rC, L_r, L_rC>::rC(); + + using R = typename CombinedEval<CombinationType::difference, L_R, R_R, L_r, L_rC, L_r, L_rC>::R; + using DerivativeRangeReturnType = typename DerivativeRangeTypeSelector<d, R, r, rC>::return_type; + + template <class Left, class Right, class D> + static DerivativeRangeReturnType + compute(const Left& left, const Right& right, const D& point, const Common::Parameter& param) + { + return left.jacobian(point, param) - right.jacobian(point, param); + } +}; + +template <class L_R, class R_R, size_t d, size_t L_r, size_t L_rC, typename a> +struct CombinedJac<CombinationType::sum, L_R, R_R, d, L_r, L_rC, L_r, L_rC, a> +{ + static const constexpr size_t r = CombinedDim<CombinationType::sum, L_r, L_rC, L_r, L_rC>::r(); + static const constexpr size_t rC = CombinedDim<CombinationType::sum, L_r, L_rC, L_r, L_rC>::rC(); + + using R = typename CombinedEval<CombinationType::sum, L_R, R_R, L_r, L_rC, L_r, L_rC>::R; + using DerivativeRangeReturnType = typename DerivativeRangeTypeSelector<d, R, r, rC>::return_type; + + template <class Left, class Right, class D> + static DerivativeRangeReturnType + compute(const Left& left, const Right& right, const D& point, const Common::Parameter& param) + { + return left.jacobian(point, param) - right.jacobian(point, param); + } +}; + + +/** + * \brief Helper class defining types of combined functions, if available. + * + * \note Most likely you do not want to use this class directly, but CombinedConstElementFunction or + * CombinedElementFunction. + */ +template <class Left, class Right, typename comb> +struct CombinedHelper +{ + static_assert(is_element_function<Left>::value || is_function<Left>::value || is_grid_function<Left>::value, ""); + static_assert(is_element_function<Right>::value || is_function<Right>::value || is_grid_function<Right>::value, ""); + static_assert(Left::d == Right::d, ""); + + static const constexpr size_t d = Left::d; + static const constexpr size_t L_r = Left::r; + static const constexpr size_t L_rC = Left::rC; + static const constexpr size_t R_r = Right::r; + static const constexpr size_t R_rC = Right::rC; + + using CombinedDimHelper = CombinedDim<comb, L_r, L_rC, R_r, R_rC>; + static const constexpr bool available = CombinedDimHelper::available(); + static const constexpr size_t r = CombinedDimHelper::r(); + static const constexpr size_t rC = CombinedDimHelper::rC(); + + static int order(const Left& left, const Right& right, const Common::Parameter& param) + { + return compute_combined_order(left, right, param, comb{}); + } + + using L_R = typename Left::R; + using R_R = typename Right::R; + using CombinedEvalHelper = CombinedEval<comb, L_R, R_R, L_r, L_rC, R_r, R_rC>; + using R = typename CombinedEvalHelper::R; + + template <class D> + static auto evaluate(const Left& left, const Right& right, const D& point, const Common::Parameter& param) + { + return CombinedEvalHelper::compute(left, right, point, param); + } + + using CombinedJacHelper = CombinedJac<comb, L_R, R_R, d, L_r, L_rC, R_r, R_rC>; + using DerivativeRangeReturnType = typename CombinedJacHelper::DerivativeRangeReturnType; + + template <class D> + static DerivativeRangeReturnType + jacobian(const Left& left, const Right& right, const D& point, const Common::Parameter& param) + { + return CombinedJacHelper::compute(left, right, point, param); + } +}; // struct CombinedHelper + + +template <class LeftType, class RightType> +struct CombinedStorageProvider +{ + using ThisType = CombinedStorageProvider; + + XT::Common::StorageProvider<LeftType> left; + XT::Common::StorageProvider<RightType> right; + + CombinedStorageProvider(LeftType& lft, RightType& rght) + : left(lft) + , right(rght) + {} + + CombinedStorageProvider(std::shared_ptr<LeftType> lft, std::shared_ptr<RightType> rght) + : left(lft) + , right(rght) + {} + + CombinedStorageProvider(std::unique_ptr<LeftType>&& lft, std::unique_ptr<RightType>&& rght) + : left(std::move(lft)) + , right(std::move(rght)) + {} + + CombinedStorageProvider(const ThisType&) = default; + + CombinedStorageProvider(ThisType&) = default; + + CombinedStorageProvider(ThisType&&) = default; +}; // struct CombinedStorageProvider + + +} // namespace internal +} // namespace Functions +} // namespace XT +} // namespace Dune + +#endif // DUNE_XT_FUNCTIONS_BASE_COMBINED_HH diff --git a/dune/xt/functions/base/composition.hh b/dune/xt/functions/base/composition.hh index def02415c26b695d027d7cd783ed889e08c92658..e99739a08a846f371f89f7676dcb2c14032ce5ba 100644 --- a/dune/xt/functions/base/composition.hh +++ b/dune/xt/functions/base/composition.hh @@ -243,11 +243,20 @@ public: CompositionFunction(const ThisType& other) = default; - ThisType& operator=(const ThisType& other) = delete; - ThisType& operator=(ThisType&& source) = delete; +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } - virtual std::string name() const override +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } + + std::string name() const override final { return name_; } @@ -255,8 +264,7 @@ public: std::unique_ptr<LocalFunctionType> local_function() const override final { return std::make_unique<ElementFunction>(inner_function_, outer_function_, element_search_); - } // ... local_function(...) - + } private: const InnerType inner_function_; diff --git a/dune/xt/functions/base/derivatives-of-element-functions.hh b/dune/xt/functions/base/derivatives-of-element-functions.hh index ce74eb4f5ceca9a523f607a7aa1801a2f3de878f..9a27933ee8484e42f6560b2b718d87d6a5683d45 100644 --- a/dune/xt/functions/base/derivatives-of-element-functions.hh +++ b/dune/xt/functions/base/derivatives-of-element-functions.hh @@ -27,7 +27,7 @@ namespace internal { template <class ElementFunctionType, DerivativeType derivative> class DerivativeElementFunctionHelper { - static_assert(is_element_function<ElementFunctionType>::value, ""); + static_assert(is_element_function<ElementFunctionType>::value || is_grid_function<ElementFunctionType>::value, ""); public: using E = typename ElementFunctionType::E; @@ -201,7 +201,7 @@ public: {} protected: - void post_bind(const ElementType& element) + void post_bind(const ElementType& element) override final { if (do_post_bind_) func_.access().bind(element); diff --git a/dune/xt/functions/base/derivatives-of-grid-functions.hh b/dune/xt/functions/base/derivatives-of-grid-functions.hh new file mode 100644 index 0000000000000000000000000000000000000000..18f4d8d6caf4a6acb03626167b757f95bbb93c97 --- /dev/null +++ b/dune/xt/functions/base/derivatives-of-grid-functions.hh @@ -0,0 +1,130 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2019) +// René Fritze (2019) +// Tobias Leibner (2020) + +#ifndef DUNE_XT_FUNCTIONS_BASE_DERIVATIVES_OF_GRID_FUNCTIONS_HH +#define DUNE_XT_FUNCTIONS_BASE_DERIVATIVES_OF_GRID_FUNCTIONS_HH + +#include <dune/xt/common/memory.hh> + +#include <dune/xt/functions/grid-function.hh> +#include <dune/xt/functions/interfaces/grid-function.hh> +#include <dune/xt/functions/type_traits.hh> + +#include "derivatives-of-element-functions.hh" + + +namespace Dune { +namespace XT { +namespace Functions { + + +template <class GridFunctionType, DerivativeType derivative> +class DerivativeGridFunction + : public GridFunctionInterface<typename internal::DerivativeElementFunctionHelper<GridFunctionType, derivative>::E, + internal::DerivativeElementFunctionHelper<GridFunctionType, derivative>::r, + internal::DerivativeElementFunctionHelper<GridFunctionType, derivative>::rC, + typename internal::DerivativeElementFunctionHelper<GridFunctionType, derivative>::R> +{ + static_assert(is_grid_function<GridFunctionType>::value, ""); + + using ThisType = DerivativeGridFunction; + using BaseType = + GridFunctionInterface<typename internal::DerivativeElementFunctionHelper<GridFunctionType, derivative>::E, + internal::DerivativeElementFunctionHelper<GridFunctionType, derivative>::r, + internal::DerivativeElementFunctionHelper<GridFunctionType, derivative>::rC, + typename internal::DerivativeElementFunctionHelper<GridFunctionType, derivative>::R>; + + using Select = internal::DerivativeElementFunctionHelper<GridFunctionType, derivative>; + + static const constexpr size_t r_ = GridFunctionType::r; + static const constexpr size_t rC_ = GridFunctionType::rC; + +public: + using BaseType::r; + using BaseType::rC; + using typename BaseType::E; + using typename BaseType::LocalFunctionType; + using typename BaseType::R; + + DerivativeGridFunction(GridFunction<E, r_, rC_, R> grid_function, const std::string& nm = "") + : BaseType(grid_function.parameter_type()) + , grid_function_(grid_function.copy_as_grid_function()) + , name_(nm.empty() ? "DerivativeGridFunction" : nm) + {} + + DerivativeGridFunction(const ThisType& other) + : BaseType(other) + , grid_function_(other.grid_function_->copy_as_grid_function()) + , name_(other.name_) + {} + + std::unique_ptr<LocalFunctionType> local_function() const override final + { + return std::make_unique<DerivativeElementFunction<typename GridFunctionType::LocalFunctionType, derivative>>( + grid_function_->local_function()); + } + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } + + std::string name() const override final + { + return name_; + } + +private: + std::unique_ptr<GridFunctionInterface<E, r_, rC_, R>> grid_function_; + const std::string name_; +}; // class DerivativeGridFunction + + +template <class GridFunctionType> +class DivergenceGridFunction : public DerivativeGridFunction<GridFunctionType, DerivativeType::divergence> +{ + using BaseType = DerivativeGridFunction<GridFunctionType, DerivativeType::divergence>; + +public: + template <class... Args> + explicit DivergenceGridFunction(Args&&... args) + : BaseType(std::forward<Args>(args)...) + {} +}; // class DivergenceGridFunction + + +template <class GridFunctionType> +class GradientGridFunction : public DerivativeGridFunction<GridFunctionType, DerivativeType::gradient> +{ + using BaseType = DerivativeGridFunction<GridFunctionType, DerivativeType::gradient>; + +public: + template <class... Args> + explicit GradientGridFunction(Args&&... args) + : BaseType(std::forward<Args>(args)...) + {} +}; // class GradientGridFunction + + +} // namespace Functions +} // namespace XT +} // namespace Dune + + +#endif // DUNE_XT_FUNCTIONS_DERIVED_HH diff --git a/dune/xt/functions/base/function-as-grid-function.hh b/dune/xt/functions/base/function-as-grid-function.hh index 94d1233f5df5f4f5805b571bcd90317c5ea752de..1d626e9e1e7f71db69d01acee4c213cde294df21 100644 --- a/dune/xt/functions/base/function-as-grid-function.hh +++ b/dune/xt/functions/base/function-as-grid-function.hh @@ -38,45 +38,50 @@ public: using FunctionType = FunctionInterface<d, r, rC, R>; FunctionAsGridFunctionWrapper(const FunctionType& function) - : function_storage_(function) + : BaseType(function.parameter_type()) + , function_(function.copy_as_function()) {} FunctionAsGridFunctionWrapper(FunctionType*&& function_ptr) - : function_storage_(std::move(function_ptr)) + : BaseType(function_ptr->parameter_type()) + , function_(std::move(function_ptr)) {} FunctionAsGridFunctionWrapper(std::unique_ptr<FunctionType>&& function_ptr) - : function_storage_(std::move(function_ptr)) + : BaseType(function_ptr->parameter_type()) + , function_(std::move(function_ptr)) + {} + + FunctionAsGridFunctionWrapper(const ThisType& other) + : BaseType(other) + , function_(other.function_->copy_as_function()) {} - FunctionAsGridFunctionWrapper(const ThisType&) = default; FunctionAsGridFunctionWrapper(ThisType&&) = default; - /** - * \name ´´This method is required by GridFunctionInterface.'' - * \{ - **/ - std::unique_ptr<LocalFunctionType> local_function() const override final +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const { - return std::make_unique<LocalFunction>(function_storage_.access()); + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); } - /** - * \} - * \name ´´These methods are optionally required by GridFunctionInterface.'' - * \{ - **/ + std::unique_ptr<LocalFunctionType> local_function() const override final + { + return std::make_unique<LocalFunction>(*function_); + } std::string name() const override final { - return function_storage_.access().name(); + return function_->name(); } - /** - * \} - **/ - private: class LocalFunction : public LocalFunctionType { @@ -90,7 +95,7 @@ private: LocalFunction(const FunctionType& function) : BaseType() - , function_(function) + , function_(function.copy_as_function()) , geometry_(nullptr) {} @@ -103,8 +108,8 @@ private: public: int order(const Common::Parameter& param = {}) const override final { - DUNE_THROW_IF(!(geometry_), Exceptions::not_bound_to_an_element_yet, function_.name()); - return function_.order(param); + DUNE_THROW_IF(!(geometry_), Exceptions::not_bound_to_an_element_yet, function_->name()); + return function_->order(param); } using BaseType::evaluate; @@ -112,9 +117,9 @@ private: RangeReturnType evaluate(const DomainType& point_in_reference_element, const Common::Parameter& param = {}) const override final { - DUNE_THROW_IF(!(geometry_), Exceptions::not_bound_to_an_element_yet, function_.name()); + DUNE_THROW_IF(!(geometry_), Exceptions::not_bound_to_an_element_yet, function_->name()); this->assert_inside_reference_element(point_in_reference_element); - return function_.evaluate(geometry_->global(point_in_reference_element), param); + return function_->evaluate(geometry_->global(point_in_reference_element), param); } using BaseType::jacobian; @@ -122,9 +127,9 @@ private: DerivativeRangeReturnType jacobian(const DomainType& point_in_reference_element, const Common::Parameter& param = {}) const override final { - DUNE_THROW_IF(!(geometry_), Exceptions::not_bound_to_an_element_yet, function_.name()); + DUNE_THROW_IF(!(geometry_), Exceptions::not_bound_to_an_element_yet, function_->name()); this->assert_inside_reference_element(point_in_reference_element); - return function_.jacobian(geometry_->global(point_in_reference_element), param); + return function_->jacobian(geometry_->global(point_in_reference_element), param); } using BaseType::derivative; @@ -133,17 +138,17 @@ private: const DomainType& point_in_reference_element, const Common::Parameter& param = {}) const override final { - DUNE_THROW_IF(!(geometry_), Exceptions::not_bound_to_an_element_yet, function_.name()); + DUNE_THROW_IF(!(geometry_), Exceptions::not_bound_to_an_element_yet, function_->name()); this->assert_inside_reference_element(point_in_reference_element); - return function_.derivative(alpha, geometry_->global(point_in_reference_element), param); + return function_->derivative(alpha, geometry_->global(point_in_reference_element), param); } private: - const FunctionType& function_; + std::unique_ptr<FunctionType> function_; std::unique_ptr<GeometryType> geometry_; }; // class LocalFunction - XT::Common::ConstStorageProvider<FunctionType> function_storage_; + std::unique_ptr<FunctionType> function_; }; // class FunctionAsGridFunctionWrapper diff --git a/dune/xt/functions/base/reinterpret.hh b/dune/xt/functions/base/reinterpret.hh index b2c6c569094668050c13f6832b1c499c1431dda6..00adcf3ceea03ad6275c78b64657e7e9a20db1c5 100644 --- a/dune/xt/functions/base/reinterpret.hh +++ b/dune/xt/functions/base/reinterpret.hh @@ -42,7 +42,8 @@ class ReinterpretLocalizableFunction : public GridFunctionInterface<TargetElement, range_dim, range_dim_cols, RangeField> { static_assert(XT::Grid::is_layer<SourceGridView>::value, ""); - using ThisType = ReinterpretLocalizableFunction<SourceGridView, TargetElement, range_dim, range_dim_cols, RangeField>; + + using ThisType = ReinterpretLocalizableFunction; using BaseType = GridFunctionInterface<TargetElement, range_dim, range_dim_cols, RangeField>; public: @@ -53,25 +54,41 @@ public: using SourceType = GridFunctionInterface<XT::Grid::extract_entity_t<SourceGridView>, r, rC, R>; - static std::string static_id() - { - return BaseType::static_id() + ".reinterpret"; - } - ReinterpretLocalizableFunction(const SourceType& source, const SourceGridView& source_grid_view) : BaseType(source.parameter_type()) - , source_(source) + , source_(source.copy_as_grid_function()) , source_grid_view_(source_grid_view) {} + ReinterpretLocalizableFunction(const ThisType& other) + : BaseType(other) + , source_(other.source_->copy_as_grid_function()) + , source_grid_view_(other.source_grid_view_) + {} + + ReinterpretLocalizableFunction(ThisType&&) = default; + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } + std::unique_ptr<LocalFunctionType> local_function() const override final { - return std::make_unique<ReinterpretLocalfunction>(source_, source_grid_view_); + return std::make_unique<ReinterpretLocalfunction>(*source_, source_grid_view_); } std::string name() const { - return BaseType::name() + ".reinterpret"; + return source_->name(); } private: @@ -88,10 +105,10 @@ private: ReinterpretLocalfunction(const SourceType& source, const SourceGridView& source_grid_view) : BaseType(source.parameter_type()) - , source_(source) + , source_(source.copy_as_grid_function()) , source_grid_view_(source_grid_view) , source_element_search_(source_grid_view_) - , local_source_(source_.local_function()) + , local_source_(source_->local_function()) , source_element_which_contains_complete_target_element_(nullptr) , source_element_which_contains_some_point_of_target_element_(nullptr) , local_source_valid_for_this_point_(false) @@ -214,7 +231,7 @@ private: } } // ... try_to_bind_local_source_for_this_point(...) - const SourceType& source_; + const std::unique_ptr<SourceType> source_; const SourceGridView& source_grid_view_; mutable XT::Grid::EntityInlevelSearch<SourceGridView> source_element_search_; mutable std::unique_ptr<typename SourceType::LocalFunctionType> local_source_; @@ -227,7 +244,7 @@ private: mutable std::vector<DomainType> single_point_; }; // class ReinterpretLocalfunction - const SourceType& source_; + std::unique_ptr<SourceType> source_; const SourceGridView& source_grid_view_; }; // class ReinterpretLocalizableFunction diff --git a/dune/xt/functions/base/sliced.hh b/dune/xt/functions/base/sliced.hh index efaf20a8a7d6e69ee320fedba6621344ee1e1810..2558782933d25b5072b5bcd614520f5a4f4c70d0 100644 --- a/dune/xt/functions/base/sliced.hh +++ b/dune/xt/functions/base/sliced.hh @@ -44,16 +44,18 @@ auto density_times_velocity = XT::Functions::make_sliced_function<d>(u, {1, 2}, auto energy = XT::Functions::make_sliced_function<1>(u, {3}, "energy"); \endcode */ -template <class LF, size_t r> -class SlicedGridFunction<LF, r, 1> : public XT::Functions::GridFunctionInterface<typename LF::E, r, 1, typename LF::R> +template <class GF, size_t r> +class SlicedGridFunction<GF, r, 1> : public XT::Functions::GridFunctionInterface<typename GF::E, r, 1, typename GF::R> { - static_assert(is_grid_function<LF>::value, ""); - static_assert(r <= LF::r, "Does not make sense!"); - using BaseType = XT::Functions::GridFunctionInterface<typename LF::E, r, 1, typename LF::R>; + static_assert(is_grid_function<GF>::value, ""); + static_assert(r <= GF::r, "Does not make sense!"); - class SlicedLocalFunction : public XT::Functions::ElementFunctionInterface<typename LF::E, r, 1, typename LF::R> + using ThisType = SlicedGridFunction; + using BaseType = XT::Functions::GridFunctionInterface<typename GF::E, r, 1, typename GF::R>; + + class SlicedLocalFunction : public XT::Functions::ElementFunctionInterface<typename GF::E, r, 1, typename GF::R> { - using BaseType = XT::Functions::ElementFunctionInterface<typename LF::E, r, 1, typename LF::R>; + using BaseType = XT::Functions::ElementFunctionInterface<typename GF::E, r, 1, typename GF::R>; public: using typename BaseType::DerivativeRangeReturnType; @@ -63,10 +65,10 @@ class SlicedGridFunction<LF, r, 1> : public XT::Functions::GridFunctionInterface using typename BaseType::RangeReturnType; using typename BaseType::RangeType; - - SlicedLocalFunction(const LF& function, const std::array<size_t, r>& dims) - : BaseType() - , local_function_(function.local_function()) + SlicedLocalFunction(const GF& function, const std::array<size_t, r>& dims) + : BaseType(function.parameter_type()) + , function_(function.copy_as_grid_function()) + , local_function_(function_->local_function()) , dims_(dims) {} @@ -98,39 +100,60 @@ class SlicedGridFunction<LF, r, 1> : public XT::Functions::GridFunctionInterface } private: - std::unique_ptr<typename LF::LocalFunctionType> local_function_; - const std::array<size_t, r>& dims_; + std::unique_ptr<GridFunctionInterface<typename GF::E, GF::r, GF::rC, typename GF::R>> function_; + std::unique_ptr<typename GF::LocalFunctionType> local_function_; + const std::array<size_t, r> dims_; }; // class SlicedLocalFunction public: - using typename BaseType::ElementType; + using typename BaseType::E; using typename BaseType::LocalFunctionType; - SlicedGridFunction(const LF& function, const std::array<size_t, r>& dims, const std::string& nm = "") - : function_(function) + SlicedGridFunction(const GF& function, const std::array<size_t, r>& dims, const std::string& nm = "") + : BaseType(function.parameter_type()) + , function_(function.copy_as_grid_function()) , dims_(dims) , name_(nm) { for (size_t ii = 0; ii < r; ++ii) - if (dims_[ii] >= LF::r) + if (dims_[ii] >= GF::r) DUNE_THROW(InvalidStateException, - "LF::r = " << LF::r << "\n " + "GF::r = " << GF::r << "\n " << "r = " << r << "\n " << "dims[" << ii << "] = " << dims_[ii]); } + SlicedGridFunction(const ThisType& other) + : BaseType(other) + , function_(other.function_->copy_as_grid_function()) + {} + + SlicedGridFunction(ThisType&&) = default; + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } std::string name() const override final { - return name_.empty() ? "sliced " + function_.name() : name_; + return name_.empty() ? "sliced " + function_->name() : name_; } std::unique_ptr<LocalFunctionType> local_function() const override final { - return std::make_unique<SlicedLocalFunction>(function_, dims_); + return std::make_unique<SlicedLocalFunction>(*function_, dims_); } private: - const LF& function_; + std::unique_ptr<GridFunctionInterface<typename GF::E, GF::r, GF::rC, typename GF::R>> function_; const std::array<size_t, r> dims_; const std::string& name_; }; // class SlicedGridFunction diff --git a/dune/xt/functions/base/transformed.hh b/dune/xt/functions/base/transformed.hh index 5df43f34df4dd11312d2531bbd085025fe3b082e..a9a527edc8747e6dac2b09e963f2f89946d80f5b 100644 --- a/dune/xt/functions/base/transformed.hh +++ b/dune/xt/functions/base/transformed.hh @@ -49,16 +49,18 @@ const auto to_primitive = [&](const auto& conservative_variables) { auto u_primitive = XT::Functions::make_transformed_function<d + 2, 1, R>(u_conservative, to_primitive); \endcode */ -template <class LF, size_t r = LF::r, size_t rC = LF::rC, class R = typename LF::R> -class TransformedGridFunction : public XT::Functions::GridFunctionInterface<typename LF::E, r, rC, R> +template <class GF, size_t r = GF::r, size_t rC = GF::rC, class R = typename GF::R> +class TransformedGridFunction : public XT::Functions::GridFunctionInterface<typename GF::E, r, rC, R> { - static_assert(is_grid_function<LF>::value, ""); - using BaseType = XT::Functions::GridFunctionInterface<typename LF::E, r, rC, R>; + static_assert(is_grid_function<GF>::value, ""); - class TransformedLocalFunction : public XT::Functions::ElementFunctionInterface<typename LF::E, r, rC, R> + using ThisType = TransformedGridFunction; + using BaseType = XT::Functions::GridFunctionInterface<typename GF::E, r, rC, R>; + + class TransformedLocalFunction : public XT::Functions::ElementFunctionInterface<typename GF::E, r, rC, R> { - using BaseType = XT::Functions::ElementFunctionInterface<typename LF::E, r, rC, R>; - using UntransformedLocalFunctionType = typename LF::LocalFunctionType; + using BaseType = XT::Functions::ElementFunctionInterface<typename GF::E, r, rC, R>; + using UntransformedLocalFunctionType = typename GF::LocalFunctionType; public: using UntransformedRangeType = typename UntransformedLocalFunctionType::RangeType; @@ -70,9 +72,10 @@ class TransformedGridFunction : public XT::Functions::GridFunctionInterface<type using typename BaseType::RangeType; using Transformation = std::function<RangeType(const UntransformedRangeType&)>; - TransformedLocalFunction(const LF& function, const Transformation& transformation) - : BaseType() - , local_function_(function.local_function()) + TransformedLocalFunction(const GF& function, const Transformation& transformation) + : BaseType(function.paramter_type()) + , function_(function.copy_as_grid_function()) + , local_function_(function_->local_function()) , transformation_(transformation) {} @@ -100,6 +103,7 @@ class TransformedGridFunction : public XT::Functions::GridFunctionInterface<type } private: + std::unique_ptr<GridFunctionInterface<typename GF::E, GF::r, GF::rC, typename GF::R>> function_; std::unique_ptr<UntransformedLocalFunctionType> local_function_; const Transformation& transformation_; }; // class TransformedLocalFunction @@ -110,17 +114,39 @@ public: using UntransformedRangeType = typename TransformedLocalFunction::UntransformedRangeType; using TransformedRangeType = typename TransformedLocalFunction::RangeType; - TransformedGridFunction(const LF& f, + TransformedGridFunction(const GF& func, std::function<TransformedRangeType(const UntransformedRangeType&)> transformation, const std::string& nm = "") - : function_(f) + : BaseType(func.parameter_type()) + , function_(func.copy_as_grid_function()) , transformation_(transformation) - , name_(nm) + , name_(nm.empty() ? "transformed " + function_.name() : nm) + {} + + TransformedGridFunction(const ThisType& other) + : BaseType(other) + , function_(other.function_->copy_as_grid_function()) + , transformation_(other.transformation_) + , name_(other.name_) {} + TransformedGridFunction(ThisType&&) = default; + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } std::string name() const override final { - return name_.empty() ? "transformed " + function_.name() : name_; + return name_; } std::unique_ptr<LocalFunctionType> local_function() const override final @@ -129,7 +155,7 @@ public: } private: - const LF& function_; + std::unique_ptr<GridFunctionInterface<typename GF::E, GF::r, GF::rC, typename GF::R>> function_; const typename TransformedLocalFunction::Transformation transformation_; const std::string name_; }; // class TransformedGridFunction diff --git a/dune/xt/functions/base/visualization.hh b/dune/xt/functions/base/visualization.hh index a621b9dad8a7110432fbca796cb33a4802758bc4..7b4bb2358bcf45c4aee42bddcc4352e5bdf5fa44 100644 --- a/dune/xt/functions/base/visualization.hh +++ b/dune/xt/functions/base/visualization.hh @@ -314,4 +314,6 @@ private: } // namespace XT } // namespace Dune +#include <dune/xt/functions/interfaces/grid-function.hh> + #endif // DUNE_XT_FUNCTIONS_VISUALIZATION_HH diff --git a/dune/xt/functions/checkerboard.hh b/dune/xt/functions/checkerboard.hh index 499fb09014cb4d7fe75cbf48f9de301bfc6fad36..c3aae488e4a4cb9ec8907d33c3d1612d4239fb58 100644 --- a/dune/xt/functions/checkerboard.hh +++ b/dune/xt/functions/checkerboard.hh @@ -15,7 +15,6 @@ #define DUNE_XT_FUNCTIONS_CHECKERBOARD_HH #include <dune/xt/common/configuration.hh> - #include <dune/xt/functions/interfaces/grid-function.hh> namespace Dune { @@ -50,7 +49,7 @@ class CheckerboardFunction : public GridFunctionInterface<E, r, rC, R> LocalCheckerboardFunction(const DomainType& lower_left, const DomainType& upper_right, const FieldVector<size_t, domain_dim>& num_elements, - std::vector<RangeType>& values) + std::shared_ptr<std::vector<RangeType>> values) : InterfaceType() , lower_left_(lower_left) , upper_right_(upper_right) @@ -64,7 +63,7 @@ class CheckerboardFunction : public GridFunctionInterface<E, r, rC, R> current_value_ = 0; if (is_in_checkerboard(element)) { const size_t subdomain = find_subdomain(element); - current_value_ = values_[subdomain]; + current_value_ = (*values_)[subdomain]; } } @@ -126,7 +125,7 @@ class CheckerboardFunction : public GridFunctionInterface<E, r, rC, R> const DomainType lower_left_; const DomainType upper_right_; const FieldVector<size_t, domain_dim> num_elements_; - const std::vector<RangeType>& values_; + const std::shared_ptr<std::vector<RangeType>> values_; RangeType current_value_; }; // class LocalCheckerboardFunction @@ -158,12 +157,12 @@ public: CheckerboardFunction(const DomainType& lower_left, const DomainType& upper_right, const FieldVector<size_t, domain_dim>& num_elements, - const std::vector<RangeType>& values, - const std::string nm = "checkerboard") + std::shared_ptr<std::vector<RangeType>> values, + const std::string nm = "CheckerboardFunction") : lower_left_(lower_left) , upper_right_(upper_right) , num_elements_(num_elements) - , values_(new std::vector<RangeType>(values)) + , values_(values) , name_(nm) { #ifndef NDEBUG @@ -183,12 +182,30 @@ public: #endif } // CheckerboardFunction(...) + CheckerboardFunction(const DomainType& lower_left, + const DomainType& upper_right, + const FieldVector<size_t, domain_dim>& num_elements, + const std::vector<RangeType>& values, + const std::string nm = "CheckerboardFunction") + : CheckerboardFunction(lower_left, upper_right, num_elements, std::make_shared<std::vector<RangeType>>(values), nm) + {} + CheckerboardFunction(const ThisType& other) = default; + CheckerboardFunction(ThisType&& source) = default; - ThisType& operator=(const ThisType& other) = delete; - ThisType& operator=(ThisType&& source) = delete; +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } std::string name() const override { return name_; @@ -196,7 +213,7 @@ public: std::unique_ptr<LocalFunctionType> local_function() const override final { - return std::make_unique<LocalCheckerboardFunction>(lower_left_, upper_right_, num_elements_, *values_); + return std::make_unique<LocalCheckerboardFunction>(lower_left_, upper_right_, num_elements_, values_); } size_t subdomain(const ElementType& element) const diff --git a/dune/xt/functions/constant.hh b/dune/xt/functions/constant.hh index 772d03b48036631e2e58d6e574633696903bb753..708d22322021094419cf427aeb74d7df11b80dff 100644 --- a/dune/xt/functions/constant.hh +++ b/dune/xt/functions/constant.hh @@ -26,10 +26,10 @@ namespace XT { namespace Functions { -template <size_t d, size_t r = 1, size_t rC = 1, class RangeField = double> -class ConstantFunction : public FunctionInterface<d, r, rC, RangeField> +template <size_t d, size_t r = 1, size_t rC = 1, class R = double> +class ConstantFunction : public FunctionInterface<d, r, rC, R> { - using BaseType = FunctionInterface<d, r, rC, RangeField>; + using BaseType = FunctionInterface<d, r, rC, R>; using ThisType = ConstantFunction; public: @@ -57,13 +57,25 @@ public: explicit ConstantFunction(const RangeReturnType& value, const std::string nm = "") : value_(value) , name_(nm.empty() ? ((r == 1 && rC == 1) ? std::string("ConstantFunction(" + Common::to_string(value) + ")") - : static_id()) + : "ConstantFunction") : nm) {} -#if !DUNE_XT_WITH_PYTHON_BINDINGS - ConstantFunction(const ThisType& other) = default; -#endif + ConstantFunction(const ThisType&) = default; + + ConstantFunction(ThisType&) = default; + +private: + ThisType* copy_as_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } int order(const XT::Common::Parameter& /*param*/ = {}) const override final { @@ -92,45 +104,40 @@ public: }; // class ConstantFunction -template <class Element, size_t rangeDim = 1, size_t rangeDimCols = 1, class RangeField = double> -class ConstantGridFunction : public GridFunctionInterface<Element, rangeDim, rangeDimCols, RangeField> +template <class E, size_t r = 1, size_t rC = 1, class R = double> +class ConstantGridFunction : public FunctionAsGridFunctionWrapper<E, r, rC, R> { - using BaseType = GridFunctionInterface<Element, rangeDim, rangeDimCols, RangeField>; + using ThisType = ConstantGridFunction; + using BaseType = FunctionAsGridFunctionWrapper<E, r, rC, R>; public: using typename BaseType::LocalFunctionType; - ConstantGridFunction(const typename LocalFunctionType::RangeReturnType constant, - const std::string name_in = static_id()) - : constant_function_(constant, name_in) - , constant_grid_function_(constant_function_) + ConstantGridFunction(const typename LocalFunctionType::RangeReturnType value, const std::string nm = "") + : BaseType(ConstantFunction<E::dimension, r, rC, R>( + value, + nm.empty() ? ((r == 1 && rC == 1) ? std::string("ConstantGridFunction(" + Common::to_string(value) + ")") + : "ConstantGridFunction") + : nm)) {} - - static std::string static_id() - { - return "dune.xt.functions.constantgridfunction"; - } - - std::unique_ptr<LocalFunctionType> local_function() const override final + std::unique_ptr<ThisType> copy_as_grid_function() const { - return constant_grid_function_.local_function(); + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); } - std::string name() const override final +private: + ThisType* copy_as_grid_function_impl() const override { - return constant_function_.name(); + return new ThisType(*this); } -private: - ConstantFunction<BaseType::domain_dim, rangeDim, rangeDimCols, RangeField> constant_function_; - FunctionAsGridFunctionWrapper<Element, rangeDim, rangeDimCols, RangeField> constant_grid_function_; }; // class ConstantGridFunction -template <class Element, size_t stateDim, size_t rangeDim = 1, size_t rangeDimCols = 1, class RangeField = double> -class ConstantFluxFunction : public FluxFunctionInterface<Element, stateDim, rangeDim, rangeDimCols, RangeField> +template <class E, size_t stateDim, size_t r = 1, size_t rC = 1, class R = double> +class ConstantFluxFunction : public FluxFunctionInterface<E, stateDim, r, rC, R> { - using BaseType = FluxFunctionInterface<Element, stateDim, rangeDim, rangeDimCols, RangeField>; + using BaseType = FluxFunctionInterface<E, stateDim, r, rC, R>; public: using typename BaseType::LocalFunctionType; @@ -162,8 +169,8 @@ public: } private: - ConstantFunction<stateDim, rangeDim, rangeDimCols, RangeField> constant_function_; - StateFunctionAsFluxFunctionWrapper<Element, stateDim, rangeDim, rangeDimCols, RangeField> constant_flux_function_; + ConstantFunction<stateDim, r, rC, R> constant_function_; + StateFunctionAsFluxFunctionWrapper<E, stateDim, r, rC, R> constant_flux_function_; }; // class ConstantGridFunction diff --git a/dune/xt/functions/derivatives.hh b/dune/xt/functions/derivatives.hh index 497f8a2071da0cdc85e266d1e9bb1a9c12e97e2e..8d2c1ba328126f0852c941c76fb22a842f752877 100644 --- a/dune/xt/functions/derivatives.hh +++ b/dune/xt/functions/derivatives.hh @@ -13,7 +13,9 @@ #define DUNE_XT_FUNCTIONS_DERIVATIVES_HH #include <dune/xt/functions/base/derivatives-of-element-functions.hh> +#include <dune/xt/functions/base/derivatives-of-grid-functions.hh> #include <dune/xt/functions/interfaces/element-functions.hh> +#include <dune/xt/functions/interfaces/grid-function.hh> namespace Dune { namespace XT { @@ -27,13 +29,33 @@ DivergenceElementFunction<ElementFunctionInterface<E, E::dimension, 1, R>> return DivergenceElementFunction<ElementFunctionInterface<E, E::dimension, 1, R>>(func); } +template <class E, class R> +DivergenceElementFunction<ElementFunctionInterface<E, E::dimension, 1, R>> +divergence(const ElementFunctionInterface<E, E::dimension, 1, R>& func) +{ + return DivergenceElementFunction<ElementFunctionInterface<E, E::dimension, 1, R>>(func); +} + +template <class E, class R> +DivergenceGridFunction<GridFunctionInterface<E, E::dimension, 1, R>> +divergence(const GridFunctionInterface<E, E::dimension, 1, R>& func) +{ + return DivergenceGridFunction<GridFunctionInterface<E, E::dimension, 1, R>>(func); +} + template <class E, class R> -GradientElementFunction<ElementFunctionInterface<E, 1, 1, R>> gradient(ElementFunctionInterface<E, 1, 1, R>& func) +GradientElementFunction<ElementFunctionInterface<E, 1, 1, R>> gradient(const ElementFunctionInterface<E, 1, 1, R>& func) { return GradientElementFunction<ElementFunctionInterface<E, 1, 1, R>>(func); } +template <class E, class R> +GradientGridFunction<GridFunctionInterface<E, 1, 1, R>> gradient(const GridFunctionInterface<E, 1, 1, R>& func) +{ + return GradientGridFunction<GridFunctionInterface<E, 1, 1, R>>(func); +} + } // namespace Functions } // namespace XT diff --git a/dune/xt/functions/elementwise-diameter.hh b/dune/xt/functions/elementwise-diameter.hh new file mode 100644 index 0000000000000000000000000000000000000000..16917840edbf78764de1d51f554c8f4490dd5a49 --- /dev/null +++ b/dune/xt/functions/elementwise-diameter.hh @@ -0,0 +1,114 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#ifndef DUNE_XT_FUNCTIONS_ELEMENTWISE_DIAMETER_HH +#define DUNE_XT_FUNCTIONS_ELEMENTWISE_DIAMETER_HH + +#include <dune/xt/functions/interfaces/grid-function.hh> + +namespace Dune { +namespace XT { +namespace Functions { + + +template <class E> +class ElementwiseDiameterFunction : public GridFunctionInterface<E> +{ + using ThisType = ElementwiseDiameterFunction; + using BaseType = GridFunctionInterface<E>; + + class LocalFunction : public XT::Functions::ElementFunctionInterface<E> + { + using BaseType = XT::Functions::ElementFunctionInterface<E>; + + public: + using typename BaseType::DerivativeRangeReturnType; + using typename BaseType::DomainType; + using typename BaseType::ElementType; + using typename BaseType::RangeReturnType; + + LocalFunction() + : BaseType() + , diameter_(0) + {} + + protected: + void post_bind(const ElementType& element) override final + { + diameter_ = Grid::diameter(element); + } + + public: + int order(const XT::Common::Parameter& /*param*/ = {}) const override final + { + return 0; + } + + RangeReturnType evaluate(const DomainType& /*xx*/, const XT::Common::Parameter& /*param*/ = {}) const override final + { + return diameter_; + } + + DerivativeRangeReturnType jacobian(const DomainType& /*xx*/, + const XT::Common::Parameter& /*param*/ = {}) const override final + { + return DerivativeRangeReturnType(); + } + + private: + double diameter_; + }; // class LocalFunction + +public: + using BaseType::d; + using BaseType::r; + using BaseType::rC; + using typename BaseType::LocalFunctionType; + + ElementwiseDiameterFunction(const std::string nm = "ElementwiseDiameterFunction") + : BaseType() + , name_(nm) + {} + + ElementwiseDiameterFunction(const ThisType&) = default; + + ElementwiseDiameterFunction(ThisType&&) = default; + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } + std::unique_ptr<LocalFunctionType> local_function() const override final + { + return std::make_unique<LocalFunction>(); + } + + std::string name() const override final + { + return name_; + } + +private: + std::string name_; +}; // class ElementwiseDiameterFunction + + +} // namespace Functions +} // namespace XT +} // namespace Dune + +#endif // DUNE_XT_FUNCTIONS_ELEMENTWISE_DIAMETER_HH diff --git a/dune/xt/functions/elementwise-minimum.hh b/dune/xt/functions/elementwise-minimum.hh new file mode 100644 index 0000000000000000000000000000000000000000..b36be48d62c5bb152b7d8572c8f405ea0966a5d3 --- /dev/null +++ b/dune/xt/functions/elementwise-minimum.hh @@ -0,0 +1,208 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#ifndef DUNE_XT_FUNCTIONS_ELEMENTWISE_MINIMUM_HH +#define DUNE_XT_FUNCTIONS_ELEMENTWISE_MINIMUM_HH + +#include <dune/geometry/quadraturerules.hh> + +#include <dune/xt/la/eigen-solver.hh> +#include <dune/xt/functions/interfaces/grid-function.hh> +#include <dune/xt/functions/grid-function.hh> +#include <dune/xt/functions/type_traits.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace internal { + + +template <class FunctionType> +class ElementwiseMinimumFunctionHelper +{ + static_assert(is_element_function<FunctionType>::value, ""); + +public: + static const constexpr size_t d = FunctionType::d; + static const constexpr size_t r = FunctionType::r; + static const constexpr size_t rC = FunctionType::rC; + using E = typename FunctionType::E; + using R = typename FunctionType::R; + using DomainType = Dune::FieldVector<double, d>; + + template <size_t r_ = r, size_t rC_ = rC, bool anything = true> + struct dim_switch + {}; + + template <bool anything> + struct dim_switch<1, 1, anything> + { + static R compute(const FunctionType& func, const int order, const XT::Common::Parameter& param) + { + // approximate minimum over the element (evaluate at some points) + double min = std::numeric_limits<double>::max(); + for (auto&& quadrature_point : QuadratureRules<double, d>::rule(func.element().type(), order)) + min = std::min(min, func.evaluate(quadrature_point.position(), param)[0]); + return min; + } + }; + + template <size_t r_, bool anything> + struct dim_switch<r_, r_, anything> + { + static R compute(const FunctionType& func, const int order, const XT::Common::Parameter& param) + { + // approximate minimum eigenvalue over the element (evaluate at some points) + double min_EV = std::numeric_limits<double>::max(); + for (auto&& quadrature_point : QuadratureRules<double, d>::rule(func.element().type(), order)) { + auto value = func.evaluate(quadrature_point.position(), param); + auto eigen_solver = + XT::LA::make_eigen_solver(value, + {{"type", XT::LA::EigenSolverOptions<decltype(value)>::types().at(0)}, + {"assert_positive_eigenvalues", "1e-15"}}); + min_EV = std::min(min_EV, eigen_solver.min_eigenvalues(1).at(0)); + } + return min_EV; + } + }; + +public: + static R compute(const FunctionType& func, const int order, const XT::Common::Parameter& param) + { + return dim_switch<>::compute(func, order, param); + } +}; // class ElementwiseMinimumFunctionHelper + + +} // namespace internal + + +/// \todo Consider searching the elements corners! +template <class SomeFunction> +class ElementwiseMinimumFunction : public GridFunctionInterface<typename SomeFunction::E> +{ + static_assert(is_function<SomeFunction>::value || is_grid_function<SomeFunction>::value, ""); + + using ThisType = ElementwiseMinimumFunction; + using BaseType = GridFunctionInterface<typename SomeFunction::E>; + + static const constexpr size_t r_ = SomeFunction::r; + static const constexpr size_t rC_ = SomeFunction::rC; + +public: + using BaseType::r; + using BaseType::rC; + using typename BaseType::E; + using typename BaseType::LocalFunctionType; + using typename BaseType::R; + +private: + static_assert(r == rC, ""); + + class LocalFunction : public XT::Functions::ElementFunctionInterface<E> + { + using BaseType = XT::Functions::ElementFunctionInterface<E>; + + public: + using typename BaseType::DerivativeRangeReturnType; + using typename BaseType::DomainType; + using typename BaseType::ElementType; + using typename BaseType::RangeReturnType; + + LocalFunction(const GridFunctionInterface<E, r_, rC_, R>& some_func, const int search_quadrature_order) + : BaseType() + , some_func_(some_func.copy_as_grid_function()) + , some_lf_(some_func_->local_function()) + , search_quadrature_order_(search_quadrature_order) + , min_(0) + {} + + protected: + void post_bind(const ElementType& element) override final + { + some_lf_->bind(element); + min_ = internal::ElementwiseMinimumFunctionHelper<typename SomeFunction::LocalFunctionType>::compute( + *some_lf_, search_quadrature_order_, {}); + } + + public: + int order(const XT::Common::Parameter& /*param*/ = {}) const override final + { + return 0; + } + + RangeReturnType evaluate(const DomainType& /*xx*/, const XT::Common::Parameter& /*param*/ = {}) const override final + { + return min_; + } + + private: + std::unique_ptr<GridFunctionInterface<E, r_, rC_, R>> some_func_; + std::unique_ptr<typename GridFunctionInterface<E, r_, rC_, R>::LocalFunctionType> some_lf_; + const int search_quadrature_order_; + double min_; + }; // class LocalFunction + +public: + ElementwiseMinimumFunction(GridFunction<E, r_, rC_> some_func, + const int search_quadrature_order, + const std::string nm = "ElementwiseMinimumFunction") + : BaseType() + , some_func_(some_func.copy_as_grid_function()) + , search_quadrature_order_(search_quadrature_order) + , name_(nm) + { + DUNE_THROW_IF(!some_func_->parameter_type().empty(), + Exceptions::parameter_error, + "Not available for parametric functions yet!"); + } + + ElementwiseMinimumFunction(const ThisType& other) + : BaseType(other) + , some_func_(other.some_func_->copy_as_grid_function()) + , search_quadrature_order_(other.search_quadrature_order_) + , name_(other.name_) + {} + + ElementwiseMinimumFunction(ThisType&&) = default; + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } + std::unique_ptr<LocalFunctionType> local_function() const override final + { + return std::make_unique<LocalFunction>(*some_func_, search_quadrature_order_); + } + + std::string name() const override final + { + return name_; + } + +private: + std::unique_ptr<GridFunctionInterface<E, r_, rC_, R>> some_func_; + const int search_quadrature_order_; + const std::string name_; +}; // class ElementwiseMinimumFunction + + +} // namespace Functions +} // namespace XT +} // namespace Dune + +#endif // DUNE_XT_FUNCTIONS_ELEMENTWISE_MINIMUM_HH diff --git a/dune/xt/functions/exceptions.hh b/dune/xt/functions/exceptions.hh index 4ea3254e980fc0f05e857b11ea3c0a6e7d8141f9..d501e25783fbd44a936145a25f738c5bf33cb5c1 100644 --- a/dune/xt/functions/exceptions.hh +++ b/dune/xt/functions/exceptions.hh @@ -37,6 +37,21 @@ class parameter_error : public Common::Exceptions::parameter_error class spe10_data_file_missing : public Dune::IOError {}; +class element_function_error : public Dune::Exception +{}; + +class combined_error : public Dune::Exception +{}; + +class function_error : public Dune::Exception +{}; + +class grid_function_error : public Dune::Exception +{}; + +class flux_function_error : public Dune::Exception +{}; + } // namespace Exceptions } // namespace Functions diff --git a/dune/xt/functions/expression/base.hh b/dune/xt/functions/expression/base.hh index fbea9ee6cf7b5e1ea597f4b7b8164e8eac09441e..85871cac6d8bbfb6d590bdd2ed560bc2b36572c7 100644 --- a/dune/xt/functions/expression/base.hh +++ b/dune/xt/functions/expression/base.hh @@ -57,12 +57,6 @@ public: using RangeFieldType = RangeField; static constexpr size_t range_dim = rangeDim; - // MathExpressionBase(const std::string var, const std::string expr) - // { - // const std::vector<std::string> expressions(1, expr); - // setup(var, expressions); - // } - MathExpressionBase(const std::string& var, const Common::FieldVector<std::string, range_dim>& exprs) : variable_(var) , expressions_(exprs) @@ -71,8 +65,10 @@ public: } MathExpressionBase(const ThisType& other) + : variable_(other.variable_) + , expressions_(other.expressions_) { - setup(other.variable(), other.expression()); + setup(); } ThisType& operator=(const ThisType& other) @@ -246,17 +242,7 @@ public: setup(other.variables(), other.expressions()); } - ThisType& operator=(const ThisType& other) - { - if (this != &other) { - cleanup(); - originalvars_ = other.originalvars_; - variables_ = std::vector<std::string>(); - expressions_ = std::vector<std::string>(); - setup(other.originalvars_, other.expressions_); - } - return this; - } + DynamicMathExpressionBase(ThisType&&) = default; ~DynamicMathExpressionBase() { diff --git a/dune/xt/functions/expression/default.hh b/dune/xt/functions/expression/default.hh index 359cfefd442bcb0734136f912085c85221d180f8..44be3c15ae719cd54595d43be64760bd75d8785f 100644 --- a/dune/xt/functions/expression/default.hh +++ b/dune/xt/functions/expression/default.hh @@ -108,11 +108,19 @@ public: const Common::FieldVector<Common::FieldMatrix<std::string, rC, d>, r>& gradient_expressions, const size_t ord, const std::string nm = static_id()) - : function_(new MathExpressionFunctionType(variable, matrix_to_vector(expressions))) + : BaseType() + , function_(variable, matrix_to_vector(expressions)) , order_(ord) , name_(nm) { - build_gradients(variable, gradient_expressions); + for (size_t cc = 0; cc < r; ++cc) { + gradients_.emplace_back(std::vector<MathExpressionGradientType>()); + for (size_t rr = 0; rr < rC; ++rr) { + const auto& gradient_expression = gradient_expressions[cc][rr]; + assert(gradient_expression.size() >= d); + gradients_[cc].emplace_back(variable, gradient_expression); + } + } } /** @@ -123,24 +131,38 @@ public: const Common::FieldMatrix<std::string, r, rC>& expressions, const size_t ord, const std::string nm = static_id()) - : function_(new MathExpressionFunctionType(variable, matrix_to_vector(expressions))) + : BaseType() + , function_(variable, matrix_to_vector(expressions)) , order_(ord) , name_(nm) {} - ExpressionFunction(const ThisType& other) = default; - - ThisType& operator=(const ThisType& other) + ExpressionFunction(const ThisType& other) + : BaseType(other) + , function_(other.function_) + , order_(other.order_) + , name_(other.name_) { - if (this != &other) { - function_ = other.function_; - order_ = other.order_; - name_ = other.name_; - gradients_ = other.gradients_; + for (size_t cc = 0; cc < other.gradients_.size(); ++cc) { + gradients_.emplace_back(std::vector<MathExpressionGradientType>()); + for (size_t rr = 0; rr < other.gradients_[cc].size(); ++rr) + gradients_[cc].emplace_back(other.gradients_[cc][rr]); } - return *this; } + ExpressionFunction(ThisType&&) = default; + +private: + ThisType* copy_as_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } std::string name() const override final { return name_; @@ -158,7 +180,7 @@ public: { RangeReturnType ret(0.); Common::FieldVector<RangeFieldType, r * rC> tmp_vector_; - function_->evaluate(point_in_global_coordinates, tmp_vector_); + function_.evaluate(point_in_global_coordinates, tmp_vector_); for (size_t rr = 0; rr < r; ++rr) { auto& retRow = ret[rr]; for (size_t cc = 0; cc < rC; ++cc) { @@ -181,7 +203,7 @@ public: for (size_t cc = 0; cc < r; ++cc) { assert(gradients_[cc].size() == rC); for (size_t rr = 0; rr < rC; ++rr) { - gradients_[cc][rr]->evaluate(point_in_global_coordinates, ret[cc][rr]); + gradients_[cc][rr].evaluate(point_in_global_coordinates, ret[cc][rr]); check_value(point_in_global_coordinates, ret[cc][rr]); } } @@ -198,7 +220,7 @@ public: size_t range = value.size(); bool failure = false; std::string error_type; - for (size_t rr = 0; rr < range; ++rr) { + for (size_t rr = 0; rr < value.size(); ++rr) { if (Common::isnan(value[rr])) { failure = true; error_type = "NaN"; @@ -209,40 +231,27 @@ public: failure = true; error_type = "an unlikely value"; } - if (failure) - DUNE_THROW(Common::Exceptions::internal_error, - "evaluating this function yielded " - << error_type << "!\n" - << "The variable of this function is: " << function_->variable() << "\n" - << "The expression of this function is: " << function_->expression() // at - << "\n" - << "You tried to evaluate it with: point_in_global_coordinates = " - << point_in_global_coordinates << "\n" - << "The result was: " << value[rr] << "\n\n" - << "You can disable this check by defining DUNE_XT_FUNCTIONS_EXPRESSION_DISABLE_CHECKS\n"); + DUNE_THROW_IF(failure, + Common::Exceptions::internal_error, + "evaluating this function yielded " + << error_type << "!\n" + << "The variable of this function is: " << function_.variable() << "\n" + << "The expression of this function is: " << function_.expression() // at + << "\n" + << "You tried to evaluate it with: point_in_global_coordinates = " + << point_in_global_coordinates << "\n" + << "The result was: " << value[rr] << "\n\n" + << "You can disable this check by defining DUNE_XT_FUNCTIONS_EXPRESSION_DISABLE_CHECKS\n"); } // check_value(...) # endif // DUNE_XT_FUNCTIONS_EXPRESSION_DISABLE_CHECKS #endif // NDEBUG } private: - void build_gradients(const std::string& variable, - const Common::FieldVector<Common::FieldMatrix<std::string, rC, d>, r>& gradient_expressions) - { - for (size_t cc = 0; cc < r; ++cc) { - gradients_.emplace_back(std::vector<std::shared_ptr<const MathExpressionGradientType>>()); - for (size_t rr = 0; rr < rC; ++rr) { - const auto& gradient_expression = gradient_expressions[cc][rr]; - assert(gradient_expression.size() >= d); - gradients_[cc].emplace_back(new MathExpressionGradientType(variable, gradient_expression)); - } - } - } // ... build_gradients(...) - - std::shared_ptr<const MathExpressionFunctionType> function_; + MathExpressionFunctionType function_; size_t order_; std::string name_; - std::vector<std::vector<std::shared_ptr<const MathExpressionGradientType>>> gradients_; + std::vector<std::vector<MathExpressionGradientType>> gradients_; }; // class ExpressionFunction @@ -303,11 +312,13 @@ public: const Common::FieldMatrix<std::string, r, d>& gradient_expressions, const size_t ord, const std::string nm = static_id()) - : function_(new MathExpressionFunctionType(variable, expressions)) + : BaseType() + , function_(variable, expressions) , order_(ord) , name_(nm) { - build_gradients(variable, gradient_expressions); + for (size_t rr = 0; rr < r; ++rr) + gradients_.emplace_back(new MathExpressionGradientType(variable, gradient_expressions[rr])); } /** @@ -318,26 +329,35 @@ public: const Common::FieldVector<std::string, r>& expressions, const size_t ord, const std::string nm = static_id()) - : function_(new MathExpressionFunctionType(variable, expressions)) + : BaseType() + , function_(variable, expressions) , order_(ord) , name_(nm) {} -#if !DUNE_XT_WITH_PYTHON_BINDINGS - ExpressionFunction(const ThisType& other) = default; -#endif + ExpressionFunction(const ThisType& other) + : BaseType() + , function_(other.function_) + , order_(other.order_) + , name_(other.name_) + { + for (size_t ii = 0; ii < other.gradients_.size(); ++ii) + gradients_.emplace_back(new MathExpressionGradientType(*other.gradients_[ii])); + } - ThisType& operator=(const ThisType& other) + ExpressionFunction(ThisType&&) = default; + +private: + ThisType* copy_as_function_impl() const override { - if (this != &other) { - function_ = other.function_; - order_ = other.order_; - name_ = other.name_; - gradients_ = other.gradients_; - } - return *this; + return new ThisType(*this); } +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } std::string name() const override final { return name_; @@ -354,7 +374,7 @@ public: const Common::Parameter& /*param*/ = {}) const override final { RangeReturnType ret(0.); - function_->evaluate(point_in_global_coordinates, ret); + function_.evaluate(point_in_global_coordinates, ret); check_value(point_in_global_coordinates, ret); return ret; } // ... evaluate(...) @@ -384,7 +404,7 @@ private: size_t range = value.size(); bool failure = false; std::string error_type; - for (size_t rr = 0; rr < range; ++rr) { + for (size_t rr = 0; rr < value.size(); ++rr) { if (Common::isnan(value[rr])) { failure = true; error_type = "NaN"; @@ -395,38 +415,26 @@ private: failure = true; error_type = "an unlikely value"; } - if (failure) - DUNE_THROW(Common::Exceptions::internal_error, - "evaluating this function yielded " - << error_type << "!\n" - << "The variable of this function is: " << function_->variable() << "\n" - << "The expression of this function is: " << function_->expression() // at - << "\n" - << "You tried to evaluate it with: point_in_global_coordinates = " - << point_in_global_coordinates << "\n" - << "The result was: " << value[rr] << "\n\n" - << "You can disable this check by defining DUNE_XT_FUNCTIONS_EXPRESSION_DISABLE_CHECKS\n"); + DUNE_THROW_IF(failure, + Common::Exceptions::internal_error, + "evaluating this function yielded " + << error_type << "!\n" + << "The variable of this function is: " << function_.variable() << "\n" + << "The expression of this function is: " << function_.expression() << "\n" + << "You tried to evaluate it with: point_in_global_coordinates = " + << point_in_global_coordinates << "\n" + << "The result was: " << value[rr] << "\n\n" + << "You can disable this check by defining DUNE_XT_FUNCTIONS_EXPRESSION_DISABLE_CHECKS\n"); } // check_value(...) # endif // DUNE_XT_FUNCTIONS_EXPRESSION_DISABLE_CHECKS #endif // NDEBUG - } + } // ... check_value(...) private: - void build_gradients(const std::string& variable, const Common::FieldMatrix<std::string, r, d>& gradient_expressions) - { - for (size_t rr = 0; rr < r; ++rr) - gradients_.emplace_back(new MathExpressionGradientType(variable, gradient_expressions[rr])); - } - - void build_gradients(const std::string& variable, const Common::FieldVector<std::string, d>& gradient_expression) - { - gradients_.emplace_back(new MathExpressionGradientType(variable, gradient_expression)); - } - - std::shared_ptr<const MathExpressionFunctionType> function_; + MathExpressionFunctionType function_; size_t order_; std::string name_; - std::vector<std::shared_ptr<const MathExpressionGradientType>> gradients_; + std::vector<std::shared_ptr<MathExpressionGradientType>> gradients_; }; // class ExpressionFunction diff --git a/dune/xt/functions/expression/parametric.hh b/dune/xt/functions/expression/parametric.hh index 1711475741c8b0a9d5f44d08e112cb32fb453b4c..7d99457c5d77f69854042b61c78a8b2f8af0a4f0 100644 --- a/dune/xt/functions/expression/parametric.hh +++ b/dune/xt/functions/expression/parametric.hh @@ -39,17 +39,21 @@ public: template <size_t d, size_t r, class R> class ParametricExpressionFunction<d, r, 1, R> : public FunctionInterface<d, r, 1, R> { + using ThisType = ParametricExpressionFunction; using BaseType = FunctionInterface<d, r, 1, R>; - using typename BaseType::D; - using ActualFunctionType = DynamicMathExpressionBase<D, R, r>; public: using BaseType::domain_dim; using BaseType::range_dim; + using typename BaseType::D; using typename BaseType::DerivativeRangeReturnType; using typename BaseType::DomainType; using typename BaseType::RangeReturnType; +private: + using ActualFunctionType = DynamicMathExpressionBase<D, R, r>; + +public: static std::string static_id() { return BaseType::static_id() + ".parametricexpression"; @@ -60,20 +64,19 @@ public: const Common::FieldVector<std::string, r>& expressions, const size_t ord = 0, const std::string nm = static_id()) - : order_(ord) + : BaseType(param_type) + , order_(ord) , name_(nm) - , param_type_(param_type) , num_parameter_variables_(0) { - if (variable.empty()) - DUNE_THROW(Common::Exceptions::wrong_input_given, "Given variable must not be empty!"); + DUNE_THROW_IF(variable.empty(), Common::Exceptions::wrong_input_given, "Given variable must not be empty!"); std::vector<std::string> variables; std::vector<std::string> expression; for (size_t rr = 0; rr < r; ++rr) expression.emplace_back(expressions[rr]); - for (const auto& key : param_type_.keys()) { - const size_t value_size = param_type_.get(key); + for (const auto& key : this->parameter_type().keys()) { + const size_t value_size = this->parameter_type().get(key); if (value_size == 1) { variables.push_back(key); ++num_parameter_variables_; @@ -86,27 +89,39 @@ public: } for (size_t ii = 0; ii < domain_dim; ++ii) variables.push_back(variable + "[" + Common::to_string(ii) + "]"); - function_ = std::make_shared<ActualFunctionType>(variables, expression); + function_ = std::make_unique<ActualFunctionType>(variables, expression); } - std::string name() const override final + ParametricExpressionFunction(const ThisType& other) + : BaseType(other) + , order_(other.order_) + , name_(other.name_) + , num_parameter_variables_(other.num_parameter_variables_) + , function_(new ActualFunctionType(*other.function_)) + {} + + ParametricExpressionFunction(ThisType&&) = default; + +private: + ThisType* copy_as_function_impl() const override { - return name_; + return new ThisType(*this); } - int order(const Common::Parameter& /*param*/ = {}) const override final +public: + std::unique_ptr<ThisType> copy_as_function() const { - return static_cast<int>(order_); + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); } - bool is_parametric() const override final + std::string name() const override final { - return !param_type_.empty(); + return name_; } - const Common::ParameterType& parameter_type() const override final + int order(const Common::Parameter& /*param*/ = {}) const override final { - return param_type_; + return static_cast<int>(order_); } RangeReturnType evaluate(const DomainType& point_in_global_coordinates, @@ -114,16 +129,16 @@ public: { RangeReturnType ret(0.); Common::Parameter parsed_param; - if (!param_type_.empty()) { + if (!this->parameter_type().empty()) { parsed_param = this->parse_parameter(param); - if (parsed_param.type() != param_type_) + if (parsed_param.type() != this->parameter_type()) DUNE_THROW(Common::Exceptions::parameter_error, - "parameter_type(): " << param_type_ << "\n " + "parameter_type(): " << this->parameter_type() << "\n " << "param.type(): " << param.type()); } DynamicVector<D> args(num_parameter_variables_ + domain_dim); size_t II = 0; - for (const auto& key : param_type_.keys()) { + for (const auto& key : this->parameter_type().keys()) { for (const auto& value : parsed_param.get(key)) { args[II] = value; ++II; @@ -176,9 +191,8 @@ public: private: size_t order_; std::string name_; - Common::ParameterType param_type_; size_t num_parameter_variables_; - std::shared_ptr<const ActualFunctionType> function_; + std::unique_ptr<ActualFunctionType> function_; }; // class ParametricExpressionFunction diff --git a/dune/xt/functions/flattop.hh b/dune/xt/functions/flattop.hh index edef22418e0a95d4a88d237a8f569bb8735ef4d4..53921bf4d70e90d53c2f95541b3ca85833872b62 100644 --- a/dune/xt/functions/flattop.hh +++ b/dune/xt/functions/flattop.hh @@ -73,8 +73,8 @@ public: FlatTopFunction(const DomainType& lower_left, const DomainType& upper_right, const DomainType& boundary_layer, - const RangeReturnType& value = defaults().template get<RangeReturnType>("value"), - const std::string name_in = defaults().template get<std::string>("name")) + const RangeReturnType& value = RangeReturnType(1), + const std::string name_in = "FlatTopFunction") : lower_left_(lower_left) , upper_right_(upper_right) , boundary_layer_(boundary_layer) @@ -84,11 +84,21 @@ public: check_input(); } - FlatTopFunction(const ThisType& other) = default; + FlatTopFunction(const ThisType&) = default; - ThisType& operator=(const ThisType& other) = delete; + FlatTopFunction(ThisType&&) = default; - virtual ~FlatTopFunction() {} +private: + ThisType* copy_as_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } std::string name() const override final { diff --git a/dune/xt/functions/generic/function.hh b/dune/xt/functions/generic/function.hh index 79f572678df1993ac12c6a2f66ead2bd74c98911..e8e6b77a18dfa44934d9b118a7be63e31534c50a 100644 --- a/dune/xt/functions/generic/function.hh +++ b/dune/xt/functions/generic/function.hh @@ -33,6 +33,7 @@ namespace Functions { template <size_t domain_dim, size_t range_dim = 1, size_t range_dim_cols = 1, class RangeField = double> class GenericFunction : public FunctionInterface<domain_dim, range_dim, range_dim_cols, RangeField> { + using ThisType = GenericFunction; using BaseType = FunctionInterface<domain_dim, range_dim, range_dim_cols, RangeField>; public: @@ -111,11 +112,21 @@ public: , name_(nm) {} + GenericFunction(const ThisType&) = default; - /** - * \name ´´These methods are required by FunctionInterface.'' - * \{ - */ + GenericFunction(ThisType&&) = default; + +private: + ThisType* copy_as_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } int order(const Common::Parameter& param = {}) const override final { @@ -154,7 +165,6 @@ public: } /** - * \} * \name ´´These methods may be used to provide defaults on construction.'' * \{ */ diff --git a/dune/xt/functions/generic/grid-function.hh b/dune/xt/functions/generic/grid-function.hh index 6d2280c1c39a4f0bbb291f09c063d5ed48014fbc..b7e52709a76f7909b4488e3c500c50242ec7e093 100644 --- a/dune/xt/functions/generic/grid-function.hh +++ b/dune/xt/functions/generic/grid-function.hh @@ -54,6 +54,7 @@ namespace Functions { template <class E, size_t r = 1, size_t rC = 1, class R = double> class GenericGridFunction : public GridFunctionInterface<E, r, rC, R> { + using ThisType = GenericGridFunction; using BaseType = GridFunctionInterface<E, r, rC, R>; public: @@ -89,11 +90,10 @@ private: const Common::ParameterType& param_type, const GenericJacobianFunctionType& jacobian_func, const GenericDerivativeFunctionType& derivative_func) - : BaseType() + : BaseType(param_type) , order_(order_func) , post_bind_(post_bind_func) , evaluate_(evaluate_func) - , param_type_(param_type) , jacobian_(jacobian_func) , derivative_(derivative_func) {} @@ -147,18 +147,12 @@ private: return derivative_(alpha, point_in_local_coordinates, parsed_param); } - const Common::ParameterType& parameter_type() const override final - { - return param_type_; - } - private: - const GenericOrderFunctionType& order_; - const GenericPostBindFunctionType& post_bind_; - const GenericEvaluateFunctionType& evaluate_; - const Common::ParameterType& param_type_; - const GenericJacobianFunctionType& jacobian_; - const GenericDerivativeFunctionType& derivative_; + const GenericOrderFunctionType order_; + const GenericPostBindFunctionType post_bind_; + const GenericEvaluateFunctionType evaluate_; + const GenericJacobianFunctionType jacobian_; + const GenericDerivativeFunctionType derivative_; }; // class LocalGenericGridFunction public: @@ -185,10 +179,10 @@ public: const std::string nm = "GenericGridFunction", GenericJacobianFunctionType jacobian_func = default_jacobian_function(), GenericDerivativeFunctionType derivative_func = default_derivative_function()) - : order_(default_order_lambda(ord)) + : BaseType(param_type) + , order_(default_order_lambda(ord)) , post_bind_(post_bind_func) , evaluate_(evaluate_func) - , param_type_(param_type) , name_(nm) , jacobian_(jacobian_func) , derivative_(derivative_func) @@ -201,18 +195,29 @@ public: const std::string nm = "GenericGridFunction", GenericJacobianFunctionType jacobian_func = default_jacobian_function(), GenericDerivativeFunctionType derivative_func = default_derivative_function()) - : order_(order_func) + : BaseType(param_type) + , order_(order_func) , post_bind_(post_bind_func) , evaluate_(evaluate_func) - , param_type_(param_type) , name_(nm) , jacobian_(jacobian_func) , derivative_(derivative_func) {} - const Common::ParameterType& parameter_type() const override final + GenericGridFunction(const ThisType&) = default; + + GenericGridFunction(ThisType&&) = default; + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const { - return param_type_; + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); } std::string name() const override final @@ -223,7 +228,7 @@ public: std::unique_ptr<LocalFunctionType> local_function() const override final { return std::make_unique<LocalGenericGridFunction>( - order_, post_bind_, evaluate_, param_type_, jacobian_, derivative_); + order_, post_bind_, evaluate_, this->parameter_type(), jacobian_, derivative_); } /** @@ -281,10 +286,9 @@ private: const GenericOrderFunctionType order_; const GenericPostBindFunctionType post_bind_; const GenericEvaluateFunctionType evaluate_; - const Common::ParameterType param_type_; const std::string name_; - GenericJacobianFunctionType jacobian_; - GenericDerivativeFunctionType derivative_; + const GenericJacobianFunctionType jacobian_; + const GenericDerivativeFunctionType derivative_; }; // class GenericGridFunction diff --git a/dune/xt/functions/grid-function.hh b/dune/xt/functions/grid-function.hh index dd1adf99bc0f8659f2ff577c2eba4ada3ab6ad46..0621001ae210a9b583eebed99d8a5c9741d618cf 100644 --- a/dune/xt/functions/grid-function.hh +++ b/dune/xt/functions/grid-function.hh @@ -13,6 +13,7 @@ #define DUNE_XT_FUNCTIONS_GRID_FUNCTION_HH #include <dune/xt/common/memory.hh> +#include <dune/xt/common/print.hh> #include <dune/xt/la/container/eye-matrix.hh> #include <dune/xt/functions/base/function-as-grid-function.hh> #include <dune/xt/functions/base/combined-grid-functions.hh> @@ -128,71 +129,123 @@ public: using typename BaseType::LocalFunctionType; using GenericFunctionType = GenericFunction<d, r, rC>; - GridFunction(const typename RangeTypeSelector<R, r, rC>::type& value) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, r, rC, R>(new ConstantFunction<d, r, rC, R>(value))) + GridFunction(const typename RangeTypeSelector<R, r, rC>::type& value, + const std::string nm = "GridFunction", + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>(new ConstantFunction<d, r, rC, R>(value))) + , name_(nm) {} - GridFunction(const FunctionInterface<d, r, rC, R>& func) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, r, rC, R>(func)) + GridFunction(const FunctionInterface<d, r, rC, R>& func, const std::string logging_prefix = "") + : BaseType(func.parameter_type(), logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>(func)) + , name_(function_->name()) {} - GridFunction(FunctionInterface<d, r, rC, R>*&& func_ptr) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, r, rC, R>(std::move(func_ptr))) + GridFunction(FunctionInterface<d, r, rC, R>*&& func_ptr, const std::string logging_prefix = "") + : BaseType( + func_ptr->parameter_type(), logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>(std::move(func_ptr))) + , name_(function_->name()) {} - GridFunction(const GridFunctionInterface<E, r, rC, R>& func) - : BaseType() - , storage_(func) + GridFunction(const GridFunctionInterface<E, r, rC, R>& func, const std::string logging_prefix = "") + : BaseType(func.parameter_type(), + logging_prefix.empty() ? func.logger.prefix : logging_prefix, + logging_prefix.empty() ? !func.logger.debug_enabled : true) + , function_(func.copy_as_grid_function()) + , name_(function_->name()) {} - GridFunction(GridFunctionInterface<E, r, rC, R>*&& func_ptr) - : BaseType() - , storage_(std::move(func_ptr)) + GridFunction(GridFunctionInterface<E, r, rC, R>*&& func_ptr, const std::string logging_prefix = "") + : BaseType(func_ptr->parameter_type(), + logging_prefix.empty() ? func_ptr->logger.prefix : logging_prefix, + logging_prefix.empty() ? !func_ptr->logger.debug_enabled : true) + , function_(std::move(func_ptr)) + , name_(function_->name()) {} - GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType> order_evaluate) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( + GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType> order_evaluate, + const std::string nm = "GridFunction", + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( new GenericFunctionType(std::get<0>(order_evaluate), std::get<1>(order_evaluate)))) + , name_(nm) + {} + + GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType, const std::string&> + order_evaluate_name, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( + new GenericFunctionType(std::get<0>(order_evaluate_name), std::get<1>(order_evaluate_name)))) + , name_(std::get<2>(order_evaluate_name)) {} GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType, - typename GenericFunctionType::GenericJacobianFunctionType> order_evaluate_jacobian) - : BaseType() - , storage_( + typename GenericFunctionType::GenericJacobianFunctionType> order_evaluate_jacobian, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_( new FunctionAsGridFunctionWrapper<E, r, rC, R>(new GenericFunctionType(std::get<0>(order_evaluate_jacobian), std::get<1>(order_evaluate_jacobian), /*name=*/"", /*param_type=*/{}, std::get<2>(order_evaluate_jacobian)))) + , name_("GridFunction") + {} + + GridFunction(std::tuple<int, + typename GenericFunctionType::GenericEvaluateFunctionType, + typename GenericFunctionType::GenericJacobianFunctionType, + const std::string&> order_evaluate_jacobian_name, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( + new GenericFunctionType(std::get<0>(order_evaluate_jacobian_name), + std::get<1>(order_evaluate_jacobian_name), + /*name=*/"", + /*param_type=*/{}, + std::get<2>(order_evaluate_jacobian_name)))) + , name_(std::get<3>(order_evaluate_jacobian_name)) {} GridFunction(const ThisType& other) : BaseType(other) - , storage_(other.storage_) + , function_(other.function_->copy_as_grid_function()) + , name_(other.name_) {} - GridFunction(ThisType&& source) - : BaseType(source) - , storage_(std::move(source.storage_)) - {} + GridFunction(ThisType&& source) = default; + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } std::unique_ptr<LocalFunctionType> local_function() const override final { - return storage_.access().local_function(); + return function_->local_function(); } std::string name() const override final { - return storage_.access().name(); + return name_; } private: - Common::ConstStorageProvider<GridFunctionInterface<E, r, rC, R>> storage_; + std::unique_ptr<GridFunctionInterface<E, r, rC, R>> function_; + std::string name_; }; // class GridFunction<..., r, rC, ...> @@ -220,103 +273,164 @@ public: using typename BaseType::LocalFunctionType; using GenericFunctionType = GenericFunction<d, r, rC>; - GridFunction(const R& value) - : BaseType() - , storage_(new ProductGridFunction<GridFunction<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( + GridFunction(const R& value, const std::string nm = "GridFunction", const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new ProductGridFunction<GridFunction<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( new GridFunction<E, 1, 1, R>(value), std::move(unit_matrix()), "")) + , name_(nm) {} - GridFunction(const FieldMatrix<R, r, r>& value) // <- Must not be XT::Common::FieldMatrix! - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, r, r, R>(new ConstantFunction<d, r, r, R>(value))) + GridFunction(const FieldMatrix<R, r, r>& value, // <- Must not be XT::Common::FieldMatrix! + const std::string nm = "GridFunction", + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, r, R>(new ConstantFunction<d, r, r, R>(value))) + , name_(nm) {} - GridFunction(const FunctionInterface<d, 1, 1, R>& func) - : BaseType() - , storage_(new ProductGridFunction<FunctionAsGridFunctionWrapper<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( + GridFunction(const FunctionInterface<d, 1, 1, R>& func, const std::string logging_prefix = "") + : BaseType(func.parameter_type(), logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new ProductGridFunction<FunctionAsGridFunctionWrapper<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( new FunctionAsGridFunctionWrapper<E, 1, 1, R>(func), std::move(unit_matrix()), func.name())) + , name_(function_->name()) {} - GridFunction(FunctionInterface<d, 1, 1, R>*&& func_ptr) - : BaseType() - , storage_(new ProductGridFunction<FunctionAsGridFunctionWrapper<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( + GridFunction(FunctionInterface<d, 1, 1, R>*&& func_ptr, const std::string logging_prefix = "") + : BaseType( + func_ptr->parameter_type(), logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new ProductGridFunction<FunctionAsGridFunctionWrapper<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( new FunctionAsGridFunctionWrapper<E, 1, 1, R>(std::move(func_ptr)), std::move(unit_matrix()), func_ptr->name())) + , name_(function_->name()) {} - GridFunction(const FunctionInterface<d, r, r, R>& func) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, r, r, R>(func)) + GridFunction(const FunctionInterface<d, r, r, R>& func, const std::string logging_prefix = "") + : BaseType(func.parameter_type(), logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, r, R>(func)) + , name_(function_->name()) {} - GridFunction(FunctionInterface<d, r, r, R>*&& func_ptr) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, r, r, R>(std::move(func_ptr))) + GridFunction(FunctionInterface<d, r, r, R>*&& func_ptr, const std::string logging_prefix = "") + : BaseType( + func_ptr->parameter_type(), logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, r, R>(std::move(func_ptr))) + , name_(function_->name()) {} - GridFunction(const GridFunctionInterface<E, 1, 1, R>& func) - : BaseType() - , storage_(new ProductGridFunction<GridFunction<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( + GridFunction(const GridFunctionInterface<E, 1, 1, R>& func, const std::string logging_prefix = "") + : BaseType(func.parameter_type(), + logging_prefix.empty() ? func.logger.prefix : logging_prefix, + logging_prefix.empty() ? !func.logger.debug_enabled : true) + , function_(new ProductGridFunction<GridFunction<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( new GridFunction<E, 1, 1, R>(func), std::move(unit_matrix()), func.name())) + , name_(function_->name()) {} - GridFunction(GridFunctionInterface<E, 1, 1, R>*&& func_ptr) - : BaseType() - , storage_(new ProductGridFunction<GridFunctionInterface<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( + GridFunction(GridFunctionInterface<E, 1, 1, R>*&& func_ptr, const std::string logging_prefix = "") + : BaseType(func_ptr->parameter_type(), + logging_prefix.empty() ? func_ptr->logger.prefix : logging_prefix, + logging_prefix.empty() ? !func_ptr->logger.debug_enabled : true) + , function_(new ProductGridFunction<GridFunctionInterface<E, 1, 1, R>, GridFunctionInterface<E, r, r, R>>( std::move(func_ptr), std::move(unit_matrix()), func_ptr->name())) + , name_(function_->name()) {} - GridFunction(const GridFunctionInterface<E, r, r, R>& func) - : BaseType() - , storage_(func) + GridFunction(const GridFunctionInterface<E, r, r, R>& func, const std::string logging_prefix = "") + : BaseType(func.parameter_type(), + logging_prefix.empty() ? func.logger.prefix : logging_prefix, + logging_prefix.empty() ? !func.logger.debug_enabled : true) + , function_(func.copy_as_grid_function()) + , name_(function_->name()) {} - GridFunction(GridFunctionInterface<E, r, r, R>*&& func_ptr) - : BaseType() - , storage_(std::move(func_ptr)) + GridFunction(GridFunctionInterface<E, r, r, R>*&& func_ptr, const std::string logging_prefix = "") + : BaseType(func_ptr->parameter_type(), + logging_prefix.empty() ? func_ptr->logger.prefix : logging_prefix, + logging_prefix.empty() ? !func_ptr->logger.debug_enabled : true) + , function_(std::move(func_ptr)) + , name_(function_->name()) {} - GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType> order_evaluate) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( + GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType> order_evaluate, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( new GenericFunctionType(std::get<0>(order_evaluate), std::get<1>(order_evaluate)))) + , name_("GridFunction") + {} + + GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType, const std::string&> + order_evaluate_name, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( + new GenericFunctionType(std::get<0>(order_evaluate_name), std::get<1>(order_evaluate_name)))) + , name_(std::get<2>(order_evaluate_name)) {} GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType, - typename GenericFunctionType::GenericJacobianFunctionType> order_evaluate_jacobian) - : BaseType() - , storage_( + typename GenericFunctionType::GenericJacobianFunctionType> order_evaluate_jacobian, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_( new FunctionAsGridFunctionWrapper<E, r, rC, R>(new GenericFunctionType(std::get<0>(order_evaluate_jacobian), std::get<1>(order_evaluate_jacobian), /*name=*/"", /*param_type=*/{}, std::get<2>(order_evaluate_jacobian)))) + , name_("GridFunction") + {} + + GridFunction(std::tuple<int, + typename GenericFunctionType::GenericEvaluateFunctionType, + typename GenericFunctionType::GenericJacobianFunctionType, + const std::string&> order_evaluate_jacobian_name, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( + new GenericFunctionType(std::get<0>(order_evaluate_jacobian_name), + std::get<1>(order_evaluate_jacobian_name), + /*name=*/"", + /*param_type=*/{}, + std::get<2>(order_evaluate_jacobian_name)))) + , name_(std::get<3>(order_evaluate_jacobian_name)) {} GridFunction(const ThisType& other) : BaseType(other) - , storage_(other.storage_) + , function_(other.function_->copy_as_grid_function()) + , name_(other.name_) {} - GridFunction(ThisType&& source) - : BaseType(source) - , storage_(std::move(source.storage_)) - {} + GridFunction(ThisType&&) = default; + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } std::unique_ptr<LocalFunctionType> local_function() const override final { - return storage_.access().local_function(); + return function_->local_function(); } std::string name() const override final { - return storage_.access().name(); + return name_; } private: - Common::ConstStorageProvider<GridFunctionInterface<E, r, rC, R>> storage_; + std::unique_ptr<GridFunctionInterface<E, r, rC, R>> function_; + std::string name_; }; // class GridFunction<..., r, r, ...> @@ -338,81 +452,170 @@ public: using typename BaseType::LocalFunctionType; using GenericFunctionType = GenericFunction<d, r, rC>; - GridFunction(const R& value) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(new ConstantFunction<d, 1, 1, R>(value))) - {} + GridFunction(const R& value, const std::string nm = "GridFunction", const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(new ConstantFunction<d, 1, 1, R>(value))) + , name_(nm) + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", value=" << value << ", nm=\"" << nm << "\")" << std::endl; + } - GridFunction(const FieldVector<R, 1>& value) // <- Must not be XT::Common::FieldVector! - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(new ConstantFunction<d, 1, 1, R>(value))) - {} + GridFunction(const FieldVector<R, 1>& value, // <- Must not be XT::Common::FieldVector! + const std::string nm = "GridFunction", + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(new ConstantFunction<d, 1, 1, R>(value))) + , name_(nm) + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", value_vec=" << Common::print(value) << ", nm=\"" << nm + << "\")" << std::endl; + } - GridFunction(const FieldMatrix<R, 1, 1>& value) // <- Must not be XT::Common::FieldMatrix! - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(new ConstantFunction<d, 1, 1, R>(value[0][0]))) - {} + GridFunction(const FieldMatrix<R, 1, 1>& value, // <- Must not be XT::Common::FieldMatrix! + const std::string nm = "GridFunction", + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(new ConstantFunction<d, 1, 1, R>(value[0][0]))) + , name_(nm) + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", value_mat=" << Common::print(value) << ", nm=\"" << nm + << "\")" << std::endl; + } - GridFunction(const FunctionInterface<d, 1, 1, R>& func) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(func)) - {} + GridFunction(const FunctionInterface<d, 1, 1, R>& func, const std::string logging_prefix = "") + : BaseType(func.parameter_type(), logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(func)) + , name_(function_->name()) + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", func=" << &func << ", func.name()=" << name_ << ")" + << std::endl; + } - GridFunction(FunctionInterface<d, 1, 1, R>*&& func_ptr) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(std::move(func_ptr))) - {} + GridFunction(FunctionInterface<d, 1, 1, R>*&& func_ptr, const std::string logging_prefix = "") + : BaseType( + func_ptr->parameter_type(), logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, 1, 1, R>(std::move(func_ptr))) + , name_(function_->name()) + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", func_ptr=" << func_ptr << ", func_ptr->name()=" << name_ + << ")" << std::endl; + } - GridFunction(const GridFunctionInterface<E, 1, 1, R>& func) - : BaseType() - , storage_(func) - {} + GridFunction(const GridFunctionInterface<E, 1, 1, R>& func, const std::string logging_prefix = "") + : BaseType(func.parameter_type(), + logging_prefix.empty() ? "GridFunction(" + func.logger.prefix + ")" : logging_prefix, + logging_prefix.empty() ? !func.logger.debug_enabled : true) + , function_(func.copy_as_grid_function()) + , name_(function_->name()) + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", grid_func=" << &func << ", grid_func.name()=" << name_ << ")" + << std::endl; + } - GridFunction(GridFunctionInterface<E, 1, 1, R>*&& func_ptr) - : BaseType() - , storage_(std::move(func_ptr)) - {} + GridFunction(GridFunctionInterface<E, 1, 1, R>*&& func_ptr, const std::string logging_prefix = "") + : BaseType(func_ptr->parameter_type(), + logging_prefix.empty() ? "GridFunction(" + func_ptr->logger.prefix + ")" : logging_prefix, + logging_prefix.empty() ? !func_ptr->logger.debug_enabled : true) + , function_(std::move(func_ptr)) + , name_(function_->name()) + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", grid_func_ptr=" << func_ptr + << ", grid_func_ptr->name()=" << name_ << ")" << std::endl; + } - GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType> order_evaluate) - : BaseType() - , storage_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( + GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType> order_evaluate, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( new GenericFunctionType(std::get<0>(order_evaluate), std::get<1>(order_evaluate)))) - {} + , name_("GridFunction") + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", order_evaluate_lambda=" << &order_evaluate << ")" + << std::endl; + } + + GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType, const std::string&> + order_evaluate_name, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( + new GenericFunctionType(std::get<0>(order_evaluate_name), std::get<1>(order_evaluate_name)))) + , name_(std::get<2>(order_evaluate_name)) + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", order_evaluate_name_lambda=" << &order_evaluate_name << ")" + << std::endl; + } GridFunction(std::tuple<int, typename GenericFunctionType::GenericEvaluateFunctionType, - typename GenericFunctionType::GenericJacobianFunctionType> order_evaluate_jacobian) - : BaseType() - , storage_( + typename GenericFunctionType::GenericJacobianFunctionType> order_evaluate_jacobian, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_( new FunctionAsGridFunctionWrapper<E, r, rC, R>(new GenericFunctionType(std::get<0>(order_evaluate_jacobian), std::get<1>(order_evaluate_jacobian), /*name=*/"", /*param_type=*/{}, std::get<2>(order_evaluate_jacobian)))) - {} + , name_("GridFunction") + { + LOG_(info) << "GridFunction<1,1>(this=" << this << ", order_evaluate_jacobian_lambda=" << &order_evaluate_jacobian + << ")" << std::endl; + } + + GridFunction(std::tuple<int, + typename GenericFunctionType::GenericEvaluateFunctionType, + typename GenericFunctionType::GenericJacobianFunctionType, + const std::string&> order_evaluate_jacobian_name, + const std::string logging_prefix = "") + : BaseType({}, logging_prefix.empty() ? "GridFunction" : logging_prefix, logging_prefix.empty()) + , function_(new FunctionAsGridFunctionWrapper<E, r, rC, R>( + new GenericFunctionType(std::get<0>(order_evaluate_jacobian_name), + std::get<1>(order_evaluate_jacobian_name), + /*name=*/"", + /*param_type=*/{}, + std::get<2>(order_evaluate_jacobian_name)))) + , name_(std::get<3>(order_evaluate_jacobian_name)) + { + LOG_(info) << "GridFunction<1,1>(this=" << this + << ", order_evaluate_jacobian_name_lambda=" << &order_evaluate_jacobian_name << ")" << std::endl; + } GridFunction(const ThisType& other) : BaseType(other) - , storage_(other.storage_) + , function_(other.function_->copy_as_grid_function()) + , name_(other.name_) {} - GridFunction(ThisType&& source) - : BaseType(source) - , storage_(std::move(source.storage_)) - {} + GridFunction(ThisType&&) = default; + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } std::unique_ptr<LocalFunctionType> local_function() const override final { - return storage_.access().local_function(); + LOG_(info) << "GridFunction<1,1>::local_function()" << std::endl; + return function_->local_function(); } std::string name() const override final { - return storage_.access().name(); + return name_; } private: - Common::ConstStorageProvider<GridFunctionInterface<E, 1, 1, R>> storage_; + std::unique_ptr<GridFunctionInterface<E, 1, 1, R>> function_; + std::string name_; }; // class GridFunction<..., 1, 1, ...> diff --git a/dune/xt/functions/indicator.hh b/dune/xt/functions/indicator.hh index d91809e547012763dd866a2118ae3813df77245e..22c8d0aa83f46626f1f107ec2d4d1e514a3b5678 100644 --- a/dune/xt/functions/indicator.hh +++ b/dune/xt/functions/indicator.hh @@ -45,7 +45,7 @@ class IndicatorGridFunction : public GridFunctionInterface<E, r, rC, R> using GeometryType = typename ElementType::Geometry; LocalIndicatorGridFunction( - const std::vector<std::tuple<DomainType, DomainType, RangeType>>& subdomain_and_value_tuples) + const std::shared_ptr<std::vector<std::tuple<DomainType, DomainType, RangeType>>> subdomain_and_value_tuples) : InterfaceType() , subdomain_and_value_tuples_(subdomain_and_value_tuples) {} @@ -55,7 +55,7 @@ class IndicatorGridFunction : public GridFunctionInterface<E, r, rC, R> { current_value_ = 0.; const auto center = element.geometry().center(); - for (const auto& subdomain_and_value_tuple : subdomain_and_value_tuples_) { + for (const auto& subdomain_and_value_tuple : *subdomain_and_value_tuples_) { const auto& subdomain_ll = std::get<0>(subdomain_and_value_tuple); const auto& subdomain_ur = std::get<1>(subdomain_and_value_tuple); if (Common::FloatCmp::le(subdomain_ll, center) && Common::FloatCmp::lt(center, subdomain_ur)) @@ -84,7 +84,7 @@ class IndicatorGridFunction : public GridFunctionInterface<E, r, rC, R> } private: - const std::vector<std::tuple<DomainType, DomainType, RangeType>>& subdomain_and_value_tuples_; + const std::shared_ptr<std::vector<std::tuple<DomainType, DomainType, RangeType>>> subdomain_and_value_tuples_; RangeType current_value_; }; // class LocalIndicatorGridFunction @@ -117,6 +117,12 @@ public: return config; } // ... defaults(...) + IndicatorGridFunction(std::shared_ptr<std::vector<std::tuple<DomainType, DomainType, RangeType>>> values, + const std::string name_in = "IndicatorGridFunction") + : subdomain_and_value_tuples_(values) + , name_(name_in) + {} + /** * Can be used for declaration of lower left corner and upper right corner of the desired domains. \code @@ -124,9 +130,8 @@ FunctionType function({{lowerleft_1, upperright_1, value_1}, {lowerleft_2, upper \endcode */ IndicatorGridFunction(const std::vector<std::tuple<DomainType, DomainType, RangeType>>& values, - const std::string name_in = "indicator") - : subdomain_and_value_tuples_(values) - , name_(name_in) + const std::string nm = "IndicatorGridFunction") + : IndicatorGridFunction(std::make_shared<std::vector<std::tuple<DomainType, DomainType, RangeType>>>(values), nm) {} /** @@ -139,11 +144,27 @@ FunctionType function({{{{0., 1.}, {0., 1.}}, 0.7}, {{{6., 10.}, {8., 10.}}, 0.9 * if you want to set indicator intervals [0,1] x [0,1] with value 0.7 and [6,10] x [8,10] with value 0.9. */ IndicatorGridFunction(const std::vector<std::pair<Common::FieldMatrix<D, d, 2>, RangeType>>& values, - const std::string name_in = "indicator") - : subdomain_and_value_tuples_(convert_from_domains(values)) - , name_(name_in) + const std::string nm = "IndicatorGridFunction") + : IndicatorGridFunction(convert_from_domains(values), nm) {} + IndicatorGridFunction(const ThisType&) = default; + + IndicatorGridFunction(ThisType&&) = default; + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } + std::string name() const override final { return name_; @@ -155,10 +176,10 @@ FunctionType function({{{{0., 1.}, {0., 1.}}, 0.7}, {{{6., 10.}, {8., 10.}}, 0.9 } private: - static std::vector<std::tuple<DomainType, DomainType, RangeType>> + static std::shared_ptr<std::vector<std::tuple<DomainType, DomainType, RangeType>>> convert_from_domains(const std::vector<std::pair<Common::FieldMatrix<D, d, 2>, RangeType>>& values) { - std::vector<std::tuple<DomainType, DomainType, RangeType>> ret; + auto ret = std::make_shared<std::vector<std::tuple<DomainType, DomainType, RangeType>>>(); for (const auto& element : values) { DomainType tmp_coordinates_ll(0.); DomainType tmp_coordinates_ur(0.); @@ -166,12 +187,12 @@ private: tmp_coordinates_ll[dd] = element.first[dd][0]; tmp_coordinates_ur[dd] = element.first[dd][1]; } - ret.emplace_back(tmp_coordinates_ll, tmp_coordinates_ur, element.second); + ret->emplace_back(tmp_coordinates_ll, tmp_coordinates_ur, element.second); } return ret; } // convert_from_tuples(...) - const std::vector<std::tuple<DomainType, DomainType, RangeType>> subdomain_and_value_tuples_; + const std::shared_ptr<std::vector<std::tuple<DomainType, DomainType, RangeType>>> subdomain_and_value_tuples_; const std::string name_; }; // class IndicatorGridFunction @@ -179,6 +200,7 @@ private: template <size_t d, size_t r = 1, size_t rC = 1, class R = double> class IndicatorFunction : public FunctionInterface<d, r, rC, R> { + using ThisType = IndicatorFunction; using BaseType = FunctionInterface<d, r, rC, R>; public: @@ -187,18 +209,38 @@ public: using typename BaseType::DomainType; using typename BaseType::RangeReturnType; - IndicatorFunction(const std::vector<std::tuple<DomainType, DomainType, RangeReturnType>>& values, - const std::string nm = "indicator") + IndicatorFunction(std::shared_ptr<std::vector<std::tuple<DomainType, DomainType, RangeReturnType>>> values, + const std::string nm = "IndicatorFunction") : subdomain_and_value_tuples_(values) , name_(nm) {} + IndicatorFunction(const std::vector<std::tuple<DomainType, DomainType, RangeReturnType>>& values, + const std::string nm = "IndicatorFunction") + : IndicatorFunction(std::make_shared<std::vector<std::tuple<DomainType, DomainType, RangeReturnType>>>(values), nm) + {} + IndicatorFunction(const std::vector<std::pair<Common::FieldMatrix<D, d, 2>, RangeReturnType>>& values, - const std::string nm = "indicator") - : subdomain_and_value_tuples_(convert_from_domains(values)) - , name_(nm) + const std::string nm = "IndicatorFunction") + : IndicatorFunction(convert_from_domains(values), nm) {} + IndicatorFunction(const ThisType&) = default; + + IndicatorFunction(ThisType&&) = default; + +private: + ThisType* copy_as_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } + int order(const XT::Common::Parameter& /*param*/ = {}) const override final { return 0; @@ -223,7 +265,7 @@ public: std::string name() const override final { - return "dune.xt.functions.indicatorfunction"; + return name_; } using BaseType::evaluate; @@ -232,7 +274,7 @@ public: const Common::Parameter& /*param*/ = {}) const override final { RangeReturnType value(0.); - for (const auto& subdomain_and_value_tuple : subdomain_and_value_tuples_) { + for (const auto& subdomain_and_value_tuple : *subdomain_and_value_tuples_) { const auto& subdomain_ll = std::get<0>(subdomain_and_value_tuple); const auto& subdomain_ur = std::get<1>(subdomain_and_value_tuple); if (Common::FloatCmp::le(subdomain_ll, point_in_global_coordinates) @@ -251,10 +293,10 @@ public: } private: - static std::vector<std::tuple<DomainType, DomainType, RangeReturnType>> + static std::shared_ptr<std::vector<std::tuple<DomainType, DomainType, RangeReturnType>>> convert_from_domains(const std::vector<std::pair<Common::FieldMatrix<D, d, 2>, RangeReturnType>>& values) { - std::vector<std::tuple<DomainType, DomainType, RangeReturnType>> ret; + auto ret = std::make_shared<std::vector<std::tuple<DomainType, DomainType, RangeReturnType>>>(); for (const auto& element : values) { DomainType tmp_coordinates_ll(0.); DomainType tmp_coordinates_ur(0.); @@ -262,12 +304,12 @@ private: tmp_coordinates_ll[dd] = element.first[dd][0]; tmp_coordinates_ur[dd] = element.first[dd][1]; } - ret.emplace_back(tmp_coordinates_ll, tmp_coordinates_ur, element.second); + ret->emplace_back(tmp_coordinates_ll, tmp_coordinates_ur, element.second); } return ret; } // convert_from_tuples(...) - const std::vector<std::tuple<DomainType, DomainType, RangeReturnType>> subdomain_and_value_tuples_; + const std::shared_ptr<std::vector<std::tuple<DomainType, DomainType, RangeReturnType>>> subdomain_and_value_tuples_; const std::string name_; }; // class IndicatorFunction diff --git a/dune/xt/functions/interfaces/element-functions.hh b/dune/xt/functions/interfaces/element-functions.hh index f97daea9278723e952be950fc26017afa98a5979..3a93d69fcd0106757d68cff28c840873d7475401 100644 --- a/dune/xt/functions/interfaces/element-functions.hh +++ b/dune/xt/functions/interfaces/element-functions.hh @@ -58,12 +58,20 @@ class ConstProductElementFunction; template <class LeftFactorType, class RightFactorType> class ProductElementFunction; +template <class LeftFactorType, class RightFactorType> +class ConstFractionElementFunction; + +template <class LeftFactorType, class RightFactorType> +class FractionElementFunction; + namespace internal { -template <class LeftType, class RightType, CombinationType> -class CombinedElementFunctionHelper; +template <class, class, class CombinationType> +struct CombinedHelper; + + } @@ -652,25 +660,47 @@ public: result[0] = this->derivative(alpha, point_in_reference_element, param); } - /** - * \} - * \name ´´These operators are provided for convenience.'' - * \{ - **/ + /// \} + + /// \name Numerical operators (const variants). + /// \{ ConstDifferenceElementFunction<ThisType, ThisType> operator-(const ThisType& other) const { return ConstDifferenceElementFunction<ThisType, ThisType>(*this, other); } - DifferenceElementFunction<ThisType, ThisType> operator-(ThisType& other) + ConstSumElementFunction<ThisType, ThisType> operator+(const ThisType& other) const { - return DifferenceElementFunction<ThisType, ThisType>(*this, other); + return ConstSumElementFunction<ThisType, ThisType>(*this, other); } - ConstSumElementFunction<ThisType, ThisType> operator+(const ThisType& other) const + template <class OtherType> + std::enable_if_t<is_element_function<OtherType>::value + && internal::CombinedHelper<ThisType, OtherType, CombinationType::product>::available, + ConstProductElementFunction<ThisType, as_element_function_interface_t<OtherType>>> + operator*(const OtherType& other) const { - return ConstSumElementFunction<ThisType, ThisType>(*this, other); + return ConstProductElementFunction<ThisType, as_element_function_interface_t<OtherType>>(*this, other); + } + + template <class OtherType> + std::enable_if_t<is_element_function<OtherType>::value + && internal::CombinedHelper<ThisType, OtherType, CombinationType::fraction>::available, + ConstFractionElementFunction<ThisType, as_element_function_interface_t<OtherType>>> + operator/(const OtherType& other) const + { + return ConstFractionElementFunction<ThisType, as_element_function_interface_t<OtherType>>(*this, other); + } + + /// \} + + /// \name Numerical operators (mutable variants). + /// \{ + + DifferenceElementFunction<ThisType, ThisType> operator-(ThisType& other) + { + return DifferenceElementFunction<ThisType, ThisType>(*this, other); } SumElementFunction<ThisType, ThisType> operator+(ThisType& other) @@ -679,28 +709,24 @@ public: } template <class OtherType> - std::enable_if_t< - is_element_function<OtherType>::value - && internal::CombinedElementFunctionHelper<ThisType, OtherType, CombinationType::product>::available, - ConstProductElementFunction<ThisType, OtherType>> - operator*(const OtherType& other) const + std::enable_if_t<is_element_function<OtherType>::value + && internal::CombinedHelper<ThisType, OtherType, CombinationType::product>::available, + ProductElementFunction<ThisType, as_element_function_interface_t<OtherType>>> + operator*(OtherType& other) { - return ConstProductElementFunction<ThisType, OtherType>(*this, other); + return ProductElementFunction<ThisType, as_element_function_interface_t<OtherType>>(*this, other); } template <class OtherType> - std::enable_if_t< - is_element_function<OtherType>::value - && internal::CombinedElementFunctionHelper<ThisType, OtherType, CombinationType::product>::available, - ProductElementFunction<ThisType, OtherType>> - operator*(OtherType& other) + std::enable_if_t<is_element_function<OtherType>::value + && internal::CombinedHelper<ThisType, OtherType, CombinationType::fraction>::available, + FractionElementFunction<ThisType, as_element_function_interface_t<OtherType>>> + operator/(OtherType& other) { - return ProductElementFunction<ThisType, OtherType>(*this, other); + return FractionElementFunction<ThisType, as_element_function_interface_t<OtherType>>(*this, other); } - /** - * \{ - **/ + /// \} private: template <class FullType> diff --git a/dune/xt/functions/interfaces/function.hh b/dune/xt/functions/interfaces/function.hh index 23544a448f8f35b19ec237a941db44c23799190d..5fd99a6785668b5870c576808f24561dddc43ccc 100644 --- a/dune/xt/functions/interfaces/function.hh +++ b/dune/xt/functions/interfaces/function.hh @@ -31,16 +31,29 @@ namespace XT { namespace Functions { -// forwards, required in operator+-* -template <class MinuendType, class SubtrahendType> +// forwards, required in operator+-*, includes are below +namespace internal { + + +template <class, class, class CombinationType> +struct CombinedHelper; + + +} // namespace internal + + +template <class, class> class DifferenceFunction; -template <class LeftSummandType, class RightSummandType> +template <class, class> class SumFunction; -template <class LeftSummandType, class RightSummandType> +template <class, class> class ProductFunction; +template <class, class> +class FractionFunction; + // forward, required in FunctionInterface::as_grid_function template <class E, size_t r, size_t rC, class R> class FunctionAsGridFunctionWrapper; @@ -52,7 +65,7 @@ class FunctionAsGridFunctionWrapper; * These functions do not depend on a grid, but only on the dimensions and fields of their domain and range. * See in particular RangeReturnTypeSelector and DerivativeRangeReturnTypeSelector for the interpretation of a * function and its derivatives, and GridFunctionInterface for functions which may have discontinuities between - * entites (as in: which are double-valued on intersections). + * entities (as in: which are double-valued on intersections). * * To turn a function into a function which is localizable w.r.t. a GridView of matching dimension (e.g., * to visualize it or to use it in a discretization scheme), use as_grid_function to obtain a const reference to @@ -120,13 +133,40 @@ public: : Common::ParametricInterface(param_type) {} + FunctionInterface(const ThisType& other) + : Common::ParametricInterface(other) + {} + + FunctionInterface(ThisType&) = default; + virtual ~FunctionInterface() = default; + ThisType& operator=(const ThisType&) = delete; + + ThisType& operator=(ThisType&&) = delete; + /** * \name ´´These methods have to be implemented.'' * \{ **/ + /** + * \brief Returns a (shallow) copy of the function. + * actual implementation work is delegated to the private `copy_as_function_impl` + * combined with hiding `copy_as_function` in derived classes, this allows us the a + * unique_ptr with correct type at all levels of the polymorphic hierarchy + * + * \note This is intended to be cheap, so make sure to share resources (but in a thread-safe way)! + */ + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } + +private: + virtual ThisType* copy_as_function_impl() const = 0; + +public: virtual int order(const XT::Common::Parameter& /*param*/ = {}) const = 0; /** @@ -165,28 +205,47 @@ public: return "dune.xt.functions.function"; } - /** - * \} - * \name ´´These methods are default implemented and should be overridden to improve their performance.'' - * \{ - **/ + /// \} + /// \name Operators emulating numeric types. + /// \{ + + Functions::DifferenceFunction<ThisType, ThisType> operator-(const ThisType& other) const + { + return Functions::DifferenceFunction<ThisType, ThisType>( + *this, other, "(" + this->name() + " - " + other.name() + ")"); + } - DifferenceType operator-(const ThisType& other) const + Functions::SumFunction<ThisType, ThisType> operator+(const ThisType& other) const { - return DifferenceType(*this, other); + return Functions::SumFunction<ThisType, ThisType>(*this, other, "(" + this->name() + " + " + other.name() + ")"); } - SumType operator+(const ThisType& other) const + template <class OtherType> + std::enable_if_t<is_function<OtherType>::value + && internal::CombinedHelper<ThisType, OtherType, CombinationType::product>::available, + Functions::ProductFunction<ThisType, as_function_interface_t<OtherType>>> + operator*(const OtherType& other) const { - return SumType(*this, other); + return Functions::ProductFunction<ThisType, as_function_interface_t<OtherType>>( + *this, other, "(" + this->name() + "*" + other.name() + ")"); } template <class OtherType> - auto operator*(const OtherType& other) const + std::enable_if_t<is_function<OtherType>::value + && internal::CombinedHelper<ThisType, OtherType, CombinationType::fraction>::available, + Functions::FractionFunction<ThisType, as_function_interface_t<OtherType>>> + operator/(const OtherType& other) const { - return Functions::ProductFunction<ThisType, OtherType>(*this, other); + return Functions::FractionFunction<ThisType, as_function_interface_t<OtherType>>( + *this, other, "(" + this->name() + "/" + other.name() + ")"); } + /** + * \} + * \name ´´These methods are default implemented and should be overridden to improve their performance.'' + * \{ + **/ + virtual R evaluate(const DomainType& point_in_global_coordinates, const size_t row, const size_t col = 0, @@ -258,22 +317,24 @@ public: /** * \note This function keeps a map of all wrappers in a local static map, to avoid temporaries. * \todo Check if this implementation is thread safe! + * \todo nvm thread safe, the caching is already broken for multiple functions in sequence */ template <class E> const typename std::enable_if<XT::Grid::is_entity<E>::value && E::dimension == d, - FunctionAsGridFunctionWrapper<E, r, rC, R>>::type& + FunctionAsGridFunctionWrapper<E, r, rC, R>>::type as_grid_function() const { - static std::map<const ThisType*, std::unique_ptr<FunctionAsGridFunctionWrapper<E, r, rC, R>>> wrappers; - if (wrappers.find(this) == wrappers.end()) - wrappers[this] = std::make_unique<FunctionAsGridFunctionWrapper<E, r, rC, R>>(*this); - return *(wrappers[this]); + // static std::map<const ThisType*, std::unique_ptr<FunctionAsGridFunctionWrapper<E, r, rC, R>>> wrappers; + // if (wrappers.find(this) == wrappers.end()) + // wrappers[this] = std::make_unique<FunctionAsGridFunctionWrapper<E, r, rC, R>>(*this); + // return *(wrappers[this]); + return FunctionAsGridFunctionWrapper<E, r, rC, R>(copy_as_function()); } template <class ViewTraits> const typename std::enable_if< (ViewTraits::Grid::dimension == d), - FunctionAsGridFunctionWrapper<typename ViewTraits::template Codim<0>::Entity, r, rC, R>>::type& + FunctionAsGridFunctionWrapper<typename ViewTraits::template Codim<0>::Entity, r, rC, R>>::type as_grid_function(const GridView<ViewTraits>& /*grid_view*/) const { return this->as_grid_function<typename ViewTraits::template Codim<0>::Entity>(); diff --git a/dune/xt/functions/interfaces/grid-function.hh b/dune/xt/functions/interfaces/grid-function.hh index a7e2e8fcccec2d139053cf8f1205575106b28634..ba8eb67114102e6cb600129b94a67963a76177f4 100644 --- a/dune/xt/functions/interfaces/grid-function.hh +++ b/dune/xt/functions/interfaces/grid-function.hh @@ -25,15 +25,16 @@ #include <dune/xt/common/filesystem.hh> #include <dune/xt/common/memory.hh> +#include <dune/xt/common/timedlogging.hh> #include <dune/xt/common/type_traits.hh> #include <dune/xt/grid/grids.hh> #include <dune/xt/grid/layers.hh> #include <dune/xt/grid/view/from-part.hh> #include <dune/xt/grid/type_traits.hh> +#include <dune/xt/functions/base/visualization.hh> #include <dune/xt/functions/exceptions.hh> #include <dune/xt/functions/type_traits.hh> -#include <dune/xt/functions/base/visualization.hh> #include "element-functions.hh" @@ -42,17 +43,21 @@ namespace XT { namespace Functions { -template <class MinuendType, class SubtrahendType> +// forwards, includes are below +template <class, class, class CombinationType> +struct CombinedHelper; + +template <class, class> class DifferenceGridFunction; -template <class LeftSummandType, class RightSummandType> +template <class, class> class SumGridFunction; -template <class LeftSummandType, class RightSummandType> +template <class, class> class ProductGridFunction; -// template <class Function> -// class DivergenceFunction; +template <class, class> +class FractionGridFunction; /** @@ -67,9 +72,12 @@ class ProductGridFunction; * situations which could not be handled generically later on. */ template <class Element, size_t rangeDim = 1, size_t rangeDimCols = 1, class RangeField = double> -class GridFunctionInterface : public Common::ParametricInterface +class GridFunctionInterface + : public Common::ParametricInterface + , public Common::WithLogger<GridFunctionInterface<Element, rangeDim, rangeDimCols, RangeField>> { - using ThisType = GridFunctionInterface<Element, rangeDim, rangeDimCols, RangeField>; + using ThisType = GridFunctionInterface; + using Logger = Common::WithLogger<GridFunctionInterface<Element, rangeDim, rangeDimCols, RangeField>>; public: using LocalFunctionType = ElementFunctionInterface<Element, rangeDim, rangeDimCols, RangeField>; @@ -90,25 +98,67 @@ public: static constexpr bool available = false; - using DifferenceType = Functions::DifferenceGridFunction<ThisType, ThisType>; - using SumType = Functions::SumGridFunction<ThisType, ThisType>; +private: + std::string logging_id() const + { + return "GridFunctionInterface<" + Common::to_string(size_t(r)) + "," + Common::to_string(size_t(rC)) + ">"; + } - GridFunctionInterface(const Common::ParameterType& param_type = {}) +public: + GridFunctionInterface(const Common::ParameterType& param_type = {}, + const std::string& logging_prefix = "", + const bool logging_disabled = true) : Common::ParametricInterface(param_type) + , Logger(logging_prefix.empty() ? "GridFunctionInterface" : logging_prefix, logging_disabled) + { + LOG_(debug) << logging_id() << "(param_type=" << param_type << ")" << std::endl; + } + + GridFunctionInterface(const ThisType& other) + : Common::ParametricInterface(other) + , Logger(other) {} + GridFunctionInterface(ThisType&) = default; + virtual ~GridFunctionInterface() = default; + ThisType& operator=(const ThisType&) = delete; + + ThisType& operator=(ThisType&&) = delete; + static std::string static_id() { return "dune.xt.functions.gridfunction"; } /** - * \name ´´This method has to be implemented.'' + * \name ´´These methods have to be implemented.'' * \{ **/ + /** + * \brief Returns a (shallow) copy of the function. + * actual implementation work is delegated to the private `copy_as_function_impl` + * combined with hiding `copy_as_function` in dervived classes, this allows us the a + * unique_ptr with correct type at all levels of the polymorphic hierarchy + * + * \note This is intended to be cheap, so make sure to share resources (but in a thread-safe way)! + */ + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } + +private: + virtual ThisType* copy_as_grid_function_impl() const = 0; + +public: + /** + * \brief Returns the local function which can be bound to grid elements. + * + * \note If possible, the returned function should be able to live on its own, e.g. by copying the grid function. + */ virtual std::unique_ptr<LocalFunctionType> local_function() const = 0; /** @@ -119,28 +169,69 @@ public: virtual std::string name() const { - return "dune.xt.functions.gridfunction"; + LOG_(debug) << logging_id() << "::name()\n returning \"GridFunction\"" << std::endl; + return "GridFunction"; } /// \} - DifferenceType operator-(const ThisType& other) const + /// \name Operators emulating numeric types. + /// \{ + + Functions::DifferenceGridFunction<ThisType, ThisType> operator-(const ThisType& other) const { - return DifferenceType(*this, other); + std::string derived_logging_prefix = ""; + if (this->logger.debug_enabled || other.logger.debug_enabled) { + derived_logging_prefix = "(" + this->logger.prefix + " - " + other.logger.prefix + ")"; + this->logger.debug() << logging_id() << "::operator-(other=" << &other << ")" << std::endl; + } + return Functions::DifferenceGridFunction<ThisType, ThisType>( + *this, other, "(" + this->name() + " - " + other.name() + ")", derived_logging_prefix); } - SumType operator+(const ThisType& other) const + Functions::SumGridFunction<ThisType, ThisType> operator+(const ThisType& other) const { - return SumType(*this, other); + std::string derived_logging_prefix = ""; + if (this->logger.debug_enabled || other.logger.debug_enabled) { + derived_logging_prefix = "(" + this->logger.prefix + " - " + other.logger.prefix + ")"; + this->logger.debug() << logging_id() << "::operator+(other=" << &other << ")" << std::endl; + } + return Functions::SumGridFunction<ThisType, ThisType>( + *this, other, "(" + this->name() + " + " + other.name() + ")", derived_logging_prefix); } template <class OtherType> - typename std::enable_if<is_grid_function<OtherType>::value, Functions::ProductGridFunction<ThisType, OtherType>>::type + std::enable_if_t<is_grid_function<OtherType>::value + && internal::CombinedHelper<ThisType, OtherType, CombinationType::product>::available, + Functions::ProductGridFunction<ThisType, as_grid_function_interface_t<OtherType>>> operator*(const OtherType& other) const { - return Functions::ProductGridFunction<ThisType, OtherType>(*this, other); + std::string derived_logging_prefix = ""; + if (this->logger.debug_enabled || other.logger.debug_enabled) { + derived_logging_prefix = "(" + this->logger.prefix + "*" + other.logger.prefix + ")"; + this->logger.debug() << logging_id() << "::operator*(other=" << &other << ")" << std::endl; + } + return Functions::ProductGridFunction<ThisType, as_grid_function_interface_t<OtherType>>( + *this, other, "(" + this->name() + "*" + other.name() + ")", derived_logging_prefix); } + template <class OtherType> + std::enable_if_t<is_grid_function<OtherType>::value + && internal::CombinedHelper<ThisType, OtherType, CombinationType::fraction>::available, + Functions::FractionGridFunction<ThisType, as_grid_function_interface_t<OtherType>>> + operator/(const OtherType& other) const + { + std::string derived_logging_prefix = ""; + if (this->logger.debug_enabled || other.logger.debug_enabled) { + derived_logging_prefix = "(" + this->logger.prefix + "/" + other.logger.prefix + ")"; + this->logger.debug() << logging_id() << "::operator/(other=" << &other << ")" << std::endl; + } + return Functions::FractionGridFunction<ThisType, as_grid_function_interface_t<OtherType>>( + *this, other, "(" + this->name() + "/" + other.name() + ")", derived_logging_prefix); + } + + /// \} + /** * \note We use the SubsamplingVTKWriter (which is better for higher orders) by default: the grid you see in the * visualization may thus be a refinement of the actual grid! @@ -234,6 +325,5 @@ public: } // namespace Dune #include <dune/xt/functions/base/combined-grid-functions.hh> -#include <dune/xt/functions/base/visualization.hh> #endif // DUNE_XT_FUNCTIONS_INTERFACES_GRID_FUNCTION_HH diff --git a/dune/xt/functions/inverse.hh b/dune/xt/functions/inverse.hh index 0c7d3f1f1aa701bc56f28a50530235fa3da43a00..f70ad2212a4e0af09db286ea3fd164780b0ca65e 100644 --- a/dune/xt/functions/inverse.hh +++ b/dune/xt/functions/inverse.hh @@ -15,7 +15,10 @@ #include <dune/xt/common/float_cmp.hh> #include <dune/xt/common/memory.hh> #include <dune/xt/la/matrix-inverter.hh> +#include <dune/xt/functions/grid-function.hh> #include <dune/xt/functions/interfaces/element-functions.hh> +#include <dune/xt/functions/interfaces/function.hh> +#include <dune/xt/functions/interfaces/grid-function.hh> #include <dune/xt/functions/exceptions.hh> #include <dune/xt/functions/type_traits.hh> @@ -43,27 +46,26 @@ public: public: static constexpr bool available = (FunctionType::rC == FunctionType::r); - static RangeReturnType compute(const FunctionType& func, const DomainType& xx, const XT::Common::Parameter& param) + static RangeReturnType compute(const RangeReturnType& value) { if constexpr (FunctionType::rC == 1 && FunctionType::r == 1) { - auto value_to_invert = func.evaluate(xx, param); + auto value_to_invert = value[0]; DUNE_THROW_IF(XT::Common::FloatCmp::eq(value_to_invert, 0.), Exceptions::wrong_input_given, "Scalar function value was not invertible!\n\nvalue_to_invert = " << value_to_invert); return 1. / value_to_invert; } else if constexpr (available) { - auto matrix_to_invert = func.evaluate(xx, param); RangeReturnType inverse_matrix; try { - inverse_matrix = XT::LA::invert_matrix(matrix_to_invert); + inverse_matrix = XT::LA::invert_matrix(value); } catch (const XT::LA::Exceptions::matrix_invert_failed& ee) { DUNE_THROW(Exceptions::wrong_input_given, "Matrix-valued function value was not invertible!\n\nmatrix_to_invert = " - << matrix_to_invert << "\n\nThis was the original error: " << ee.what()); + << value << "\n\nThis was the original error: " << ee.what()); } return inverse_matrix; } else { - static_assert(AlwaysFalse<FunctionType>::value, "compute not available"); + static_assert(AlwaysFalse<FunctionType>::value, "Not available for these dimensions!"); } } }; // class InverseFunctionHelper @@ -79,6 +81,8 @@ class InverseElementFunction internal::InverseFunctionHelper<ElementFunctionType>::rC, typename internal::InverseFunctionHelper<ElementFunctionType>::R> { + static_assert(is_element_function<ElementFunctionType>::value, ""); + using BaseType = ElementFunctionInterface<typename ElementFunctionType::E, internal::InverseFunctionHelper<ElementFunctionType>::r, internal::InverseFunctionHelper<ElementFunctionType>::rC, @@ -88,6 +92,7 @@ class InverseElementFunction public: using typename BaseType::DomainType; + using typename BaseType::E; using typename BaseType::ElementType; using typename BaseType::RangeReturnType; @@ -107,7 +112,7 @@ public: {} protected: - void post_bind(const ElementType& element) + void post_bind(const ElementType& element) override final { func_.access().bind(element); } @@ -120,7 +125,7 @@ public: RangeReturnType evaluate(const DomainType& xx, const Common::Parameter& param = {}) const override final { - return Helper::compute(func_.access(), xx, param); + return Helper::compute(func_.access().evaluate(xx, param)); } private: @@ -136,6 +141,9 @@ class InverseFunction internal::InverseFunctionHelper<FunctionType>::rC, typename internal::InverseFunctionHelper<FunctionType>::R> { + static_assert(is_function<FunctionType>::value, ""); + + using ThisType = InverseFunction; using BaseType = FunctionInterface<FunctionType::d, internal::InverseFunctionHelper<FunctionType>::r, internal::InverseFunctionHelper<FunctionType>::rC, @@ -147,21 +155,37 @@ public: using typename BaseType::DomainType; using typename BaseType::RangeReturnType; - InverseFunction(FunctionType& func, const int ord) - : func_(func) + InverseFunction(const FunctionType& func, const int ord) + : BaseType(func.parameter_type()) + , func_(func.copy_as_function()) , order_(ord) {} - InverseFunction(std::shared_ptr<FunctionType> func, const int ord) - : func_(func) + InverseFunction(FunctionType&& func, const int ord) + : BaseType(func->parameter_type()) + , func_(std::move(func)) , order_(ord) {} - InverseFunction(std::unique_ptr<FunctionType>&& func, const int ord) - : func_(std::move(func)) - , order_(ord) + InverseFunction(const ThisType& other) + : BaseType(other) + , func_(other.func_->copy_as_function()) + , order_(order) {} + InverseFunction(ThisType&&) = default; + +private: + ThisType* copy_as_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_function_impl()); + } int order(const XT::Common::Parameter& /*param*/ = {}) const override final { return order_; @@ -169,15 +193,18 @@ public: RangeReturnType evaluate(const DomainType& xx, const Common::Parameter& param = {}) const override final { - return Helper::compute(func_.access(), xx, param); + return Helper::compute(func_.evaluate(xx, param)); } private: - XT::Common::StorageProvider<FunctionType> func_; + const std::unique_ptr<FunctionType> func_; const int order_; }; // class InverseFunction +/** + * \todo Write custom local function to hold a copy af this! + */ template <class GridFunctionType> class InverseGridFunction : public GridFunctionInterface<typename GridFunctionType::E, @@ -185,46 +212,69 @@ class InverseGridFunction internal::InverseFunctionHelper<GridFunctionType>::rC, typename internal::InverseFunctionHelper<GridFunctionType>::R> { - using BaseType = GridFunctionInterface<typename GridFunctionType::E, - internal::InverseFunctionHelper<GridFunctionType>::r, - internal::InverseFunctionHelper<GridFunctionType>::rC, - typename internal::InverseFunctionHelper<GridFunctionType>::R>; + static_assert(is_grid_function<GridFunctionType>::value, ""); using Helper = internal::InverseFunctionHelper<GridFunctionType>; + static const constexpr size_t r_ = GridFunctionType::r; + static const constexpr size_t rC_ = GridFunctionType::rC; public: + using ThisType = InverseGridFunction; + using BaseType = GridFunctionInterface<typename GridFunctionType::E, + internal::InverseFunctionHelper<GridFunctionType>::r, + internal::InverseFunctionHelper<GridFunctionType>::rC, + typename internal::InverseFunctionHelper<GridFunctionType>::R>; + using typename BaseType::E; using typename BaseType::LocalFunctionType; + using typename BaseType::R; - InverseGridFunction(const GridFunctionType& func, const int ord) - : func_(func) + InverseGridFunction(GridFunction<E, r_, rC_, R> func, const int ord, const std::string nm = "") + : func_(func.copy_as_grid_function()) , order_(ord) + , name_(nm.empty() ? ("inverse of " + func_->name()) : nm) {} - InverseGridFunction(std::shared_ptr<const GridFunctionType> func, const int ord) - : func_(func) + InverseGridFunction(GridFunctionInterface<E, r_, rC_, R>&& func, const int ord, const std::string nm = "") + : func_(std::move(func)) , order_(ord) + , name_(nm.empty() ? ("inverse of " + func_->name()) : nm) {} - InverseGridFunction(std::unique_ptr<const GridFunctionType>&& func, const int ord) - : func_(std::move(func)) - , order_(ord) + InverseGridFunction(const ThisType& other) + : BaseType(other) + , func_(other.func_->copy_as_grid_function()) + , order_(other.order_) {} + InverseGridFunction(ThisType&&) = default; + + +private: + ThisType* copy_as_grid_function_impl() const override + { + return new ThisType(*this); + } + +public: + std::unique_ptr<ThisType> copy_as_grid_function() const + { + return std::unique_ptr<ThisType>(this->copy_as_grid_function_impl()); + } std::unique_ptr<LocalFunctionType> local_function() const override final { using LocalFunction = InverseElementFunction<typename GridFunctionType::LocalFunctionType>; - return std::unique_ptr<LocalFunction>(new LocalFunction(std::move(func_.access().local_function()), order_)); + return std::make_unique<LocalFunction>(func_->local_function(), order_); } std::string name() const override final { - auto func_name = func_.access().name(); - return func_name.empty() ? ("dune.xt.functions.inversegridfunction") : ("inverse of " + func_name); + return name_; } private: - const XT::Common::ConstStorageProvider<GridFunctionType> func_; + const std::unique_ptr<GridFunctionInterface<E, r_, rC_, R>> func_; const int order_; + const std::string name_; }; // class InverseGridFunction @@ -234,7 +284,7 @@ auto inverse(ElementFunctionInterface<E, r, rC, R>& func, const int order) if constexpr (internal::InverseFunctionHelper<ElementFunctionInterface<E, r, rC, R>>::available) { return InverseElementFunction<ElementFunctionInterface<E, r, rC, R>>(func, order); } else { - static_assert(AlwaysFalse<R>::value, "No inverse implementation available"); + static_assert(AlwaysFalse<R>::value, "Not available for these dimensions!"); } } @@ -245,7 +295,7 @@ auto inverse(const FunctionInterface<d, r, rC, R>& func, const int order) if constexpr (internal::InverseFunctionHelper<FunctionInterface<d, r, rC, R>>::available) { return InverseFunction<FunctionInterface<d, r, rC, R>>(func, order); } else { - static_assert(AlwaysFalse<R>::value, "No inverse implementation available"); + static_assert(AlwaysFalse<R>::value, "Not available for these dimensions!"); } } @@ -256,7 +306,7 @@ auto inverse(const GridFunctionInterface<E, r, rC, R>& func, const int order) if constexpr (internal::InverseFunctionHelper<GridFunctionInterface<E, r, rC, R>>::available) { return InverseGridFunction<GridFunctionInterface<E, r, rC, R>>(func, order); } else { - static_assert(AlwaysFalse<R>::value, "No inverse implementation available"); + static_assert(AlwaysFalse<R>::value, "Not available for these dimensions!"); } } diff --git a/dune/xt/functions/spe10/model1.hh b/dune/xt/functions/spe10/model1.hh index c78b6fb6490f2fa88612439a8db08d60be2a6dc4..c6e298f3892f8e40324e78310bedf70a33238a04 100644 --- a/dune/xt/functions/spe10/model1.hh +++ b/dune/xt/functions/spe10/model1.hh @@ -60,10 +60,10 @@ public: } // ... static_id(...) private: - static std::vector<RangeType> read_values_from_file(const std::string& filename, - const RangeFieldType& min, - const RangeFieldType& max, - const RangeType& unit_range) + static std::shared_ptr<std::vector<RangeType>> read_values_from_file(const std::string& filename, + const RangeFieldType& min, + const RangeFieldType& max, + const RangeType& unit_range) { if (!(max > min)) @@ -76,11 +76,11 @@ private: DUNE_THROW(Exceptions::spe10_data_file_missing, "could not open '" << filename << "'!"); static constexpr size_t entriesPerDim = model1_x_elements * model1_y_elements * model1_z_elements; // create storage (there should be exactly 6000 values in the file, but we only read the first 2000) - std::vector<RangeType> data(entriesPerDim, unit_range); + auto data = std::make_shared<std::vector<RangeType>>(entriesPerDim, unit_range); double tmp = 0; size_t counter = 0; while (datafile >> tmp && counter < entriesPerDim) - data[counter++] *= (tmp * scale) + shift; + (*data)[counter++] *= (tmp * scale) + shift; datafile.close(); if (counter != entriesPerDim) DUNE_THROW(Dune::IOError, diff --git a/dune/xt/functions/spe10/model2.hh b/dune/xt/functions/spe10/model2.hh index 4464b5d2666e5c4547d1a3dcea7bd9129a7adcb2..10fb5a3f7ed01c09db80476c2b9b925fa97ad758 100644 --- a/dune/xt/functions/spe10/model2.hh +++ b/dune/xt/functions/spe10/model2.hh @@ -73,8 +73,8 @@ public: } // ... static_id(...) private: - static std::vector<RangeType> read_values_from_file(const std::string& filename, - const Common::FieldVector<size_t, domain_dim>& number_of_elements) + static std::shared_ptr<std::vector<RangeType>> + read_values_from_file(const std::string& filename, const Common::FieldVector<size_t, domain_dim>& number_of_elements) { // read all the data from the file @@ -104,12 +104,12 @@ private: // if (filecounter != 3366000) //#warning you are not using the entire data file. Use default number_of_elements instead. - std::vector<RangeType> data(entries_per_coordinate, RangeType(0)); + auto data = std::make_shared<std::vector<RangeType>>(entries_per_coordinate, RangeType(0)); for (size_t ii = 0; ii < entries_per_coordinate; ++ii) { for (size_t dim = 0; dim < domain_dim; ++dim) { const auto idx = ii + dim * entries_per_coordinate; - data[ii][dim][dim] = values_in_file[idx]; + (*data)[ii][dim][dim] = values_in_file[idx]; } } return data; diff --git a/dune/xt/functions/test/.gitignore b/dune/xt/functions/test/.gitignore deleted file mode 100644 index 6cc7cd31f48fdd0d5b7faa22d8441afe540f184e..0000000000000000000000000000000000000000 --- a/dune/xt/functions/test/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -# ~~~ -# This file is part of the dune-xt project: -# https://github.com/dune-community/dune-xt -# Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. -# License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) -# or GPL-2.0+ (http://opensource.org/licenses/gpl-license) -# with "runtime exception" (http://www.dune-project.org/license.html) -# Authors: -# Felix Schindler (2013, 2016 - 2017) -# René Fritze (2012, 2015 - 2019) -# Tobias Leibner (2016, 2020) -# ~~~ - -test_validation -*.o -*.gcda -*.gcno -common_color -common_logger -common_parameter_validation -function_expression_2 -common_math -common_profiler -common_string -common_typenames -data/ -fem_error -fem_projection -function_expression -grid_information -grid_provider -function.param -provider.param -pgfoutput_* -common_tuple -grid_output_pgf -functions_constant -functions_expression -functions_checkerboard -functions_functions -perm_case1.dat -!builder_definitions.cmake diff --git a/dune/xt/functions/type_traits.hh b/dune/xt/functions/type_traits.hh index 25966a89bd6943303e16b1154568ca9af094eda6..0bc32873a513792ce8807d91a6d3b708bf87c4ca 100644 --- a/dune/xt/functions/type_traits.hh +++ b/dune/xt/functions/type_traits.hh @@ -16,6 +16,7 @@ #include <dune/common/dynmatrix.hh> #include <dune/common/dynvector.hh> +#include <dune/xt/common/exceptions.hh> #include <dune/xt/common/fmatrix.hh> #include <dune/xt/common/fvector.hh> #include <dune/xt/common/type_traits.hh> @@ -125,8 +126,8 @@ struct RangeTypeSelector<R, r, 1> template <size_t d, class R, size_t r, size_t rC> struct DerivativeRangeTypeSelector { - using single_type = XT::Common::FieldVector<R, d>; - using return_single_type = FieldVector<R, d>; + using single_type = FieldVector<R, d>; + using return_single_type = XT::Common::FieldVector<R, d>; using dynamic_single_type = DynamicVector<R>; using row_derivative_type = FieldMatrix<R, rC, d>; @@ -284,12 +285,106 @@ struct is_grid_function<T, true> : std::is_base_of<GridFunctionInterface<typenam {}; -enum class CombinationType +template <class F> +struct as_element_function_interface +{ + static_assert(is_element_function<F>::value, ""); + using type = Functions::ElementFunctionInterface<typename F::E, F::r, F::rC, typename F::R>; +}; + +template <class F> +using as_element_function_interface_t = typename as_element_function_interface<F>::type; + + +template <class F> +struct as_function_interface +{ + static_assert(is_function<F>::value, ""); + using type = Functions::FunctionInterface<F::d, F::r, F::rC, typename F::R>; +}; + +template <class F> +using as_function_interface_t = typename as_function_interface<F>::type; + + +template <class F> +struct as_grid_function_interface +{ + static_assert(is_grid_function<F>::value, ""); + using type = Functions::GridFunctionInterface<typename F::E, F::r, F::rC, typename F::R>; +}; + +template <class F> +using as_grid_function_interface_t = typename as_grid_function_interface<F>::type; + + +struct CombinationType +{ + struct difference + {}; + struct fraction + {}; + struct product + {}; + struct sum + {}; +}; // struct CombinationType + + +template <typename CombinationType> +struct GetCombination +{ + static std::string name() + { + return get_combination_name(CombinationType()); + } + + static std::string symbol() + { + return get_combination_symbol(CombinationType()); + } +}; // struct GetCombination + + +inline std::string get_combination_name(CombinationType::difference) +{ + return "difference"; +} + +inline std::string get_combination_symbol(CombinationType::difference) +{ + return "-"; +} + +inline std::string get_combination_name(CombinationType::fraction) +{ + return "fraction"; +} + +inline std::string get_combination_symbol(CombinationType::fraction) +{ + return "/"; +} + +inline std::string get_combination_name(CombinationType::product) +{ + return "product"; +} + +inline std::string get_combination_symbol(CombinationType::product) +{ + return "*"; +} + +inline std::string get_combination_name(CombinationType::sum) +{ + return "sum"; +} + +inline std::string get_combination_symbol(CombinationType::sum) { - difference, - product, - sum -}; // enum class CombinationType + return "+"; +} enum class DerivativeType diff --git a/dune/xt/grid/element.hh b/dune/xt/grid/element.hh new file mode 100644 index 0000000000000000000000000000000000000000..f900f0c8ff7e4af91556d9588c9b2b789736a80d --- /dev/null +++ b/dune/xt/grid/element.hh @@ -0,0 +1,76 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#ifndef DUNE_XT_GRID_ELEMENT_HH +#define DUNE_XT_GRID_ELEMENT_HH + +#include <dune/grid/common/entity.hh> + +#include <dune/xt/common/numeric_cast.hh> +#include <dune/xt/grid/type_traits.hh> + +namespace Dune { +namespace XT { +namespace Grid { + + +template <class E> +class SubEntityCenter +{ + static_assert(is_entity<E>::value, ""); + using G = extract_grid_t<E>; + using D = typename G::ctype; + static const constexpr size_t d = G::dimension; + + template <int cd = d, bool anything = true> + struct subEntity + { + static FieldVector<D, d> center(const E& element, const int codim, const size_t i) + { + if (codim == cd) { + DUNE_THROW_IF(i >= element.subEntities(codim), + Common::Exceptions::index_out_of_range, + "element.subEntities(" << codim << ") = " << element.subEntities(codim) << "\n i = " << i); + return element.template subEntity<cd>(Common::numeric_cast<int>(i)).geometry().center(); + } else + return subEntity<cd - 1>::center(element, codim, i); + } // ... center(...) + }; // struct subEntity + + template <bool anything> + struct subEntity<0, anything> + { + static FieldVector<D, d> center(const E& element, const int codim, const size_t i) + { + DUNE_THROW_IF(codim != 0, Common::Exceptions::internal_error, "This must not happen"); + return element.template subEntity<0>(Common::numeric_cast<int>(i)).geometry().center(); + } + }; // struct subEntity + +public: + static FieldVector<D, d> get(const E& element, const int codim, const size_t i) + { + return subEntity<>::center(element, codim, i); + } +}; // class SubEntityCenter + + +template <int dim, class GridImp, template <int, int, class> class EntityImp> +FieldVector<typename GridImp::ctype, GridImp::dimension> +sub_entity_center(const Dune::Entity<0, dim, GridImp, EntityImp> element, const int codim, const size_t i) +{ + return SubEntityCenter<Dune::Entity<0, dim, GridImp, EntityImp>>::get(element, codim, i); +} + + +} // namespace Grid +} // namespace XT +} // namespace Dune + +#endif // DUNE_XT_GRID_ELEMENT_HH diff --git a/dune/xt/grid/filters/intersection.hh b/dune/xt/grid/filters/intersection.hh index 206163b6cdc1a65b998dcfc8450070a291a013d3..4ffa2d5e8658735de26c0997f6db366e9c720979 100644 --- a/dune/xt/grid/filters/intersection.hh +++ b/dune/xt/grid/filters/intersection.hh @@ -14,14 +14,15 @@ #include <functional> +#include <dune/grid/common/partitionset.hh> + #include <dune/xt/common/memory.hh> #include <dune/xt/common/timedlogging.hh> #include <dune/xt/grid/boundaryinfo.hh> #include <dune/xt/grid/print.hh> #include <dune/xt/grid/type_traits.hh> - -#include <dune/grid/common/partitionset.hh> +#include <dune/xt/grid/print.hh> #include "base.hh" diff --git a/dune/xt/grid/intersection.hh b/dune/xt/grid/intersection.hh index 0519110aad00197e070efa489c5819b1ece134b3..bc4ad8bf1379a1c6abb37d79066edb08add1b9ca 100644 --- a/dune/xt/grid/intersection.hh +++ b/dune/xt/grid/intersection.hh @@ -169,6 +169,7 @@ bool contains(const Dune::Intersection<G, I>& intersection, } // namespace XT +// DXT_DEPRECATED_MSG did not work here template <class G, class I> [[deprecated("Use out << print(intersection) from <dune/xt/grid/print.hh> instead (05.07.2020)!")]] void operator<<(std::ostream& /*out*/, const Dune::Intersection<G, I>& intersection) diff --git a/dune/xt/grid/mapper.hh b/dune/xt/grid/mapper.hh new file mode 100644 index 0000000000000000000000000000000000000000..c6b098d157d9e22a4ceef791a863d797dedcb6e6 --- /dev/null +++ b/dune/xt/grid/mapper.hh @@ -0,0 +1,88 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#ifndef DUNE_XT_GRID_MAPPER_HH +#define DUNE_XT_GRID_MAPPER_HH + +#include <dune/grid/common/mapper.hh> + +#include <dune/xt/common/numeric_cast.hh> +#include <dune/xt/grid/type_traits.hh> + +namespace Dune { +namespace XT { +namespace Grid { + + +template <class M, class E> +class SubEntityIndex +{ + static_assert(is_entity<E>::value, ""); + using G = extract_grid_t<E>; + using D = typename G::ctype; + static const constexpr size_t d = G::dimension; + + template <int cd = d, bool anything = true> + struct subEntity + { + static size_t index(const M& mapper, const E& element, const int codim, const size_t i) + { + if (codim == cd) { + DUNE_THROW_IF(i >= element.subEntities(codim), + Common::Exceptions::index_out_of_range, + "element.subEntities(" << codim << ") = " << element.subEntities(codim) << "\n i = " << i); + return Common::numeric_cast<size_t>(mapper.index(element.template subEntity<cd>(Common::numeric_cast<int>(i)))); + } else + return subEntity<cd - 1>::index(mapper, element, codim, i); + } // ... center(...) + }; // struct subEntity + + template <bool anything> + struct subEntity<0, anything> + { + static size_t index(const M& mapper, const E& element, const int codim, const size_t i) + { + DUNE_THROW_IF(codim != 0, Common::Exceptions::internal_error, "This must not happen"); + DUNE_THROW_IF(i >= element.subEntities(0), + Common::Exceptions::index_out_of_range, + "element.subEntities(0) = " << element.subEntities(0) << "\n i = " << i); + return Common::numeric_cast<size_t>(mapper.index(element.template subEntity<0>(Common::numeric_cast<int>(i)))); + } + }; // struct subEntity + +public: + static size_t get(const M& mapper, const E& element, const int codim, const size_t i) + { + return subEntity<>::index(mapper, element, codim, i); + } +}; // class SubEntityIndex + + +template <typename G, + typename MapperImp, + typename IndexType, + int dim, + class GridImp, + template <int, int, class> + class EntityImp> +size_t sub_entity_index(const Dune::Mapper<G, MapperImp, IndexType>& mapper, + const Dune::Entity<0, dim, GridImp, EntityImp> element, + const int codim, + const size_t i) +{ + return SubEntityIndex<Dune::Mapper<G, MapperImp, IndexType>, Dune::Entity<0, dim, GridImp, EntityImp>>::get( + mapper, element, codim, i); +} + + +} // namespace Grid +} // namespace XT +} // namespace Dune + +#endif // DUNE_XT_GRID_MAPPER_HH diff --git a/dune/xt/la/container/container-interface.hh b/dune/xt/la/container/container-interface.hh index 08b66562b61cba2544fe21f91a7e8c4a073403e8..7507ca3641b1e1912b5e85ace2bcb69b005382f7 100644 --- a/dune/xt/la/container/container-interface.hh +++ b/dune/xt/la/container/container-interface.hh @@ -167,6 +167,12 @@ public: return this->as_imp(); } + virtual derived_type& operator/=(const ScalarType& alpha) + { + scal(1. / alpha); + return this->as_imp(); + } + /** * \brief Multiplies every component of this by a scalar. * \param alpha The scalar. diff --git a/dune/xt/la/container/matrix-interface.hh b/dune/xt/la/container/matrix-interface.hh index 77c63f8a708cad0b339caea99344d1b093afc88e..1cccb033fec0a2ccd58b4f49de62a56e25094f91 100644 --- a/dune/xt/la/container/matrix-interface.hh +++ b/dune/xt/la/container/matrix-interface.hh @@ -417,11 +417,11 @@ protected: template <class MM> derived_type& add_assign(const MatrixInterface<MM, ScalarType>& other) { - const auto& other_pattern = other.pattern(); + const auto other_pattern = other.pattern(); #ifndef NDEBUG if (other.rows() != rows() || other.cols() != cols()) DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match, "Dimensions of matrices to be added do not match!"); - const auto& this_pattern = pattern(); + const auto this_pattern = pattern(); if (!this_pattern.contains(other_pattern)) DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match, "The matrix to be added contains entries that are not in this' pattern!"); @@ -435,11 +435,11 @@ protected: template <class MM> derived_type& subtract_assign(const MatrixInterface<MM, ScalarType>& other) { - const auto& other_pattern = other.pattern(); + const auto other_pattern = other.pattern(); #ifndef NDEBUG if (other.rows() != rows() || other.cols() != cols()) DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match, "Dimensions of matrices to be added do not match!"); - const auto& this_pattern = pattern(); + const auto this_pattern = pattern(); if (!this_pattern.contains(other_pattern)) DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match, "The matrix to be added contains entries that are not in this' pattern!"); diff --git a/dune/xt/test/functions/ESV2007_exact_solution.tpl b/dune/xt/test/functions/ESV2007_exact_solution.tpl index 3bf28205c281b3d2426f61ae1522461afc3dbdc4..568476cc6e54d666ff788d2e3e173b3ebf1f46a8 100644 --- a/dune/xt/test/functions/ESV2007_exact_solution.tpl +++ b/dune/xt/test/functions/ESV2007_exact_solution.tpl @@ -114,7 +114,7 @@ TEST_F(ESV2007ExactSolutionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, glo TEST_F(ESV2007ExactSolutionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, is_bindable) { FunctionType default_function(3); - const auto& localizable_function = default_function.template as_grid_function<ElementType>(); + auto&& localizable_function = default_function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -127,7 +127,7 @@ TEST_F(ESV2007ExactSolutionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, loc { const int expected_order = 3; FunctionType default_function(3); - const auto& localizable_function = default_function.template as_grid_function<ElementType>(); + auto&& localizable_function = default_function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -141,7 +141,7 @@ TEST_F(ESV2007ExactSolutionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, loc TEST_F(ESV2007ExactSolutionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_evaluate) { FunctionType function(3); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -160,7 +160,7 @@ TEST_F(ESV2007ExactSolutionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, loc TEST_F(ESV2007ExactSolutionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_jacobian) { FunctionType function(3); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { diff --git a/dune/xt/test/functions/ESV2007_force.tpl b/dune/xt/test/functions/ESV2007_force.tpl index a5e589fff454550a04a328aa94645d988eef9fb0..14704abe9e81ed95384559e31c614f65d8e906ca 100644 --- a/dune/xt/test/functions/ESV2007_force.tpl +++ b/dune/xt/test/functions/ESV2007_force.tpl @@ -114,7 +114,7 @@ TEST_F(ESV2007ForceFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, global_jaco TEST_F(ESV2007ForceFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, is_bindable) { FunctionType default_function(3); - const auto& localizable_function = default_function.template as_grid_function<ElementType>(); + auto&& localizable_function = default_function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -127,7 +127,7 @@ TEST_F(ESV2007ForceFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_order { const int expected_order = 3; FunctionType default_function(3); - const auto& localizable_function = default_function.template as_grid_function<ElementType>(); + auto&& localizable_function = default_function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -141,7 +141,7 @@ TEST_F(ESV2007ForceFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_order TEST_F(ESV2007ForceFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_evaluate) { FunctionType function(3); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -160,7 +160,7 @@ TEST_F(ESV2007ForceFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_evalu TEST_F(ESV2007ForceFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_jacobian) { FunctionType function(3); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { diff --git a/dune/xt/test/functions/constant.tpl b/dune/xt/test/functions/constant.tpl index 64ad07351e25eaf74451ceb4957a74a36315b30a..4a8154dca99f5bdf90142f92e315a524bb0ef4ca 100644 --- a/dune/xt/test/functions/constant.tpl +++ b/dune/xt/test/functions/constant.tpl @@ -109,7 +109,7 @@ TEST_F(ConstantFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, global_jacobian TEST_F(ConstantFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, is_bindable) { FunctionType function(1.); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -123,7 +123,7 @@ TEST_F(ConstantFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_order) for (auto vv : {-10., 3., 17., 41.}) { const RangeReturnType value(vv); FunctionType function(value); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -139,7 +139,7 @@ TEST_F(ConstantFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_evaluate) for (auto value : {-10., 3., 17., 41.}) { const RangeReturnType expected_value(value); FunctionType function(expected_value); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -160,7 +160,7 @@ TEST_F(ConstantFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_jacobian) DerivativeRangeReturnType expected_jacobian; //expected_jacobian *= 0; FunctionType function(value); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { diff --git a/dune/xt/test/functions/element_function_interface_operators.cc b/dune/xt/test/functions/element_function_interface_operators.cc new file mode 100644 index 0000000000000000000000000000000000000000..a982f75902c412329f7e3da39045cb992ff575f4 --- /dev/null +++ b/dune/xt/test/functions/element_function_interface_operators.cc @@ -0,0 +1,135 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + + +#include <dune/xt/test/main.hxx> // <- has to come first, include config.h! +#include <dune/xt/functions/grid-function.hh> + +using namespace Dune::XT; + +using E1 = Grid::extract_entity_t<YASP_1D_EQUIDISTANT_OFFSET>; +using E2 = Grid::extract_entity_t<YASP_2D_EQUIDISTANT_OFFSET>; + +#define VAL(r, rC) Functions::RangeTypeSelector<double, r, rC>::return_type(0) + + +template <class L, class R> +void test_difference(const L& left, const R& right) +{ + auto ll = left.local_function(); + auto lr = right.local_function(); + (*ll) - (*lr); +} + + +template <class L, class R> +void test_fraction(const L& left, const R& right) +{ + auto ll = left.local_function(); + auto lr = right.local_function(); + (*ll) / (*lr); +} + + +template <class L, class R> +void test_product(const L& left, const R& right) +{ + auto ll = left.local_function(); + auto lr = right.local_function(); + (*ll) * (*lr); +} + + +template <class L, class R> +void test_sum(const L& left, const R& right) +{ + auto ll = left.local_function(); + auto lr = right.local_function(); + (*ll) + (*lr); +} + + +GTEST_TEST(grid_function_interface_operators, main) +{ + test_difference(Functions::GridFunction<E1, 1, 1>(VAL(1, 1)), Functions::GridFunction<E1, 1, 1>(VAL(1, 1))); + test_difference(Functions::GridFunction<E2, 1, 1>(VAL(1, 1)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_difference(Functions::GridFunction<E2, 1, 2>(VAL(1, 2)), Functions::GridFunction<E2, 1, 2>(VAL(1, 2))); + test_difference(Functions::GridFunction<E2, 1, 3>(VAL(1, 3)), Functions::GridFunction<E2, 1, 3>(VAL(1, 3))); + test_difference(Functions::GridFunction<E2, 2, 1>(VAL(2, 1)), Functions::GridFunction<E2, 2, 1>(VAL(2, 1))); + test_difference(Functions::GridFunction<E2, 2, 2>(VAL(2, 2)), Functions::GridFunction<E2, 2, 2>(VAL(2, 2))); + test_difference(Functions::GridFunction<E2, 2, 3>(VAL(2, 3)), Functions::GridFunction<E2, 2, 3>(VAL(2, 3))); + test_difference(Functions::GridFunction<E2, 3, 1>(VAL(3, 1)), Functions::GridFunction<E2, 3, 1>(VAL(3, 1))); + test_difference(Functions::GridFunction<E2, 3, 2>(VAL(3, 2)), Functions::GridFunction<E2, 3, 2>(VAL(3, 2))); + test_difference(Functions::GridFunction<E2, 3, 3>(VAL(3, 3)), Functions::GridFunction<E2, 3, 3>(VAL(3, 3))); + + test_sum(Functions::GridFunction<E1, 1, 1>(VAL(1, 1)), Functions::GridFunction<E1, 1, 1>(VAL(1, 1))); + test_sum(Functions::GridFunction<E2, 1, 1>(VAL(1, 1)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_sum(Functions::GridFunction<E2, 1, 2>(VAL(1, 2)), Functions::GridFunction<E2, 1, 2>(VAL(1, 2))); + test_sum(Functions::GridFunction<E2, 1, 3>(VAL(1, 3)), Functions::GridFunction<E2, 1, 3>(VAL(1, 3))); + test_sum(Functions::GridFunction<E2, 2, 1>(VAL(2, 1)), Functions::GridFunction<E2, 2, 1>(VAL(2, 1))); + test_sum(Functions::GridFunction<E2, 2, 2>(VAL(2, 2)), Functions::GridFunction<E2, 2, 2>(VAL(2, 2))); + test_sum(Functions::GridFunction<E2, 2, 3>(VAL(2, 3)), Functions::GridFunction<E2, 2, 3>(VAL(2, 3))); + test_sum(Functions::GridFunction<E2, 3, 1>(VAL(3, 1)), Functions::GridFunction<E2, 3, 1>(VAL(3, 1))); + test_sum(Functions::GridFunction<E2, 3, 2>(VAL(3, 2)), Functions::GridFunction<E2, 3, 2>(VAL(3, 2))); + test_sum(Functions::GridFunction<E2, 3, 3>(VAL(3, 3)), Functions::GridFunction<E2, 3, 3>(VAL(3, 3))); + + test_fraction(Functions::GridFunction<E1, 1, 1>(VAL(1, 1)), Functions::GridFunction<E1, 1, 1>(VAL(1, 1))); + test_fraction(Functions::GridFunction<E2, 1, 1>(VAL(1, 1)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_fraction(Functions::GridFunction<E2, 1, 2>(VAL(1, 2)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_fraction(Functions::GridFunction<E2, 1, 3>(VAL(1, 3)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_fraction(Functions::GridFunction<E2, 2, 1>(VAL(2, 1)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_fraction(Functions::GridFunction<E2, 2, 2>(VAL(2, 2)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_fraction(Functions::GridFunction<E2, 2, 3>(VAL(2, 3)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_fraction(Functions::GridFunction<E2, 3, 1>(VAL(3, 1)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_fraction(Functions::GridFunction<E2, 3, 2>(VAL(3, 2)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_fraction(Functions::GridFunction<E2, 3, 3>(VAL(3, 3)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + + test_product(Functions::GridFunction<E1, 1, 1>(VAL(1, 1)), Functions::GridFunction<E1, 1, 1>(VAL(1, 1))); + test_product(Functions::GridFunction<E2, 1, 1>(VAL(1, 1)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_product(Functions::GridFunction<E2, 1, 2>(VAL(1, 2)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_product(Functions::GridFunction<E2, 1, 3>(VAL(1, 3)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_product(Functions::GridFunction<E2, 2, 1>(VAL(2, 1)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_product(Functions::GridFunction<E2, 2, 2>(VAL(2, 2)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_product(Functions::GridFunction<E2, 2, 3>(VAL(2, 3)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_product(Functions::GridFunction<E2, 3, 1>(VAL(3, 1)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_product(Functions::GridFunction<E2, 3, 2>(VAL(3, 2)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + test_product(Functions::GridFunction<E2, 3, 3>(VAL(3, 3)), Functions::GridFunction<E2, 1, 1>(VAL(1, 1))); + + test_product(Functions::GridFunction<E2, 1, 2>(VAL(1, 2)), Functions::GridFunction<E2, 2, 1>(VAL(2, 1))); + test_product(Functions::GridFunction<E2, 1, 2>(VAL(1, 2)), Functions::GridFunction<E2, 2, 2>(VAL(2, 2))); + test_product(Functions::GridFunction<E2, 1, 2>(VAL(1, 2)), Functions::GridFunction<E2, 2, 3>(VAL(2, 3))); + + test_product(Functions::GridFunction<E2, 1, 3>(VAL(1, 3)), Functions::GridFunction<E2, 3, 1>(VAL(3, 1))); + test_product(Functions::GridFunction<E2, 1, 3>(VAL(1, 3)), Functions::GridFunction<E2, 3, 2>(VAL(3, 2))); + test_product(Functions::GridFunction<E2, 1, 3>(VAL(1, 3)), Functions::GridFunction<E2, 3, 3>(VAL(3, 3))); + + test_product(Functions::GridFunction<E2, 2, 1>(VAL(2, 1)), Functions::GridFunction<E2, 1, 2>(VAL(1, 2))); + test_product(Functions::GridFunction<E2, 2, 1>(VAL(2, 1)), Functions::GridFunction<E2, 1, 3>(VAL(1, 3))); + test_product(Functions::GridFunction<E2, 2, 1>(VAL(2, 1)), Functions::GridFunction<E2, 2, 1>(VAL(2, 1))); + + test_product(Functions::GridFunction<E2, 2, 2>(VAL(2, 2)), Functions::GridFunction<E2, 2, 1>(VAL(2, 1))); + test_product(Functions::GridFunction<E2, 2, 2>(VAL(2, 2)), Functions::GridFunction<E2, 2, 2>(VAL(2, 2))); + test_product(Functions::GridFunction<E2, 2, 2>(VAL(2, 2)), Functions::GridFunction<E2, 2, 3>(VAL(2, 3))); + + test_product(Functions::GridFunction<E2, 2, 3>(VAL(2, 3)), Functions::GridFunction<E2, 3, 1>(VAL(3, 1))); + test_product(Functions::GridFunction<E2, 2, 3>(VAL(2, 3)), Functions::GridFunction<E2, 3, 2>(VAL(3, 2))); + test_product(Functions::GridFunction<E2, 2, 3>(VAL(2, 3)), Functions::GridFunction<E2, 3, 3>(VAL(3, 3))); + + test_product(Functions::GridFunction<E2, 3, 1>(VAL(3, 1)), Functions::GridFunction<E2, 1, 2>(VAL(1, 2))); + test_product(Functions::GridFunction<E2, 3, 1>(VAL(3, 1)), Functions::GridFunction<E2, 1, 3>(VAL(1, 3))); + test_product(Functions::GridFunction<E2, 3, 1>(VAL(3, 1)), Functions::GridFunction<E2, 3, 1>(VAL(3, 1))); + + test_product(Functions::GridFunction<E2, 3, 2>(VAL(3, 2)), Functions::GridFunction<E2, 2, 1>(VAL(2, 1))); + test_product(Functions::GridFunction<E2, 3, 2>(VAL(3, 2)), Functions::GridFunction<E2, 2, 2>(VAL(2, 2))); + test_product(Functions::GridFunction<E2, 3, 2>(VAL(3, 2)), Functions::GridFunction<E2, 2, 3>(VAL(2, 3))); + + test_product(Functions::GridFunction<E2, 3, 3>(VAL(3, 3)), Functions::GridFunction<E2, 3, 1>(VAL(3, 1))); + test_product(Functions::GridFunction<E2, 3, 3>(VAL(3, 3)), Functions::GridFunction<E2, 3, 2>(VAL(3, 2))); + test_product(Functions::GridFunction<E2, 3, 3>(VAL(3, 3)), Functions::GridFunction<E2, 3, 3>(VAL(3, 3))); +} diff --git a/dune/xt/test/functions/expression_matrix_valued.tpl b/dune/xt/test/functions/expression_matrix_valued.tpl index ddfe0bf315604bc3f83fd100197f70cc17db1859..b4551942d2cf5dd33b5057a16811cf5ea91b8cd9 100644 --- a/dune/xt/test/functions/expression_matrix_valued.tpl +++ b/dune/xt/test/functions/expression_matrix_valued.tpl @@ -199,7 +199,7 @@ TEST_F(ExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, is_bindable) RangeExpressionType expr_1(std::string("x[0]*x[0]")); FunctionType default_function("x", expr_1, 2); - const auto& localizable_function = default_function.template as_grid_function<ElementType>(); + auto&& localizable_function = default_function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); @@ -218,7 +218,7 @@ TEST_F(ExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_order) const auto leaf_view = grid_.leaf_view(); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : Dune::elements(leaf_view)) { local_f->bind(element); @@ -236,7 +236,7 @@ TEST_F(ExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_evaluat const RangeReturnType expected_value(value); const RangeExpressionType constant_expr(Common::to_string(value)); FunctionType function("x", constant_expr, 0); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : Dune::elements(leaf_view)) { local_f->bind(element); @@ -261,7 +261,7 @@ TEST_F(ExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_jacobia DerivativeRangeExpressionType constant_grad(constant_grad_single); DerivativeRangeReturnType expected_jacobian(Common::FieldMatrix<double, rC, d>(0.)); FunctionType function("x", constant_expr, constant_grad, 0); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : Dune::elements(leaf_view)) { local_f->bind(element); diff --git a/dune/xt/test/functions/expression_parametric.tpl b/dune/xt/test/functions/expression_parametric.tpl index ca10ab8491aaa24529dde55f6d1196515a022178..d6f3b4b5b8b274c72c543dba82df7a5ba49bd68d 100644 --- a/dune/xt/test/functions/expression_parametric.tpl +++ b/dune/xt/test/functions/expression_parametric.tpl @@ -102,7 +102,7 @@ TEST_F(ParametricExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, is_ const RangeExpressionType expr(std::string("sin(x[0]t_)")); FunctionType function("x", {"t_", 1}, expr, 3); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : Dune::elements(leaf_view)) { @@ -119,7 +119,7 @@ TEST_F(ParametricExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, loc const auto leaf_view = grid_.leaf_view(); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : Dune::elements(leaf_view)) { local_f->bind(element); @@ -134,7 +134,7 @@ TEST_F(ParametricExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, loc const RangeExpressionType expr(std::string("sin(x[0]t_)")); FunctionType function("x", {"t_", 1}, expr, 3); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : Dune::elements(leaf_view)) { const auto geometry = element.geometry(); diff --git a/dune/xt/test/functions/expression_vector_valued.tpl b/dune/xt/test/functions/expression_vector_valued.tpl index ddccfabf4317c23552c06091271f030e36dcb880..3f03849e3fa3279eaaad11f5919ee2de363ad77e 100644 --- a/dune/xt/test/functions/expression_vector_valued.tpl +++ b/dune/xt/test/functions/expression_vector_valued.tpl @@ -200,7 +200,7 @@ TEST_F(ExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, is_bindable) RangeExpressionType expr_1(std::string("x[0]*x[0]")); FunctionType default_function("x", expr_1, 2); - const auto& localizable_function = default_function.template as_grid_function<ElementType>(); + auto&& localizable_function = default_function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); @@ -219,7 +219,7 @@ TEST_F(ExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_order) const auto leaf_view = grid_.leaf_view(); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : Dune::elements(leaf_view)) { local_f->bind(element); @@ -237,7 +237,7 @@ TEST_F(ExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_evaluat const RangeReturnType expected_value(value); const RangeExpressionType constant_expr(Common::to_string(value)); FunctionType function("x", constant_expr, 0); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : Dune::elements(leaf_view)) { local_f->bind(element); @@ -264,7 +264,7 @@ TEST_F(ExpressionFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_jacobia } const DerivativeRangeReturnType expected_jacobian; FunctionType function("x", constant_expr, constant_grad, 0); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : Dune::elements(leaf_view)) { local_f->bind(element); diff --git a/dune/xt/test/functions/flattop.tpl b/dune/xt/test/functions/flattop.tpl index 5b742c4759d7484def3b118392429eab9e7c4448..18173c38e947a7f9e1d027c8b8f53a9f6f83efb3 100644 --- a/dune/xt/test/functions/flattop.tpl +++ b/dune/xt/test/functions/flattop.tpl @@ -120,7 +120,7 @@ TEST_F(FlattopFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, is_bindable) const DomainType delta(1e-6); const double top_value = 20; FunctionType function(left, right, delta, top_value); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -137,7 +137,7 @@ TEST_F(FlattopFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_order) const DomainType delta(1e-6); const double top_value = 20; FunctionType function(left, right, delta, top_value); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -155,7 +155,7 @@ TEST_F(FlattopFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_evaluate) const DomainType delta(1e-6); const double top_value = 20; FunctionType func(left, right, delta, top_value); - const auto& localizable_function = func.template as_grid_function<ElementType>(); + auto&& localizable_function = func.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { diff --git a/dune/xt/test/functions/function_interface_operators.cc b/dune/xt/test/functions/function_interface_operators.cc new file mode 100644 index 0000000000000000000000000000000000000000..345228ebb1d1a2e5b4438ae04152f90bfd293530 --- /dev/null +++ b/dune/xt/test/functions/function_interface_operators.cc @@ -0,0 +1,94 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + + +#include <dune/xt/test/main.hxx> // <- has to come first, include config.h! +#include <dune/xt/functions/constant.hh> + + +GTEST_TEST(function_interface_operators, main) +{ + using namespace Dune::XT; + + Functions::ConstantFunction<1, 1, 1>({}) - Functions::ConstantFunction<1, 1, 1>({}); + Functions::ConstantFunction<2, 1, 1>({}) - Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 1, 2>({}) - Functions::ConstantFunction<2, 1, 2>({}); + Functions::ConstantFunction<2, 1, 3>({}) - Functions::ConstantFunction<2, 1, 3>({}); + Functions::ConstantFunction<2, 2, 1>({}) - Functions::ConstantFunction<2, 2, 1>({}); + Functions::ConstantFunction<2, 2, 2>({}) - Functions::ConstantFunction<2, 2, 2>({}); + Functions::ConstantFunction<2, 2, 3>({}) - Functions::ConstantFunction<2, 2, 3>({}); + Functions::ConstantFunction<2, 3, 1>({}) - Functions::ConstantFunction<2, 3, 1>({}); + Functions::ConstantFunction<2, 3, 2>({}) - Functions::ConstantFunction<2, 3, 2>({}); + Functions::ConstantFunction<2, 3, 3>({}) - Functions::ConstantFunction<2, 3, 3>({}); + + Functions::ConstantFunction<1, 1, 1>({}) + Functions::ConstantFunction<1, 1, 1>({}); + Functions::ConstantFunction<2, 1, 1>({}) + Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 1, 2>({}) + Functions::ConstantFunction<2, 1, 2>({}); + Functions::ConstantFunction<2, 1, 3>({}) + Functions::ConstantFunction<2, 1, 3>({}); + Functions::ConstantFunction<2, 2, 1>({}) + Functions::ConstantFunction<2, 2, 1>({}); + Functions::ConstantFunction<2, 2, 2>({}) + Functions::ConstantFunction<2, 2, 2>({}); + Functions::ConstantFunction<2, 2, 3>({}) + Functions::ConstantFunction<2, 2, 3>({}); + Functions::ConstantFunction<2, 3, 1>({}) + Functions::ConstantFunction<2, 3, 1>({}); + Functions::ConstantFunction<2, 3, 2>({}) + Functions::ConstantFunction<2, 3, 2>({}); + Functions::ConstantFunction<2, 3, 3>({}) + Functions::ConstantFunction<2, 3, 3>({}); + + Functions::ConstantFunction<1, 1, 1>({}) / Functions::ConstantFunction<1, 1, 1>({}); + Functions::ConstantFunction<2, 1, 1>({}) / Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 1, 2>({}) / Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 1, 3>({}) / Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 2, 1>({}) / Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 2, 2>({}) / Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 2, 3>({}) / Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 3, 1>({}) / Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 3, 2>({}) / Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 3, 3>({}) / Functions::ConstantFunction<2, 1, 1>({}); + + Functions::ConstantFunction<1, 1, 1>({}) * Functions::ConstantFunction<1, 1, 1>({}); + Functions::ConstantFunction<2, 1, 1>({}) * Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 1, 2>({}) * Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 1, 3>({}) * Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 2, 1>({}) * Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 2, 2>({}) * Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 2, 3>({}) * Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 3, 1>({}) * Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 3, 2>({}) * Functions::ConstantFunction<2, 1, 1>({}); + Functions::ConstantFunction<2, 3, 3>({}) * Functions::ConstantFunction<2, 1, 1>({}); + + Functions::ConstantFunction<2, 1, 2>({}) * Functions::ConstantFunction<2, 2, 1>({}); + Functions::ConstantFunction<2, 1, 2>({}) * Functions::ConstantFunction<2, 2, 2>({}); + Functions::ConstantFunction<2, 1, 2>({}) * Functions::ConstantFunction<2, 2, 3>({}); + + Functions::ConstantFunction<2, 1, 3>({}) * Functions::ConstantFunction<2, 3, 1>({}); + Functions::ConstantFunction<2, 1, 3>({}) * Functions::ConstantFunction<2, 3, 2>({}); + Functions::ConstantFunction<2, 1, 3>({}) * Functions::ConstantFunction<2, 3, 3>({}); + + Functions::ConstantFunction<2, 2, 1>({}) * Functions::ConstantFunction<2, 1, 2>({}); + Functions::ConstantFunction<2, 2, 1>({}) * Functions::ConstantFunction<2, 1, 3>({}); + Functions::ConstantFunction<2, 2, 1>({}) * Functions::ConstantFunction<2, 2, 1>({}); + + Functions::ConstantFunction<2, 2, 2>({}) * Functions::ConstantFunction<2, 2, 1>({}); + Functions::ConstantFunction<2, 2, 2>({}) * Functions::ConstantFunction<2, 2, 2>({}); + Functions::ConstantFunction<2, 2, 2>({}) * Functions::ConstantFunction<2, 2, 3>({}); + + Functions::ConstantFunction<2, 2, 3>({}) * Functions::ConstantFunction<2, 3, 1>({}); + Functions::ConstantFunction<2, 2, 3>({}) * Functions::ConstantFunction<2, 3, 2>({}); + Functions::ConstantFunction<2, 2, 3>({}) * Functions::ConstantFunction<2, 3, 3>({}); + + Functions::ConstantFunction<2, 3, 1>({}) * Functions::ConstantFunction<2, 1, 2>({}); + Functions::ConstantFunction<2, 3, 1>({}) * Functions::ConstantFunction<2, 1, 3>({}); + Functions::ConstantFunction<2, 3, 1>({}) * Functions::ConstantFunction<2, 3, 1>({}); + + Functions::ConstantFunction<2, 3, 2>({}) * Functions::ConstantFunction<2, 2, 1>({}); + Functions::ConstantFunction<2, 3, 2>({}) * Functions::ConstantFunction<2, 2, 2>({}); + Functions::ConstantFunction<2, 3, 2>({}) * Functions::ConstantFunction<2, 2, 3>({}); + + Functions::ConstantFunction<2, 3, 3>({}) * Functions::ConstantFunction<2, 3, 1>({}); + Functions::ConstantFunction<2, 3, 3>({}) * Functions::ConstantFunction<2, 3, 2>({}); + Functions::ConstantFunction<2, 3, 3>({}) * Functions::ConstantFunction<2, 3, 3>({}); +} diff --git a/dune/xt/test/functions/generic_function.tpl b/dune/xt/test/functions/generic_function.tpl index 5e82716c6d883fb076eacb9b836506f957983c44..f5a0a4be6fcc3206824def7594921d04a9e56d5e 100644 --- a/dune/xt/test/functions/generic_function.tpl +++ b/dune/xt/test/functions/generic_function.tpl @@ -97,7 +97,7 @@ TEST_F(GenericFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, global_jacobian) TEST_F(GenericFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, is_bindable) { LambdaType function(1.); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -110,7 +110,7 @@ TEST_F(GenericFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_order) for (auto vv : {1, 3, 5}) { const int expected_order = vv; LambdaType function(vv); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -127,7 +127,7 @@ TEST_F(GenericFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_evaluate) [](const auto& xx, const auto& param) { RangeReturnType ret(std::pow(xx[0], param.get("power").at(0))); return ret;}, "x_power_p", Common::ParameterType("power", 1)); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { @@ -151,7 +151,7 @@ TEST_F(GenericFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_jacobian) "jacobian.function", {}, [](const auto& /*xx*/, const auto& /*param*/) { return DerivativeRangeReturnType();}); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : Dune::elements(leaf_view)) { diff --git a/dune/xt/test/functions/grid_function_interface_operators.cc b/dune/xt/test/functions/grid_function_interface_operators.cc new file mode 100644 index 0000000000000000000000000000000000000000..de912a85bce2b87f0737aef077639033a04da064 --- /dev/null +++ b/dune/xt/test/functions/grid_function_interface_operators.cc @@ -0,0 +1,99 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + + +#include <dune/xt/test/main.hxx> // <- has to come first, include config.h! +#include <dune/xt/functions/grid-function.hh> + +using namespace Dune::XT; + +using E1 = Grid::extract_entity_t<YASP_1D_EQUIDISTANT_OFFSET>; +using E2 = Grid::extract_entity_t<YASP_2D_EQUIDISTANT_OFFSET>; + +#define VAL(r, rC) Functions::RangeTypeSelector<double, r, rC>::return_type(0) + + +GTEST_TEST(grid_function_interface_operators, main) +{ + Functions::GridFunction<E1, 1, 1>(VAL(1, 1)) - Functions::GridFunction<E1, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 1>(VAL(1, 1)) - Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 2>(VAL(1, 2)) - Functions::GridFunction<E2, 1, 2>(VAL(1, 2)); + Functions::GridFunction<E2, 1, 3>(VAL(1, 3)) - Functions::GridFunction<E2, 1, 3>(VAL(1, 3)); + Functions::GridFunction<E2, 2, 1>(VAL(2, 1)) - Functions::GridFunction<E2, 2, 1>(VAL(2, 1)); + Functions::GridFunction<E2, 2, 2>(VAL(2, 2)) - Functions::GridFunction<E2, 2, 2>(VAL(2, 2)); + Functions::GridFunction<E2, 2, 3>(VAL(2, 3)) - Functions::GridFunction<E2, 2, 3>(VAL(2, 3)); + Functions::GridFunction<E2, 3, 1>(VAL(3, 1)) - Functions::GridFunction<E2, 3, 1>(VAL(3, 1)); + Functions::GridFunction<E2, 3, 2>(VAL(3, 2)) - Functions::GridFunction<E2, 3, 2>(VAL(3, 2)); + Functions::GridFunction<E2, 3, 3>(VAL(3, 3)) - Functions::GridFunction<E2, 3, 3>(VAL(3, 3)); + + Functions::GridFunction<E1, 1, 1>(VAL(1, 1)) + Functions::GridFunction<E1, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 1>(VAL(1, 1)) + Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 2>(VAL(1, 2)) + Functions::GridFunction<E2, 1, 2>(VAL(1, 2)); + Functions::GridFunction<E2, 1, 3>(VAL(1, 3)) + Functions::GridFunction<E2, 1, 3>(VAL(1, 3)); + Functions::GridFunction<E2, 2, 1>(VAL(2, 1)) + Functions::GridFunction<E2, 2, 1>(VAL(2, 1)); + Functions::GridFunction<E2, 2, 2>(VAL(2, 2)) + Functions::GridFunction<E2, 2, 2>(VAL(2, 2)); + Functions::GridFunction<E2, 2, 3>(VAL(2, 3)) + Functions::GridFunction<E2, 2, 3>(VAL(2, 3)); + Functions::GridFunction<E2, 3, 1>(VAL(3, 1)) + Functions::GridFunction<E2, 3, 1>(VAL(3, 1)); + Functions::GridFunction<E2, 3, 2>(VAL(3, 2)) + Functions::GridFunction<E2, 3, 2>(VAL(3, 2)); + Functions::GridFunction<E2, 3, 3>(VAL(3, 3)) + Functions::GridFunction<E2, 3, 3>(VAL(3, 3)); + + Functions::GridFunction<E1, 1, 1>(VAL(1, 1)) / Functions::GridFunction<E1, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 1>(VAL(1, 1)) / Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 2>(VAL(1, 2)) / Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 3>(VAL(1, 3)) / Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 2, 1>(VAL(2, 1)) / Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 2, 2>(VAL(2, 2)) / Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 2, 3>(VAL(2, 3)) / Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 3, 1>(VAL(3, 1)) / Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 3, 2>(VAL(3, 2)) / Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 3, 3>(VAL(3, 3)) / Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + + Functions::GridFunction<E1, 1, 1>(VAL(1, 1)) * Functions::GridFunction<E1, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 1>(VAL(1, 1)) * Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 2>(VAL(1, 2)) * Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 1, 3>(VAL(1, 3)) * Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 2, 1>(VAL(2, 1)) * Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 2, 2>(VAL(2, 2)) * Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 2, 3>(VAL(2, 3)) * Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 3, 1>(VAL(3, 1)) * Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 3, 2>(VAL(3, 2)) * Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + Functions::GridFunction<E2, 3, 3>(VAL(3, 3)) * Functions::GridFunction<E2, 1, 1>(VAL(1, 1)); + + Functions::GridFunction<E2, 1, 2>(VAL(1, 2)) * Functions::GridFunction<E2, 2, 1>(VAL(2, 1)); + Functions::GridFunction<E2, 1, 2>(VAL(1, 2)) * Functions::GridFunction<E2, 2, 2>(VAL(2, 2)); + Functions::GridFunction<E2, 1, 2>(VAL(1, 2)) * Functions::GridFunction<E2, 2, 3>(VAL(2, 3)); + + Functions::GridFunction<E2, 1, 3>(VAL(1, 3)) * Functions::GridFunction<E2, 3, 1>(VAL(3, 1)); + Functions::GridFunction<E2, 1, 3>(VAL(1, 3)) * Functions::GridFunction<E2, 3, 2>(VAL(3, 2)); + Functions::GridFunction<E2, 1, 3>(VAL(1, 3)) * Functions::GridFunction<E2, 3, 3>(VAL(3, 3)); + + Functions::GridFunction<E2, 2, 1>(VAL(2, 1)) * Functions::GridFunction<E2, 1, 2>(VAL(1, 2)); + Functions::GridFunction<E2, 2, 1>(VAL(2, 1)) * Functions::GridFunction<E2, 1, 3>(VAL(1, 3)); + Functions::GridFunction<E2, 2, 1>(VAL(2, 1)) * Functions::GridFunction<E2, 2, 1>(VAL(2, 1)); + + Functions::GridFunction<E2, 2, 2>(VAL(2, 2)) * Functions::GridFunction<E2, 2, 1>(VAL(2, 1)); + Functions::GridFunction<E2, 2, 2>(VAL(2, 2)) * Functions::GridFunction<E2, 2, 2>(VAL(2, 2)); + Functions::GridFunction<E2, 2, 2>(VAL(2, 2)) * Functions::GridFunction<E2, 2, 3>(VAL(2, 3)); + + Functions::GridFunction<E2, 2, 3>(VAL(2, 3)) * Functions::GridFunction<E2, 3, 1>(VAL(3, 1)); + Functions::GridFunction<E2, 2, 3>(VAL(2, 3)) * Functions::GridFunction<E2, 3, 2>(VAL(3, 2)); + Functions::GridFunction<E2, 2, 3>(VAL(2, 3)) * Functions::GridFunction<E2, 3, 3>(VAL(3, 3)); + + Functions::GridFunction<E2, 3, 1>(VAL(3, 1)) * Functions::GridFunction<E2, 1, 2>(VAL(1, 2)); + Functions::GridFunction<E2, 3, 1>(VAL(3, 1)) * Functions::GridFunction<E2, 1, 3>(VAL(1, 3)); + Functions::GridFunction<E2, 3, 1>(VAL(3, 1)) * Functions::GridFunction<E2, 3, 1>(VAL(3, 1)); + + Functions::GridFunction<E2, 3, 2>(VAL(3, 2)) * Functions::GridFunction<E2, 2, 1>(VAL(2, 1)); + Functions::GridFunction<E2, 3, 2>(VAL(3, 2)) * Functions::GridFunction<E2, 2, 2>(VAL(2, 2)); + Functions::GridFunction<E2, 3, 2>(VAL(3, 2)) * Functions::GridFunction<E2, 2, 3>(VAL(2, 3)); + + Functions::GridFunction<E2, 3, 3>(VAL(3, 3)) * Functions::GridFunction<E2, 3, 1>(VAL(3, 1)); + Functions::GridFunction<E2, 3, 3>(VAL(3, 3)) * Functions::GridFunction<E2, 3, 2>(VAL(3, 2)); + Functions::GridFunction<E2, 3, 3>(VAL(3, 3)) * Functions::GridFunction<E2, 3, 3>(VAL(3, 3)); +} diff --git a/dune/xt/test/functions/indicator_function.tpl b/dune/xt/test/functions/indicator_function.tpl index cbd5e51edaeded05dcb0baa21852b1ca87582bf8..8eaefcebfaebf4d8bd3dce90bab0785afacc1dca 100644 --- a/dune/xt/test/functions/indicator_function.tpl +++ b/dune/xt/test/functions/indicator_function.tpl @@ -186,7 +186,7 @@ TEST_F(IndicatorFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, is_bindable) RangeType first_value(1.); FunctionType default_function({std::make_tuple(lower_left, upper_right, first_value)}); - const auto& localizable_function = default_function.template as_grid_function<ElementType>(); + auto&& localizable_function = default_function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); const auto leaf_view = grid_.leaf_view(); for (auto&& element : elements(leaf_view)) { @@ -205,7 +205,7 @@ TEST_F(IndicatorFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_order) for (auto vv : {1., 2., 3., 4.}) { RangeType value(vv); FunctionType function({std::make_tuple(lower_left, upper_right, value)}); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : elements(leaf_view)) { local_f->bind(element); @@ -229,7 +229,7 @@ TEST_F(IndicatorFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_evaluate for (auto vv : {1., 2., 3., 4.}) { RangeType value(vv); FunctionType function({std::make_tuple(lower_left, upper_right, value)}); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : elements(leaf_view)) { local_f->bind(element); @@ -313,7 +313,7 @@ TEST_F(IndicatorFunction_from_{{GRIDNAME}}_to_{{r}}_times_{{rC}}, local_jacobian for (auto vv : {1., 2., 3., 4.}) { RangeType value(vv); FunctionType function({std::make_tuple(lower_left, upper_right, value)}); - const auto& localizable_function = function.template as_grid_function<ElementType>(); + auto&& localizable_function = function.template as_grid_function<ElementType>(); auto local_f = localizable_function.local_function(); for (auto&& element : elements(leaf_view)) { local_f->bind(element); diff --git a/python/dune/xt/functions/CMakeLists.txt b/python/dune/xt/functions/CMakeLists.txt index 46fcaf780c485dcfbde4051dc0822b8d07158dfd..3212c5ac29bc06393c19c3c67cece795df13d8ef 100644 --- a/python/dune/xt/functions/CMakeLists.txt +++ b/python/dune/xt/functions/CMakeLists.txt @@ -14,14 +14,20 @@ dune_pybindxi_add_module(_functions_checkerboard EXCLUDE_FROM_ALL checkerboard.cc) dune_pybindxi_add_module(_functions_constant EXCLUDE_FROM_ALL constant.cc) +dune_pybindxi_add_module(_functions_elementwise_diameter EXCLUDE_FROM_ALL elementwise-diameter.cc) +dune_pybindxi_add_module(_functions_elementwise_minimum EXCLUDE_FROM_ALL elementwise-minimum.cc) dune_pybindxi_add_module(_functions_expression EXCLUDE_FROM_ALL expression.cc) +dune_pybindxi_add_module(_functions_divergence EXCLUDE_FROM_ALL divergence.cc) dune_pybindxi_add_module(_functions_function_as_grid_function EXCLUDE_FROM_ALL function-as-grid-function.cc) dune_pybindxi_add_module(_functions_function_interface_1d EXCLUDE_FROM_ALL function-interface-1d.cc) dune_pybindxi_add_module(_functions_function_interface_2d EXCLUDE_FROM_ALL function-interface-2d.cc) dune_pybindxi_add_module(_functions_function_interface_3d EXCLUDE_FROM_ALL function-interface-3d.cc) +dune_pybindxi_add_module(_functions_gradient EXCLUDE_FROM_ALL gradient.cc) dune_pybindxi_add_module(_functions_gridfunction EXCLUDE_FROM_ALL gridfunction.cc) -dune_pybindxi_add_module(_functions_gridfunction_interface_1d EXCLUDE_FROM_ALL gridfunction-interface-1d.cc) -dune_pybindxi_add_module(_functions_gridfunction_interface_2d EXCLUDE_FROM_ALL gridfunction-interface-2d.cc) -dune_pybindxi_add_module(_functions_gridfunction_interface_3d EXCLUDE_FROM_ALL gridfunction-interface-3d.cc) dune_pybindxi_add_module(_functions_indicator EXCLUDE_FROM_ALL indicator.cc) +dune_pybindxi_add_module(_functions_interfaces_grid_function_1d EXCLUDE_FROM_ALL interfaces/grid-function_1d.cc) +dune_pybindxi_add_module(_functions_interfaces_grid_function_2d EXCLUDE_FROM_ALL interfaces/grid-function_2d.cc) +dune_pybindxi_add_module(_functions_interfaces_grid_function_3d EXCLUDE_FROM_ALL interfaces/grid-function_3d.cc) +dune_pybindxi_add_module(_functions_inverse EXCLUDE_FROM_ALL inverse.cc) +dune_pybindxi_add_module(_functions_parametric_expression EXCLUDE_FROM_ALL parametric-expression.cc) dune_pybindxi_add_module(_functions_spe10 EXCLUDE_FROM_ALL spe10.cc) diff --git a/python/dune/xt/functions/ESV2007.bindings.hh b/python/dune/xt/functions/ESV2007.bindings.hh index 5ef91a172deb79a512ebe0b6bb1a794dd51bc8a3..faafd44ea0c60f929f621d580ad03acb7543603f 100644 --- a/python/dune/xt/functions/ESV2007.bindings.hh +++ b/python/dune/xt/functions/ESV2007.bindings.hh @@ -98,7 +98,7 @@ class CutoffFunction const ScalarFunction& diffusion_factor, const TensorFunction& diffusion_tensor, const R& poincare_constant, - const std::string& name) { return type(diffusion_factor, diffusion_tensor, poincare_constant, name); }, + const std::string& name) { return new type(diffusion_factor, diffusion_tensor, poincare_constant, name); }, "grid_provider"_a, "diffusion_factor"_a, "diffusion_tesor"_a, diff --git a/python/dune/xt/functions/__init__.py b/python/dune/xt/functions/__init__.py index 5b57f7ab3c1472521f776aaa00791b1cdc4bb475..2a9d186cd883395dd02b7c96f05b04abc02e5d27 100644 --- a/python/dune/xt/functions/__init__.py +++ b/python/dune/xt/functions/__init__.py @@ -12,21 +12,43 @@ # Tobias Leibner (2019 - 2020) # ~~~ +from tempfile import NamedTemporaryFile + from dune.xt import guarded_import +from dune.xt.common.vtk.plot import plot for mod_name in ( '_functions_function_interface_1d', '_functions_function_interface_2d', '_functions_checkerboard', '_functions_constant', + '_functions_elementwise_diameter', + '_functions_elementwise_minimum', '_functions_expression', + '_functions_divergence', '_functions_function_as_grid_function', '_functions_function_interface_3d', + '_functions_gradient', '_functions_gridfunction', - '_functions_gridfunction_interface_1d', - '_functions_gridfunction_interface_2d', - '_functions_gridfunction_interface_3d', '_functions_indicator', + '_functions_interfaces_grid_function_1d', + '_functions_interfaces_grid_function_2d', + '_functions_interfaces_grid_function_3d', + '_functions_inverse', + '_functions_parametric_expression', '_functions_spe10', ): guarded_import(globals(), 'dune.xt.functions', mod_name) + +from dune.xt.functions._functions_gridfunction import GridFunction + + +def visualize_function(function, grid, subsampling=False): + assert function.dim_domain == 2, f'Not implemented yet for {function.dim_domain}-dimensional grids!' + assert function.dim_range == 1, f'Not implemented yet for {function.dim_domain}-dimensional functions!' + tmpfile = NamedTemporaryFile(mode='wb', delete=False, suffix='.vtu').name + try: + function.visualize(grid, filename=tmpfile[:-4], subsampling=subsampling) + except AttributeError: + GridFunction(grid, function).visualize(grid, filename=tmpfile[:-4], subsampling=subsampling) + return plot(tmpfile, color_attribute_name=function.name) diff --git a/python/dune/xt/functions/base/combined-grid-function.hh b/python/dune/xt/functions/base/combined-grid-function.hh new file mode 100644 index 0000000000000000000000000000000000000000..2dc2b80e0421fc73493ea90501b352158c74dda7 --- /dev/null +++ b/python/dune/xt/functions/base/combined-grid-function.hh @@ -0,0 +1,161 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License +// (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#ifndef PYTHON_DUNE_XT_FUNCTIONS_BASE_COMBINED_GRID_FUNCTION_HH +#define PYTHON_DUNE_XT_FUNCTIONS_BASE_COMBINED_GRID_FUNCTION_HH + +#include <python/dune/xt/functions/interfaces/grid-function.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace bindings { + + +template <class G, class E, size_t r = 1, size_t rC = 1, class R = double> +class DifferenceGridFunction : public GridFunctionInterface<G, E, r, rC, R> +{ + using BaseType = GridFunctionInterface<G, E, r, rC, R>; + +public: + using base_type = typename BaseType::type; + using type = Functions::DifferenceGridFunction<base_type, base_type>; + using bound_type = pybind11::class_<type, base_type>; + + static bound_type bind(pybind11::module& m, + const std::string& grid_id, + const std::string& layer_id = "", + const std::string& class_id = "difference_grid_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + const auto ClassName = Common::to_camel_case(BaseType::class_name(grid_id, layer_id, class_id)); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + + c.def(py::init<const base_type&, const base_type&>()); + + BaseType::addbind_methods(c); + + return c; + } +}; // class DifferenceGridFunction + + +template <class G, class E, size_t r = 1, size_t rC = 1, class R = double> +class SumGridFunction : public GridFunctionInterface<G, E, r, rC, R> +{ + using BaseType = GridFunctionInterface<G, E, r, rC, R>; + +public: + using base_type = typename BaseType::type; + using type = Functions::SumGridFunction<base_type, base_type>; + using bound_type = pybind11::class_<type, base_type>; + + static bound_type bind(pybind11::module& m, + const std::string& grid_id, + const std::string& layer_id = "", + const std::string& class_id = "sum_grid_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + const auto ClassName = Common::to_camel_case(BaseType::class_name(grid_id, layer_id, class_id)); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + + c.def(py::init<const base_type&, const base_type&>()); + + BaseType::addbind_methods(c); + + return c; + } +}; // class SumGridFunction + + +template <class G, class E, class R = double> +class FractionGridFunction : public GridFunctionInterface<G, E, 1, 1, R> +{ + using BaseType = GridFunctionInterface<G, E, 1, 1, R>; + +public: + using base_type = typename BaseType::type; + using type = Functions::FractionGridFunction<base_type, base_type>; + using bound_type = pybind11::class_<type, base_type>; + + static bound_type bind(pybind11::module& m, + const std::string& grid_id, + const std::string& layer_id = "", + const std::string& class_id = "fraction_grid_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + const auto ClassName = Common::to_camel_case(BaseType::class_name(grid_id, layer_id, class_id)); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + + c.def(py::init<const base_type&, const base_type&>()); + + BaseType::addbind_methods(c); + + return c; + } +}; // class FractionGridFunction + + +template <class G, class E, size_t Lr = 1, size_t LrC = 1, size_t Rr = 1, size_t RrC = 1, class R = double> +class ProductGridFunction + : public GridFunctionInterface<G, + E, + internal::CombinedDim<CombinationType::product, Lr, LrC, Rr, RrC>::r(), + internal::CombinedDim<CombinationType::product, Lr, LrC, Rr, RrC>::rC(), + R> +{ + using BaseType = GridFunctionInterface<G, + E, + internal::CombinedDim<CombinationType::product, Lr, LrC, Rr, RrC>::r(), + internal::CombinedDim<CombinationType::product, Lr, LrC, Rr, RrC>::rC(), + R>; + + using Left = Functions::GridFunctionInterface<E, Lr, LrC, R>; + using Right = Functions::GridFunctionInterface<E, Rr, RrC, R>; + +public: + using base_type = typename BaseType::type; + using type = Functions::ProductGridFunction<Left, Right>; + using bound_type = pybind11::class_<type, base_type>; + + static bound_type bind(pybind11::module& m, + const std::string& grid_id, + const std::string& layer_id = "", + const std::string& class_id = "product_grid_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + const auto ClassName = + Common::to_camel_case(BaseType::class_name(grid_id, layer_id, class_id) + "_from_" + Common::to_string(Lr) + "x" + + Common::to_string(LrC) + "X" + Common::to_string(Rr) + "x" + Common::to_string(RrC)); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + + c.def(py::init<const Left&, const Right&>()); + + BaseType::addbind_methods(c); + + return c; + } +}; // class ProductGridFunction + + +} // namespace bindings +} // namespace Functions +} // namespace XT +} // namespace Dune + +#endif // PYTHON_DUNE_XT_FUNCTIONS_BASE_COMBINED_GRID_FUNCTION_HH diff --git a/python/dune/xt/functions/checkerboard.cc b/python/dune/xt/functions/checkerboard.cc index 43ec993401c1c0c245e8b3792088035dd52e227a..8ae33249bc6e77ca3030e4800f4741c661136718 100644 --- a/python/dune/xt/functions/checkerboard.cc +++ b/python/dune/xt/functions/checkerboard.cc @@ -146,9 +146,9 @@ PYBIND11_MODULE(_functions_checkerboard, m) py::module::import("dune.xt.common"); py::module::import("dune.xt.grid"); py::module::import("dune.xt.la"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_1d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_2d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_3d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); CheckerboardFunction_for_all_grids<>::bind(m); } // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/divergence.cc b/python/dune/xt/functions/divergence.cc new file mode 100644 index 0000000000000000000000000000000000000000..962b1100f6d1d63f1e827cd73a33c044f0dd9c21 --- /dev/null +++ b/python/dune/xt/functions/divergence.cc @@ -0,0 +1,131 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2019) + +#include "config.h" + +#include <string> +#include <vector> + +#include <dune/common/parallel/mpihelper.hh> + +#include <dune/pybindxi/pybind11.h> +#include <dune/pybindxi/functional.h> +#include <dune/pybindxi/stl.h> + +#include <dune/xt/common/string.hh> +#include <dune/xt/grid/gridprovider/provider.hh> +#include <dune/xt/grid/type_traits.hh> +#include <dune/xt/functions/base/derivatives-of-grid-functions.hh> + +#include <python/dune/xt/common/parameter.hh> +#include <python/dune/xt/common/fvector.hh> +#include <python/dune/xt/common/fmatrix.hh> +#include <python/dune/xt/common/bindings.hh> +#include <python/dune/xt/grid/traits.hh> +#include <python/dune/xt/common/exceptions.bindings.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace bindings { + + +template <class G, class E> +class DivergenceGridFunction +{ + using GP = XT::Grid::GridProvider<G>; + static const size_t d = G::dimension; + using GF = Functions::GridFunction<E, d>; + +public: + using type = Functions::DivergenceGridFunction<GF>; + using base_type = Functions::GridFunctionInterface<E>; + using bound_type = pybind11::class_<type, base_type>; + +public: + static bound_type bind(pybind11::module& m, + const std::string& grid_id = Grid::bindings::grid_name<G>::value(), + const std::string& layer_id = "", + const std::string& class_id = "divergence_grid_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + std::string class_name = class_id; + class_name += "_" + grid_id; + if (!layer_id.empty()) + class_name += "_" + layer_id; + class_name += "_to_1d"; + const auto ClassName = Common::to_camel_case(class_name); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + c.def(py::init<GF, const std::string&>(), "grid_function"_a, "name"_a = "DivergenceGridFunction"); + + m.def( + "divergence", + [](const GridFunctionInterface<E, d>& grid_function, const std::string& name) { + return new type(grid_function, name); + }, + "grid_function"_a, + "name"_a = "DivergenceGridFunction"); + m.def( + "divergence", + [](GF grid_function, const std::string& name) { return new type(grid_function, name); }, + "grid_function"_a, + "name"_a = "DivergenceGridFunction"); + + return c; + } +}; // class GridFunction + + +} // namespace bindings +} // namespace Functions +} // namespace XT +} // namespace Dune + + +template <class GridTypes = Dune::XT::Grid::AvailableGridTypes> +struct DivergenceGridFunction_for_all_grids +{ + using G = typename GridTypes::head_type; + using GV = typename G::LeafGridView; + using E = Dune::XT::Grid::extract_entity_t<GV>; + + static void bind(pybind11::module& m) + { + using Dune::XT::Functions::bindings::DivergenceGridFunction; + using Dune::XT::Grid::bindings::grid_name; + + DivergenceGridFunction<G, E>::bind(m, grid_name<G>::value()); + + DivergenceGridFunction_for_all_grids<typename GridTypes::tail_type>::bind(m); + } +}; + +template <> +struct DivergenceGridFunction_for_all_grids<boost::tuples::null_type> +{ + static void bind(pybind11::module& /*m*/) {} +}; + + +PYBIND11_MODULE(_functions_divergence, m) +{ + namespace py = pybind11; + + py::module::import("dune.xt.common"); + py::module::import("dune.xt.grid"); + py::module::import("dune.xt.la"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); + py::module::import("dune.xt.functions._functions_gridfunction"); + + DivergenceGridFunction_for_all_grids<>::bind(m); +} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/elementwise-diameter.cc b/python/dune/xt/functions/elementwise-diameter.cc new file mode 100644 index 0000000000000000000000000000000000000000..2b1c90fdf2c91343660bdaed27d4696e1a5f5051 --- /dev/null +++ b/python/dune/xt/functions/elementwise-diameter.cc @@ -0,0 +1,123 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2019) + +#include "config.h" + +#include <string> +#include <vector> + +#include <dune/common/parallel/mpihelper.hh> + +#include <dune/pybindxi/pybind11.h> +#include <dune/pybindxi/functional.h> +#include <dune/pybindxi/stl.h> + +#include <dune/xt/common/string.hh> +#include <dune/xt/grid/gridprovider/provider.hh> +#include <dune/xt/grid/type_traits.hh> +#include <dune/xt/functions/elementwise-diameter.hh> + +#include <python/dune/xt/common/parameter.hh> +#include <python/dune/xt/common/fvector.hh> +#include <python/dune/xt/common/fmatrix.hh> +#include <python/dune/xt/common/bindings.hh> +#include <python/dune/xt/grid/traits.hh> +#include <python/dune/xt/common/exceptions.bindings.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace bindings { + + +template <class G, class E> +class ElementwiseDiameterFunction +{ + using GP = XT::Grid::GridProvider<G>; + static const size_t d = G::dimension; + +public: + using type = Functions::ElementwiseDiameterFunction<E>; + using base_type = Functions::GridFunctionInterface<E>; + using bound_type = pybind11::class_<type, base_type>; + +public: + static bound_type bind(pybind11::module& m, + const std::string& grid_id = Grid::bindings::grid_name<G>::value(), + const std::string& layer_id = "", + const std::string& class_id = "elementwise_diameter_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + std::string class_name = class_id; + class_name += "_" + grid_id; + if (!layer_id.empty()) + class_name += "_" + layer_id; + class_name += "_to_1d"; + const auto ClassName = Common::to_camel_case(class_name); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + c.def(py::init<const std::string&>(), "name"_a = "ElementwiseDiameterFunction"); + + const auto FactoryName = Common::to_camel_case(class_id); + m.def( + FactoryName.c_str(), + [](const GP&, const std::string& name) { return new type(name); }, + "grid"_a, + "name"_a = "ElementwiseDiameterFunction"); + + return c; + } +}; // class GridFunction + + +} // namespace bindings +} // namespace Functions +} // namespace XT +} // namespace Dune + + +template <class GridTypes = Dune::XT::Grid::AvailableGridTypes> +struct ElementwiseDiameterFunction_for_all_grids +{ + using G = typename GridTypes::head_type; + using GV = typename G::LeafGridView; + using E = Dune::XT::Grid::extract_entity_t<GV>; + + static void bind(pybind11::module& m) + { + using Dune::XT::Functions::bindings::ElementwiseDiameterFunction; + using Dune::XT::Grid::bindings::grid_name; + + ElementwiseDiameterFunction<G, E>::bind(m, grid_name<G>::value()); + + ElementwiseDiameterFunction_for_all_grids<typename GridTypes::tail_type>::bind(m); + } +}; + +template <> +struct ElementwiseDiameterFunction_for_all_grids<boost::tuples::null_type> +{ + static void bind(pybind11::module& /*m*/) {} +}; + + +PYBIND11_MODULE(_functions_elementwise_diameter, m) +{ + namespace py = pybind11; + + py::module::import("dune.xt.common"); + py::module::import("dune.xt.grid"); + py::module::import("dune.xt.la"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); + + ElementwiseDiameterFunction_for_all_grids<>::bind(m); +} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/elementwise-minimum.cc b/python/dune/xt/functions/elementwise-minimum.cc new file mode 100644 index 0000000000000000000000000000000000000000..aff47d85866733f4a19437b84b176b870e079acb --- /dev/null +++ b/python/dune/xt/functions/elementwise-minimum.cc @@ -0,0 +1,144 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2019) + +#include "config.h" + +#include <string> +#include <vector> + +#include <dune/common/parallel/mpihelper.hh> + +#include <dune/pybindxi/pybind11.h> +#include <dune/pybindxi/functional.h> +#include <dune/pybindxi/stl.h> + +#include <dune/xt/common/string.hh> +#include <dune/xt/grid/gridprovider/provider.hh> +#include <dune/xt/grid/type_traits.hh> +#include <dune/xt/functions/elementwise-minimum.hh> + +#include <python/dune/xt/common/parameter.hh> +#include <python/dune/xt/common/fvector.hh> +#include <python/dune/xt/common/fmatrix.hh> +#include <python/dune/xt/common/bindings.hh> +#include <python/dune/xt/grid/traits.hh> +#include <python/dune/xt/common/exceptions.bindings.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace bindings { + + +template <class G, class E, size_t r = 1, size_t rC = 1> +class ElementwiseMinimumFunction +{ + using GP = XT::Grid::GridProvider<G>; + using GF = Functions::GridFunction<E, r, rC>; + static const size_t d = G::dimension; + +public: + using type = Functions::ElementwiseMinimumFunction<Functions::GridFunctionInterface<E, r, rC>>; + using base_type = Functions::GridFunctionInterface<E>; + using bound_type = pybind11::class_<type, base_type>; + +public: + static bound_type bind(pybind11::module& m, + const std::string& grid_id = Grid::bindings::grid_name<G>::value(), + const std::string& layer_id = "", + const std::string& class_id = "elementwise_minimum_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + std::string class_name = class_id; + class_name += "_" + grid_id; + if (!layer_id.empty()) + class_name += "_" + layer_id; + class_name += "_to_" + Common::to_string(r); + if (rC > 1) + class_name += "x" + Common::to_string(rC); + class_name += "d"; + const auto ClassName = Common::to_camel_case(class_name); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + c.def(py::init<GF, const int, const std::string&>(), + "grid_function"_a, + "search_quadrature_order"_a, + "name"_a = "ElementwiseMinimumFunction"); + + const auto FactoryName = Common::to_camel_case(class_id); + m.def( + FactoryName.c_str(), + [](GF grid_function, const int search_quadrature_order, const std::string& name) { + return new type(grid_function, search_quadrature_order, name); + }, + "grid_function"_a, + "search_quadrature_order"_a, + "name"_a = "ElementwiseMinimumFunction"); + m.def( + FactoryName.c_str(), + [](const Functions::GridFunction<E, r, rC>& grid_function, + const int search_quadrature_order, + const std::string& name) { return new type(grid_function, search_quadrature_order, name); }, + "grid_function"_a, + "search_quadrature_order"_a, + "name"_a = "ElementwiseMinimumFunction"); + + return c; + } +}; // class GridFunction + + +} // namespace bindings +} // namespace Functions +} // namespace XT +} // namespace Dune + + +template <class GridTypes = Dune::XT::Grid::AvailableGridTypes> +struct ElementwiseMinimumFunction_for_all_grids +{ + using G = typename GridTypes::head_type; + using GV = typename G::LeafGridView; + using E = Dune::XT::Grid::extract_entity_t<GV>; + + static void bind(pybind11::module& m) + { + using Dune::XT::Functions::bindings::ElementwiseMinimumFunction; + using Dune::XT::Grid::bindings::grid_name; + + ElementwiseMinimumFunction<G, E, 1, 1>::bind(m, grid_name<G>::value()); + ElementwiseMinimumFunction<G, E, 2, 2>::bind(m, grid_name<G>::value()); + ElementwiseMinimumFunction<G, E, 3, 3>::bind(m, grid_name<G>::value()); + + ElementwiseMinimumFunction_for_all_grids<typename GridTypes::tail_type>::bind(m); + } +}; + +template <> +struct ElementwiseMinimumFunction_for_all_grids<boost::tuples::null_type> +{ + static void bind(pybind11::module& /*m*/) {} +}; + + +PYBIND11_MODULE(_functions_elementwise_minimum, m) +{ + namespace py = pybind11; + + py::module::import("dune.xt.common"); + py::module::import("dune.xt.grid"); + py::module::import("dune.xt.la"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); + py::module::import("dune.xt.functions._functions_gridfunction"); + + ElementwiseMinimumFunction_for_all_grids<>::bind(m); +} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/function-as-grid-function.cc b/python/dune/xt/functions/function-as-grid-function.cc index 68ee9187284544b9e36fdbcedae5e73dc623132c..3ac206f7602654ca859d4227927fbb0d6df8f31e 100644 --- a/python/dune/xt/functions/function-as-grid-function.cc +++ b/python/dune/xt/functions/function-as-grid-function.cc @@ -66,9 +66,9 @@ PYBIND11_MODULE(_functions_function_as_grid_function, m) py::module::import("dune.xt.functions._functions_function_interface_1d"); py::module::import("dune.xt.functions._functions_function_interface_2d"); py::module::import("dune.xt.functions._functions_function_interface_3d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_1d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_2d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_3d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); all_grids(m); } diff --git a/python/dune/xt/functions/function-as-grid-function.hh b/python/dune/xt/functions/function-as-grid-function.hh index 62c12a304801c203842e8525c4ce6337d9b006cf..24b372762a7ef5ffbba00ea7ee0ce5edc78c5bfb 100644 --- a/python/dune/xt/functions/function-as-grid-function.hh +++ b/python/dune/xt/functions/function-as-grid-function.hh @@ -46,7 +46,6 @@ auto bind_FunctionAsGridFunctionWrapper(pybind11::module& m, const std::string& "function_to_grid_function", [](XT::Functions::FunctionInterface<d, r, rC, R>& func, const XT::Grid::GridProvider<G>& /*only_here_to_select_grid_type*/) { return std::make_unique<C>(func); }, - py::keep_alive<0, 1>(), "function"_a, "grid_provider"_a); diff --git a/python/dune/xt/functions/function-interface-1d.cc b/python/dune/xt/functions/function-interface-1d.cc index 55a48b8fe73da3c9ce9c89f12ba303fda3921ec2..a8fc131a5860b46c8709a15640d4c39cb20b2f37 100644 --- a/python/dune/xt/functions/function-interface-1d.cc +++ b/python/dune/xt/functions/function-interface-1d.cc @@ -35,9 +35,9 @@ PYBIND11_MODULE(_functions_function_interface_1d, m) using namespace Dune::XT::Functions; - const auto diff = CombinationType::difference; - const auto sum = CombinationType::sum; - const auto prod = CombinationType::product; + using diff = CombinationType::difference; + using sum = CombinationType::sum; + using prod = CombinationType::product; auto i_1_1_1 = bind_FunctionInterface<1, 1, 1>(m); auto i_1_2_1 = bind_FunctionInterface<1, 2, 1>(m); diff --git a/python/dune/xt/functions/function-interface-2d.cc b/python/dune/xt/functions/function-interface-2d.cc index 8342ff43d426eb521d086ad58877f36b966a2331..d7caf3c8ce5855ab4da82bcb67d8b230845712bf 100644 --- a/python/dune/xt/functions/function-interface-2d.cc +++ b/python/dune/xt/functions/function-interface-2d.cc @@ -35,9 +35,9 @@ PYBIND11_MODULE(_functions_function_interface_2d, m) using namespace Dune::XT::Functions; - const auto diff = CombinationType::difference; - const auto sum = CombinationType::sum; - const auto prod = CombinationType::product; + using diff = CombinationType::difference; + using sum = CombinationType::sum; + using prod = CombinationType::product; auto i_2_1_1 = bind_FunctionInterface<2, 1, 1>(m); auto i_2_2_1 = bind_FunctionInterface<2, 2, 1>(m); diff --git a/python/dune/xt/functions/function-interface-3d.cc b/python/dune/xt/functions/function-interface-3d.cc index ff1fe0f6581fe9c34aa62b81744f46074fa63370..ee9186738dbda2c671f2ca474fae377ea7c3844e 100644 --- a/python/dune/xt/functions/function-interface-3d.cc +++ b/python/dune/xt/functions/function-interface-3d.cc @@ -35,9 +35,9 @@ PYBIND11_MODULE(_functions_function_interface_3d, m) using namespace Dune::XT::Functions; - const auto diff = CombinationType::difference; - const auto sum = CombinationType::sum; - const auto prod = CombinationType::product; + using diff = CombinationType::difference; + using sum = CombinationType::sum; + using prod = CombinationType::product; auto i_3_1_1 = bind_FunctionInterface<3, 1, 1>(m); auto i_3_2_1 = bind_FunctionInterface<3, 2, 1>(m); diff --git a/python/dune/xt/functions/function-interface.hh b/python/dune/xt/functions/function-interface.hh index 61e2aa9f75b6982f50376427363a89c67057f975..96c3cb2d020e6e84d132ef590f87ce233ef54021 100644 --- a/python/dune/xt/functions/function-interface.hh +++ b/python/dune/xt/functions/function-interface.hh @@ -27,7 +27,7 @@ namespace Functions { namespace internal { -template <class L, class R, CombinationType comb> +template <class L, class R, class comb> struct get_combined {}; // struct get_combined @@ -114,7 +114,7 @@ struct get_combined<L, R, CombinationType::product> template <size_t d, - CombinationType comb, + class comb, size_t lr, size_t lrC, size_t rr, @@ -147,7 +147,7 @@ bind_combined_Function(pybind11::module& m) } // ... bind_combined_Function(...) -template <size_t d, CombinationType comb, size_t r, size_t rC, size_t oR, size_t orC, class C> +template <size_t d, class comb, size_t r, size_t rC, size_t oR, size_t orC, class C> void addbind_FunctionInterface_combined_op(C& c) { namespace py = pybind11; @@ -158,8 +158,7 @@ void addbind_FunctionInterface_combined_op(C& c) c.def( internal::get_combined<S, O, comb>::op().c_str(), [](const S& self, const O& other) { return internal::get_combined<S, O, comb>::call(self, other); }, - py::keep_alive<0, 1>(), - py::keep_alive<0, 2>()); + py::is_operator()); } // ... addbind_FunctionInterface_combined_op(...) @@ -179,6 +178,11 @@ pybind11::class_<FunctionInterface<d, r, rC, double>> bind_FunctionInterface(pyb + Common::to_string(rC)) .c_str()); + c.def_property_readonly("dim_domain", [](const C& /*self*/) { return size_t(d); }); + if (rC == 1) + c.def_property_readonly("dim_range", [](const C& /*self*/) { return size_t(r); }); + else + c.def_property_readonly("dim_range", [](const C& /*self*/) { return std::make_pair(size_t(r), size_t(rC)); }); c.def_property_readonly("static_id", [](const C& /*self*/) { return C::static_id(); }); c.def_property_readonly("name", [](const C& self) { return self.name(); }); diff --git a/python/dune/xt/functions/gradient.cc b/python/dune/xt/functions/gradient.cc new file mode 100644 index 0000000000000000000000000000000000000000..34413212c35a4111dac4e1cf5f1676b650397d99 --- /dev/null +++ b/python/dune/xt/functions/gradient.cc @@ -0,0 +1,129 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2019) + +#include "config.h" + +#include <string> +#include <vector> + +#include <dune/common/parallel/mpihelper.hh> + +#include <dune/pybindxi/pybind11.h> +#include <dune/pybindxi/functional.h> +#include <dune/pybindxi/stl.h> + +#include <dune/xt/common/string.hh> +#include <dune/xt/grid/gridprovider/provider.hh> +#include <dune/xt/grid/type_traits.hh> +#include <dune/xt/functions/base/derivatives-of-grid-functions.hh> + +#include <python/dune/xt/common/parameter.hh> +#include <python/dune/xt/common/fvector.hh> +#include <python/dune/xt/common/fmatrix.hh> +#include <python/dune/xt/common/bindings.hh> +#include <python/dune/xt/grid/traits.hh> +#include <python/dune/xt/common/exceptions.bindings.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace bindings { + + +template <class G, class E> +class GradientGridFunction +{ + using GP = XT::Grid::GridProvider<G>; + static const size_t d = G::dimension; + +public: + using type = Functions::GradientGridFunction<GridFunctionInterface<E>>; + using base_type = Functions::GridFunctionInterface<E, d>; + using bound_type = pybind11::class_<type, base_type>; + +public: + static bound_type bind(pybind11::module& m, + const std::string& grid_id = Grid::bindings::grid_name<G>::value(), + const std::string& layer_id = "", + const std::string& class_id = "gradient_grid_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + std::string class_name = class_id; + class_name += "_" + grid_id; + if (!layer_id.empty()) + class_name += "_" + layer_id; + class_name += "_to_" + Common::to_string(size_t(d)) + "d"; + const auto ClassName = Common::to_camel_case(class_name); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + c.def(py::init([](const Functions::GridFunctionInterface<E>& grid_function, const std::string& logging_prefix) { + return new type(grid_function, logging_prefix); + }), + "grid_function"_a, + "name"_a = "GradientGridFunction"); + + m.def( + "gradient", + [](const GridFunctionInterface<E>& grid_function, const std::string& name) { + return new type(grid_function, name); + }, + "grid_function"_a, + "name"_a = "GradientGridFunction"); + + return c; + } +}; // class GridFunction + + +} // namespace bindings +} // namespace Functions +} // namespace XT +} // namespace Dune + + +template <class GridTypes = Dune::XT::Grid::AvailableGridTypes> +struct GradientGridFunction_for_all_grids +{ + using G = typename GridTypes::head_type; + using GV = typename G::LeafGridView; + using E = Dune::XT::Grid::extract_entity_t<GV>; + + static void bind(pybind11::module& m) + { + using Dune::XT::Functions::bindings::GradientGridFunction; + using Dune::XT::Grid::bindings::grid_name; + + GradientGridFunction<G, E>::bind(m, grid_name<G>::value()); + + GradientGridFunction_for_all_grids<typename GridTypes::tail_type>::bind(m); + } +}; + +template <> +struct GradientGridFunction_for_all_grids<boost::tuples::null_type> +{ + static void bind(pybind11::module& /*m*/) {} +}; + + +PYBIND11_MODULE(_functions_gradient, m) +{ + namespace py = pybind11; + + py::module::import("dune.xt.common"); + py::module::import("dune.xt.grid"); + py::module::import("dune.xt.la"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); + py::module::import("dune.xt.functions._functions_gridfunction"); + + GradientGridFunction_for_all_grids<>::bind(m); +} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/gridfunction-interface-1d.cc b/python/dune/xt/functions/gridfunction-interface-1d.cc deleted file mode 100644 index 342ccc44169647247b9adf9f8d0e72a4f53876ec..0000000000000000000000000000000000000000 --- a/python/dune/xt/functions/gridfunction-interface-1d.cc +++ /dev/null @@ -1,53 +0,0 @@ -// This file is part of the dune-xt project: -// https://github.com/dune-community/dune-xt -// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. -// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) -// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) -// with "runtime exception" (http://www.dune-project.org/license.html) -// Authors: -// Felix Schindler (2019) -// René Fritze (2019) -// Tobias Leibner (2019 - 2020) - -#include "config.h" - -#include <string> -#include <vector> - -#include <dune/common/parallel/mpihelper.hh> - -#include <dune/pybindxi/pybind11.h> -#include <dune/pybindxi/stl.h> - -#include <python/dune/xt/common/bindings.hh> -#include <python/dune/xt/common/exceptions.bindings.hh> -#include <python/dune/xt/grid/grids.bindings.hh> - -#include "gridfunction-interface.hh" - - -template <class Tuple = Dune::XT::Grid::Available1dGridTypes> -void bind_all_1d_grids(pybind11::module& m) -{ - Dune::XT::Common::bindings::guarded_bind([&]() { // different grids but same entity - Dune::XT::Functions::bindings::addbind_GridFunctionInterface_all_dims<typename Tuple::head_type>(m); - }); - bind_all_1d_grids<typename Tuple::tail_type>(m); -} - -template <> -void bind_all_1d_grids<boost::tuples::null_type>(pybind11::module&) -{} - - -PYBIND11_MODULE(_functions_gridfunction_interface_1d, m) -{ - namespace py = pybind11; - - py::module::import("dune.xt.common"); - py::module::import("dune.xt.la"); - py::module::import("dune.xt.grid"); - py::module::import("dune.xt.functions._functions_function_interface_1d"); - - bind_all_1d_grids(m); -} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/gridfunction-interface-2d.cc b/python/dune/xt/functions/gridfunction-interface-2d.cc deleted file mode 100644 index 0d003986e08d1d1ace735b8a62d49e187bd61b82..0000000000000000000000000000000000000000 --- a/python/dune/xt/functions/gridfunction-interface-2d.cc +++ /dev/null @@ -1,53 +0,0 @@ -// This file is part of the dune-xt project: -// https://github.com/dune-community/dune-xt -// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. -// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) -// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) -// with "runtime exception" (http://www.dune-project.org/license.html) -// Authors: -// Felix Schindler (2019) -// René Fritze (2019) -// Tobias Leibner (2019 - 2020) - -#include "config.h" - -#include <string> -#include <vector> - -#include <dune/common/parallel/mpihelper.hh> - -#include <dune/pybindxi/pybind11.h> -#include <dune/pybindxi/stl.h> - -#include <python/dune/xt/common/bindings.hh> -#include <python/dune/xt/common/exceptions.bindings.hh> -#include <python/dune/xt/grid/grids.bindings.hh> - -#include "gridfunction-interface.hh" - - -template <class Tuple = Dune::XT::Grid::Available2dGridTypes> -void bind_all_2d_grids(pybind11::module& m) -{ - Dune::XT::Common::bindings::guarded_bind([&]() { // different grids but same entity - Dune::XT::Functions::bindings::addbind_GridFunctionInterface_all_dims<typename Tuple::head_type>(m); - }); - bind_all_2d_grids<typename Tuple::tail_type>(m); -} - -template <> -void bind_all_2d_grids<boost::tuples::null_type>(pybind11::module&) -{} - - -PYBIND11_MODULE(_functions_gridfunction_interface_2d, m) -{ - namespace py = pybind11; - - py::module::import("dune.xt.common"); - py::module::import("dune.xt.la"); - py::module::import("dune.xt.grid"); - py::module::import("dune.xt.functions._functions_function_interface_2d"); - - bind_all_2d_grids(m); -} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/gridfunction-interface-3d.cc b/python/dune/xt/functions/gridfunction-interface-3d.cc deleted file mode 100644 index db8793bba427a1606733ade8a007b8466eefde55..0000000000000000000000000000000000000000 --- a/python/dune/xt/functions/gridfunction-interface-3d.cc +++ /dev/null @@ -1,53 +0,0 @@ -// This file is part of the dune-xt project: -// https://github.com/dune-community/dune-xt -// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. -// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) -// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) -// with "runtime exception" (http://www.dune-project.org/license.html) -// Authors: -// Felix Schindler (2019) -// René Fritze (2019) -// Tobias Leibner (2019 - 2020) - -#include "config.h" - -#include <string> -#include <vector> - -#include <dune/common/parallel/mpihelper.hh> - -#include <dune/pybindxi/pybind11.h> -#include <dune/pybindxi/stl.h> - -#include <python/dune/xt/common/bindings.hh> -#include <python/dune/xt/common/exceptions.bindings.hh> -#include <python/dune/xt/grid/grids.bindings.hh> - -#include "gridfunction-interface.hh" - - -template <class Tuple = Dune::XT::Grid::Available3dGridTypes> -void bind_all_3d_grids(pybind11::module& m) -{ - Dune::XT::Common::bindings::guarded_bind([&]() { // different grids but same entity - Dune::XT::Functions::bindings::addbind_GridFunctionInterface_all_dims<typename Tuple::head_type>(m); - }); - bind_all_3d_grids<typename Tuple::tail_type>(m); -} - -template <> -void bind_all_3d_grids<boost::tuples::null_type>(pybind11::module&) -{} - - -PYBIND11_MODULE(_functions_gridfunction_interface_3d, m) -{ - namespace py = pybind11; - - py::module::import("dune.xt.common"); - py::module::import("dune.xt.la"); - py::module::import("dune.xt.grid"); - py::module::import("dune.xt.functions._functions_function_interface_3d"); - - bind_all_3d_grids(m); -} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/gridfunction-interface.hh b/python/dune/xt/functions/gridfunction-interface.hh deleted file mode 100644 index 88797b70b51618de172f9a06783860898d68e340..0000000000000000000000000000000000000000 --- a/python/dune/xt/functions/gridfunction-interface.hh +++ /dev/null @@ -1,461 +0,0 @@ -// This file is part of the dune-xt project: -// https://github.com/dune-community/dune-xt -// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. -// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) -// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) -// with "runtime exception" (http://www.dune-project.org/license.html) -// Authors: -// Felix Schindler (2016 - 2019) -// René Fritze (2018 - 2019) -// Tim Keil (2018) -// Tobias Leibner (2018, 2020) - -#ifndef DUNE_XT_FUNCTIONS_INTERFACE_PBH -#define DUNE_XT_FUNCTIONS_INTERFACE_PBH - -#include <dune/pybindxi/pybind11.h> -#include <dune/pybindxi/operators.h> - -#include <python/dune/xt/common/bindings.hh> -#include <python/dune/xt/grid/grids.bindings.hh> -#include <dune/xt/grid/gridprovider/provider.hh> - -#include <dune/xt/functions/interfaces/grid-function.hh> -#include <dune/xt/functions/interfaces/function.hh> - -namespace Dune { -namespace XT { -namespace Functions { -namespace bindings { -namespace internal { - - -template <class L, class R, CombinationType comb> -struct get_combined -{}; // struct get_combined - -template <class L, class R> -struct get_combined<L, R, CombinationType::difference> -{ - typedef DifferenceFunction<L, R> type; - - static std::string id() - { - return "DifferenceFunction"; - } - - static std::string doc() - { - return "difference"; - } - - static std::string op() - { - return "__sub__"; - } - - static auto call(const L& l, const R& r) -> decltype(l - r) - { - return l - r; - } -}; // struct get_combined - -template <class L, class R> -struct get_combined<L, R, CombinationType::sum> -{ - typedef SumFunction<L, R> type; - - static std::string id() - { - return "SumFunction"; - } - - static std::string doc() - { - return "sum"; - } - - static std::string op() - { - return "__add__"; - } - - static auto call(const L& l, const R& r) -> decltype(l + r) - { - return l + r; - } -}; // struct get_combined - -template <class L, class R> -struct get_combined<L, R, CombinationType::product> -{ - typedef ProductFunction<L, R> type; - - static std::string id() - { - return "ProductFunction"; - } - - static std::string doc() - { - return "product"; - } - - static std::string op() - { - return "__mul__"; - } - - static auto call(const L& l, const R& r) -> decltype(l * r) - { - return l * r; - } -}; // struct get_combined - - -/** - * grid_combined - */ - -template <class L, class R, CombinationType comb> -struct get_grid_combined -{}; // struct get_grid_combined - -template <class L, class R> -struct get_grid_combined<L, R, CombinationType::difference> -{ - typedef DifferenceGridFunction<L, R> type; - - static std::string id() - { - return "DifferenceGridFunction"; - } - - static std::string doc() - { - return "difference"; - } - - static std::string op() - { - return "__sub__"; - } - - static auto call(const L& l, const R& r) -> decltype(l - r) - { - return l - r; - } -}; // struct get_grid_combined - -template <class L, class R> -struct get_grid_combined<L, R, CombinationType::sum> -{ - typedef SumGridFunction<L, R> type; - - static std::string id() - { - return "SumGridFunction"; - } - - static std::string doc() - { - return "sum"; - } - - static std::string op() - { - return "__add__"; - } - - static auto call(const L& l, const R& r) -> decltype(l + r) - { - return l + r; - } -}; // struct get_grid_combined - -template <class L, class R> -struct get_grid_combined<L, R, CombinationType::product> -{ - typedef ProductGridFunction<L, R> type; - - static std::string id() - { - return "ProductGridFunction"; - } - - static std::string doc() - { - return "product"; - } - - static std::string op() - { - return "__mul__"; - } - - static auto call(const L& l, const R& r) -> decltype(l * r) - { - return l * r; - } -}; // struct get_grid_combined - -// template <class G> -// struct Divergence -//{ -// template <size_t d, size_t r, size_t rC, bool dims_match = (d == r) && (rC == 1)> -// struct helper -// { -// template <class E, class R> -// static void addbind(pybind11::module& m, pybind11::class_<GridFunctionInterface<E, d, 1, R>>& c) -// { -// namespace py = pybind11; -// using namespace pybind11::literals; -// using Common::to_string; - -// try { // guard since we might not be the first to do bind this combination -// py::class_<DivergenceFunction<GridFunctionInterface<E, d, 1, R>>, -// GridFunctionInterface<E, d, 1, R>>( -// m, -// Common::to_camel_case( -// "divergence_of_function_from_" + Grid::bindings::grid_name<G>::value() + "_to_" + to_string(r) + "x" -// + to_string(rC)) -// .c_str(), -// "DivergenceFunction"); -// } catch (std::runtime_error&) { -// } - -// c.def("divergence", -// [](const GridFunctionInterface<E, d, 1, R>& self, const std::string& name) { -// return new DivergenceFunction<GridFunctionInterface<E, d, 1, R>>(self, name); -// }, -// "name"_a = "", -// py::keep_alive<0, 1>()); -// } // ... addbind(...) -// }; // struct helper<..., true> - -// template <size_t d, size_t r, size_t rC> -// struct helper<d, r, rC, false> -// { -// template <class E, class R> -// static void addbind(pybind11::module& /*m*/, pybind11::class_<GridFunctionInterface<E, r, rC, R>>& /*c*/) -// { -// } -// }; // struct helper<..., false> - -// template <class E, size_t d, class R, size_t r, size_t rC> -// static void addbind(pybind11::module& m, pybind11::class_<GridFunctionInterface<E, r, rC, R>>& c) -// { -// helper<d, r, rC>::addbind(m, c); -// } // ... addbind(...) -//}; // struct Divergence - - -} // namespace internal - - -/** - * \note We would like to drop the d template paremter and use either of -\code -static constexpr size_t d = G::dimension; -static constexpr size_t d = G::dimension; -\endcode - * but this triggers a bug in gcc-4.9, see e.g.: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59937 - */ -template <class G, - size_t d, - CombinationType comb, - size_t lr, - size_t lrC, - size_t rr, - size_t rrC, - class C = typename internal::get_grid_combined< - GridFunctionInterface<typename G::template Codim<0>::Entity, lr, lrC, double>, - GridFunctionInterface<typename G::template Codim<0>::Entity, rr, rrC, double>, - comb>::type> -pybind11::class_<C, - GridFunctionInterface<typename G::template Codim<0>::Entity, C::range_dim, C::range_dim_cols, double>> -bind_combined_GridFunction(pybind11::module& m, const std::string& grid_id) -{ - namespace py = pybind11; - - typedef typename G::template Codim<0>::Entity E; - typedef double R; - typedef GridFunctionInterface<E, lr, lrC, R> Left; - typedef GridFunctionInterface<E, rr, rrC, R> Right; - static constexpr size_t r = C::range_dim; - static constexpr size_t rC = C::range_dim_cols; - const std::string id = internal::get_grid_combined<Left, Right, comb>::id(); - const std::string op = internal::get_grid_combined<Left, Right, comb>::doc(); - const std::string class_name = id + "__" + grid_id + "_to_" + Common::to_string(r) + "x" + Common::to_string(rC); - const std::string doc = class_name + " (as a " + op + " of functions of dimensions " + Common::to_string(lr) + "x" - + Common::to_string(lrC) + " and " + Common::to_string(rr) + "x" + Common::to_string(rrC) - + ")"; - - py::class_<C, GridFunctionInterface<E, r, rC, R>> c(m, std::string(class_name).c_str(), doc.c_str()); - - c.def_property_readonly("static_id", [](const C& /*self*/) { return C::static_id(); }); - - return c; -} // ... bind_combined_GridFunction(...) - - -/** - * \note We would like to drop the d template paremter and use either of -\code -static constexpr size_t d = G::dimension; -static constexpr size_t d = G::dimension; -\endcode - * but this triggers a bug in gcc-4.9, see e.g.: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59937 - */ -template <class G, size_t d, CombinationType comb, size_t r, size_t rC, size_t oR, size_t orC, class C> -void addbind_GridFunctionInterface_combined_op(C& c) -{ - namespace py = pybind11; - - typedef typename G::template Codim<0>::Entity E; - typedef GridFunctionInterface<E, r, rC, double> S; - typedef GridFunctionInterface<E, oR, orC, double> O; - - c.def( - internal::get_grid_combined<S, O, comb>::op().c_str(), - [](const S& self, const O& other) { return internal::get_grid_combined<S, O, comb>::call(self, other); }, - py::keep_alive<0, 1>(), - py::keep_alive<0, 2>()); -} // ... addbind_GridFunctionInterface_combined_op(...) - - -template <class G, size_t r, size_t rC> -pybind11::class_<GridFunctionInterface<typename G::template Codim<0>::Entity, r, rC, double>> -bind_GridFunctionInterface(pybind11::module& m, const std::string& grid_id) -{ - namespace py = pybind11; - using namespace pybind11::literals; - - typedef GridFunctionInterface<typename G::template Codim<0>::Entity, r, rC, double> C; - - py::class_<C> c( - m, - std::string("GridFunctionInterface__" + grid_id + "_to_" + Common::to_string(r) + "x" + Common::to_string(rC)) - .c_str(), - std::string("GridFunctionInterface__" + grid_id + "_to_" + Common::to_string(r) + "x" + Common::to_string(rC)) - .c_str()); - - c.def_property_readonly("static_id", [](const C& /*self*/) { return C::static_id(); }); - c.def_property_readonly("name", [](const C& self) { return self.name(); }); - - c.def( - "visualize", - [](const C& self, - const Grid::GridProvider<G>& grid_provider, - const std::string& layer, - const ssize_t lvl, - const std::string& path, - const bool subsampling) { - const auto level = XT::Common::numeric_cast<int>(lvl); - if (layer == "leaf") - self.visualize(grid_provider.leaf_view(), path, subsampling); - else if (layer == "level") - self.visualize(grid_provider.template layer<XT::Grid::Layers::level, XT::Grid::Backends::view>(level), - path, - subsampling); - else - DUNE_THROW(XT::Common::Exceptions::wrong_input_given, - "Given layer has to be one of ('leaf', 'level'), is '" << layer << "'!"); - }, - "grid_provider"_a, - "layer"_a = "leaf", - "level"_a = -1, - "path"_a, - "subsampling"_a = true); - - // internal::Divergence<G>::addbind(m, c); - - return c; -} // ... bind_GridFunctionInterface(...) - - -template <class G> -void addbind_GridFunctionInterface_all_dims(pybind11::module& m) -{ - using namespace Dune::XT::Functions; - const auto grid_id = Dune::XT::Grid::bindings::grid_name<G>::value(); - constexpr const auto diff = CombinationType::difference; - constexpr const auto sum = CombinationType::sum; - constexpr const auto prod = CombinationType::product; - constexpr const auto g_dim = G::dimension; - - auto i_1_1 = bind_GridFunctionInterface<G, 1, 1>(m, grid_id); - auto i_1_2 = bind_GridFunctionInterface<G, 1, 2>(m, grid_id); - auto i_1_3 = bind_GridFunctionInterface<G, 1, 3>(m, grid_id); - auto i_2_1 = bind_GridFunctionInterface<G, 2, 1>(m, grid_id); - auto i_2_2 = bind_GridFunctionInterface<G, 2, 2>(m, grid_id); - auto i_2_3 = bind_GridFunctionInterface<G, 2, 3>(m, grid_id); - auto i_3_1 = bind_GridFunctionInterface<G, 3, 1>(m, grid_id); - auto i_3_2 = bind_GridFunctionInterface<G, 3, 2>(m, grid_id); - auto i_3_3 = bind_GridFunctionInterface<G, 3, 3>(m, grid_id); - - bind_combined_GridFunction<G, g_dim, diff, 1, 1, 1, 1>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, diff, 1, 1, 1, 1>(i_1_1); - bind_combined_GridFunction<G, g_dim, diff, 1, 2, 1, 2>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, diff, 1, 2, 1, 2>(i_1_2); - bind_combined_GridFunction<G, g_dim, diff, 1, 3, 1, 3>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, diff, 1, 3, 1, 3>(i_1_3); - bind_combined_GridFunction<G, g_dim, diff, 2, 1, 2, 1>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, diff, 2, 1, 2, 1>(i_2_1); - bind_combined_GridFunction<G, g_dim, diff, 2, 2, 2, 2>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, diff, 2, 2, 2, 2>(i_2_2); - bind_combined_GridFunction<G, g_dim, diff, 2, 3, 2, 3>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, diff, 2, 3, 2, 3>(i_2_3); - bind_combined_GridFunction<G, g_dim, diff, 3, 1, 3, 1>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, diff, 3, 1, 3, 1>(i_3_1); - bind_combined_GridFunction<G, g_dim, diff, 3, 2, 3, 2>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, diff, 3, 2, 3, 2>(i_3_2); - bind_combined_GridFunction<G, g_dim, diff, 3, 3, 3, 3>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, diff, 3, 3, 3, 3>(i_3_3); - - bind_combined_GridFunction<G, g_dim, sum, 1, 1, 1, 1>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, sum, 1, 1, 1, 1>(i_1_1); - bind_combined_GridFunction<G, g_dim, sum, 1, 2, 1, 2>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, sum, 1, 2, 1, 2>(i_1_2); - bind_combined_GridFunction<G, g_dim, sum, 1, 3, 1, 3>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, sum, 1, 3, 1, 3>(i_1_3); - bind_combined_GridFunction<G, g_dim, sum, 2, 1, 2, 1>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, sum, 2, 1, 2, 1>(i_2_1); - bind_combined_GridFunction<G, g_dim, sum, 2, 2, 2, 2>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, sum, 2, 2, 2, 2>(i_2_2); - bind_combined_GridFunction<G, g_dim, sum, 2, 3, 2, 3>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, sum, 2, 3, 2, 3>(i_2_3); - bind_combined_GridFunction<G, g_dim, sum, 3, 1, 3, 1>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, sum, 3, 1, 3, 1>(i_3_1); - bind_combined_GridFunction<G, g_dim, sum, 3, 2, 3, 2>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, sum, 3, 2, 3, 2>(i_3_2); - bind_combined_GridFunction<G, g_dim, sum, 3, 3, 3, 3>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, sum, 3, 3, 3, 3>(i_3_3); - - bind_combined_GridFunction<G, g_dim, prod, 1, 1, 1, 1>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, prod, 1, 1, 1, 1>(i_1_1); - bind_combined_GridFunction<G, g_dim, prod, 1, 1, 1, 2>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, prod, 1, 1, 1, 2>(i_1_1); - bind_combined_GridFunction<G, g_dim, prod, 1, 1, 1, 3>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, prod, 1, 1, 1, 3>(i_1_1); - bind_combined_GridFunction<G, g_dim, prod, 1, 1, 2, 1>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, prod, 1, 1, 2, 1>(i_1_1); - bind_combined_GridFunction<G, g_dim, prod, 1, 1, 2, 2>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, prod, 1, 1, 2, 2>(i_1_1); - bind_combined_GridFunction<G, g_dim, prod, 1, 1, 2, 3>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, prod, 1, 1, 2, 3>(i_1_1); - bind_combined_GridFunction<G, g_dim, prod, 1, 1, 3, 1>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, prod, 1, 1, 3, 1>(i_1_1); - bind_combined_GridFunction<G, g_dim, prod, 1, 1, 3, 2>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, prod, 1, 1, 3, 2>(i_1_1); - bind_combined_GridFunction<G, g_dim, prod, 1, 1, 3, 3>(m, grid_id); - addbind_GridFunctionInterface_combined_op<G, g_dim, prod, 1, 1, 3, 3>(i_1_1); -} // ... addbind_GridFunctionInterface_all_dims(...) - - -} // namespace bindings -} // namespace Functions -} // namespace XT -} // namespace Dune - -#endif // DUNE_XT_FUNCTIONS_INTERFACE_PBH diff --git a/python/dune/xt/functions/gridfunction.cc b/python/dune/xt/functions/gridfunction.cc index df6a82d39ffc3e3007dbd3b431aea66d71723eec..6ab69fb96f8c69bf8964cea98d1c5afcc5fea2e5 100644 --- a/python/dune/xt/functions/gridfunction.cc +++ b/python/dune/xt/functions/gridfunction.cc @@ -57,9 +57,16 @@ private: namespace py = pybind11; using namespace pybind11::literals; - c.def(py::init<const typename RangeTypeSelector<R, r, rC>::type&>(), "constant_matrix"_a); - c.def(py::init<const FunctionInterface<d, r, rC, R>&>(), "matrix_function"_a, py::keep_alive<1, 2>()); - c.def(py::init<const GridFunctionInterface<E, r, rC, R>&>(), "matrix_grid_function"_a, py::keep_alive<1, 2>()); + c.def(py::init<const typename RangeTypeSelector<R, r, rC>::type&, const std::string&, const std::string&>(), + "constant_matrix"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); + c.def(py::init<const FunctionInterface<d, r, rC, R>&, const std::string&>(), + "matrix_function"_a, + "logging_prefix"_a = ""); + c.def(py::init<const GridFunctionInterface<E, r, rC, R>&, const std::string&>(), + "matrix_grid_function"_a, + "logging_prefix"_a = ""); } // ... init(...) static void factory(pybind11::module& m, const std::string& FactoryName) @@ -70,63 +77,70 @@ private: // without dimRange m.def( FactoryName.c_str(), - [](const GP&, const typename RangeTypeSelector<R, r, rC>::type& constant_matrix) { - return type(constant_matrix); - }, + [](const GP&, + const typename RangeTypeSelector<R, r, rC>::type& constant_matrix, + const std::string& name, + const std::string& logging_prefix) { return new type(constant_matrix, name, logging_prefix); }, "grid"_a, - "constant_matrix"_a); + "constant_matrix"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const FunctionInterface<d, r, rC, R>& matrix_function) { return type(matrix_function); }, + [](const GP&, const FunctionInterface<d, r, rC, R>& matrix_function, const std::string& logging_prefix) { + return new type(matrix_function, logging_prefix); + }, "grid"_a, "matrix_function"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const GridFunctionInterface<E, r, rC, R>& matrix_grid_function) { - return type(matrix_grid_function); - }, + [](const GP&, + const GridFunctionInterface<E, r, rC, R>& matrix_grid_function, + const std::string& logging_prefix) { return new type(matrix_grid_function, logging_prefix); }, "grid"_a, "matrix_grid_function"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GridFunctionInterface<E, r, rC, R>& matrix_grid_function) { return type(matrix_grid_function); }, + [](const GridFunctionInterface<E, r, rC, R>& matrix_grid_function, const std::string& logging_prefix) { + return new type(matrix_grid_function, logging_prefix); + }, "matrix_grid_function"_a, - py::keep_alive<0, 1>()); + "logging_prefix"_a = ""); // and with dimRange m.def( FactoryName.c_str(), [](const GP&, const typename RangeTypeSelector<R, r, rC>::type& constant_matrix, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(constant_matrix); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& name, + const std::string& logging_prefix) { return new type(constant_matrix, name, logging_prefix); }, "grid"_a, "constant_matrix"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const FunctionInterface<d, r, rC, R>& matrix_function, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(matrix_function); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& logging_prefix) { return new type(matrix_function, logging_prefix); }, "grid"_a, "matrix_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const GridFunctionInterface<E, r, rC, R>& matrix_grid_function, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(matrix_grid_function); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& logging_prefix) { return new type(matrix_grid_function, logging_prefix); }, "grid"_a, "matrix_grid_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); } // ... factory (...) }; // struct dim_dependent<r, rC, anything>, the general case, neither scalar nor square matrix @@ -138,10 +152,20 @@ private: namespace py = pybind11; using namespace pybind11::literals; - c.def(py::init<const R&>(), "constant_scalar"_a); - c.def(py::init<const FieldVector<R, 1>&>(), "constant_vector_of_length_one"_a); - c.def(py::init<const FunctionInterface<d, 1, 1, R>&>(), "scalar_function"_a, py::keep_alive<1, 2>()); - c.def(py::init<const GridFunctionInterface<E, 1, 1, R>&>(), "scalar_grid_function"_a, py::keep_alive<1, 2>()); + c.def(py::init<const R&, const std::string&, const std::string&>(), + "constant_scalar"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); + c.def(py::init<const FieldVector<R, 1>&, const std::string&, const std::string&>(), + "constant_vector_of_length_one"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); + c.def(py::init<const FunctionInterface<d, 1, 1, R>&, const std::string&>(), + "scalar_function"_a, + "logging_prefix"_a = ""); + c.def(py::init<const GridFunctionInterface<E, 1, 1, R>&, const std::string&>(), + "scalar_grid_function"_a, + "logging_prefix"_a = ""); } // ... init(...) static void factory(pybind11::module& m, const std::string& FactoryName) @@ -152,113 +176,142 @@ private: // without dimRange m.def( FactoryName.c_str(), - [](const GP&, const R& constant_scalar) { return type(constant_scalar); }, + [](const GP&, const R& constant_scalar, const std::string& name, const std::string& logging_prefix) { + return new type(constant_scalar, name, logging_prefix); + }, "grid"_a, - "constant_scalar"_a); + "constant_scalar"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const FieldVector<R, 1>& constant_vector_of_length_one) { - return type(constant_vector_of_length_one); + [](const GP&, + const FieldVector<R, 1>& constant_vector_of_length_one, + const std::string& name, + const std::string& logging_prefix) { + return new type(constant_vector_of_length_one, name, logging_prefix); }, "grid"_a, - "constant_vector_of_length_one"_a); + "constant_vector_of_length_one"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const FunctionInterface<d, 1, 1, R>& scalar_function) { return type(scalar_function); }, + [](const GP&, const FunctionInterface<d, 1, 1, R>& scalar_function, const std::string& logging_prefix) { + return new type(scalar_function, logging_prefix); + }, "grid"_a, "scalar_function"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const GridFunctionInterface<E, 1, 1, R>& scalar_grid_function) { - return type(scalar_grid_function); - }, + [](const GP&, + const GridFunctionInterface<E, 1, 1, R>& scalar_grid_function, + const std::string& logging_prefix) { return new type(scalar_grid_function, logging_prefix); }, "grid"_a, "scalar_grid_function"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GridFunctionInterface<E, 1, 1, R>& scalar_grid_function) { return type(scalar_grid_function); }, + [](const GridFunctionInterface<E, 1, 1, R>& scalar_grid_function, const std::string& logging_prefix) { + return new type(scalar_grid_function, logging_prefix); + }, "scalar_grid_function"_a, - py::keep_alive<0, 1>()); + "logging_prefix"_a = ""); // and with dimRange, to distinguish from the square matrix case m.def( FactoryName.c_str(), - [](const GP&, const R& constant_scalar, const Grid::bindings::Dimension<1>&) { - return type(constant_scalar); - }, + [](const GP&, + const R& constant_scalar, + const Grid::bindings::Dimension<1>&, + const std::string& name, + const std::string& logging_prefix) { return new type(constant_scalar, name, logging_prefix); }, "grid"_a, "constant_scalar"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const FieldVector<R, 1>& constant_vector_of_length_one, const Grid::bindings::Dimension<1>&) { - return type(constant_vector_of_length_one); + [](const GP&, + const FieldVector<R, 1>& constant_vector_of_length_one, + const Grid::bindings::Dimension<1>&, + const std::string& name, + const std::string& logging_prefix) { + return new type(constant_vector_of_length_one, name, logging_prefix); }, "grid"_a, "constant_vector_of_length_one"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const FunctionInterface<d, 1, 1, R>& scalar_function, const Grid::bindings::Dimension<1>&) { - return type(scalar_function); - }, + [](const GP&, + const FunctionInterface<d, 1, 1, R>& scalar_function, + const Grid::bindings::Dimension<1>&, + const std::string& logging_prefix) { return new type(scalar_function, logging_prefix); }, "grid"_a, "scalar_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const GridFunctionInterface<E, 1, 1, R>& scalar_grid_function, - const Grid::bindings::Dimension<1>&) { return type(scalar_grid_function); }, + const Grid::bindings::Dimension<1>&, + const std::string& logging_prefix) { return new type(scalar_grid_function, logging_prefix); }, "grid"_a, "scalar_grid_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); // and with dimRange x dimRangeCols m.def( FactoryName.c_str(), [](const GP&, const R& constant_scalar, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(constant_scalar); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& name, + const std::string& logging_prefix) { return new type(constant_scalar, name, logging_prefix); }, "grid"_a, "constant_scalar"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const FieldVector<R, 1>& constant_vector_of_length_one, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(constant_vector_of_length_one); + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& name, + const std::string& logging_prefix) { + return new type(constant_vector_of_length_one, name, logging_prefix); }, "grid"_a, "constant_vector_of_length_one"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const FunctionInterface<d, 1, 1, R>& scalar_function, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(scalar_function); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& logging_prefix) { return new type(scalar_function, logging_prefix); }, "grid"_a, "scalar_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const GridFunctionInterface<E, 1, 1, R>& scalar_grid_function, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(scalar_grid_function); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& logging_prefix) { return new type(scalar_grid_function, logging_prefix); }, "grid"_a, "scalar_grid_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); } // ... factory (...) }; // struct dim_dependent<1, 1, anything> the scalar case @@ -270,9 +323,16 @@ private: namespace py = pybind11; using namespace pybind11::literals; - c.def(py::init<const typename RangeTypeSelector<R, r, rC>::type&>(), "constant_vector"_a); - c.def(py::init<const FunctionInterface<d, r, rC, R>&>(), "vector_function"_a, py::keep_alive<1, 2>()); - c.def(py::init<const GridFunctionInterface<E, r, rC, R>&>(), "vector_grid_function"_a, py::keep_alive<1, 2>()); + c.def(py::init<const typename RangeTypeSelector<R, r, rC>::type&, const std::string&, const std::string&>(), + "constant_vector"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); + c.def(py::init<const FunctionInterface<d, r, rC, R>&, const std::string&>(), + "vector_function"_a, + "logging_prefix"_a = ""); + c.def(py::init<const GridFunctionInterface<E, r, rC, R>&, const std::string&>(), + "vector_grid_function"_a, + "logging_prefix"_a = ""); } // ... init(...) static void factory(pybind11::module& m, const std::string& FactoryName) @@ -283,90 +343,103 @@ private: // without dimRange m.def( FactoryName.c_str(), - [](const GP&, const typename RangeTypeSelector<R, r, rC>::type& constant_vector) { - return type(constant_vector); - }, + [](const GP&, + const typename RangeTypeSelector<R, r, rC>::type& constant_vector, + const std::string& name, + const std::string& logging_prefix) { return new type(constant_vector, name, logging_prefix); }, "grid"_a, - "constant_vector"_a); + "constant_vector"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const FunctionInterface<d, r, rC, R>& vector_function) { return type(vector_function); }, + [](const GP&, const FunctionInterface<d, r, rC, R>& vector_function, const std::string& logging_prefix) { + return new type(vector_function, logging_prefix); + }, "grid"_a, "vector_function"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const GridFunctionInterface<E, r, rC, R>& vector_grid_function) { - return type(vector_grid_function); - }, + [](const GP&, + const GridFunctionInterface<E, r, rC, R>& vector_grid_function, + const std::string& logging_prefix) { return new type(vector_grid_function, logging_prefix); }, "grid"_a, "vector_grid_function"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GridFunctionInterface<E, r, rC, R>& vector_grid_function) { return type(vector_grid_function); }, + [](const GridFunctionInterface<E, r, rC, R>& vector_grid_function, const std::string& logging_prefix) { + return new type(vector_grid_function, logging_prefix); + }, "vector_grid_function"_a, - py::keep_alive<0, 1>()); + "logging_prefix"_a = ""); // with dimRange m.def( FactoryName.c_str(), [](const GP&, const typename RangeTypeSelector<R, r, rC>::type& constant_vector, - const Grid::bindings::Dimension<r>&) { return type(constant_vector); }, + const Grid::bindings::Dimension<r>&, + const std::string& name, + const std::string& logging_prefix) { return new type(constant_vector, name, logging_prefix); }, "grid"_a, "constant_vector"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const FunctionInterface<d, r, rC, R>& vector_function, const Grid::bindings::Dimension<r>&) { - return type(vector_function); - }, + [](const GP&, + const FunctionInterface<d, r, rC, R>& vector_function, + const Grid::bindings::Dimension<r>&, + const std::string& logging_prefix) { return new type(vector_function, logging_prefix); }, "grid"_a, "vector_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const GridFunctionInterface<E, r, rC, R>& vector_grid_function, - const Grid::bindings::Dimension<r>&) { return type(vector_grid_function); }, + const Grid::bindings::Dimension<r>&, + const std::string& logging_prefix) { return new type(vector_grid_function, logging_prefix); }, "grid"_a, "vector_grid_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); // with dimRange x 1 m.def( FactoryName.c_str(), [](const GP&, const typename RangeTypeSelector<R, r, rC>::type& constant_vector, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<1>>&) { - return type(constant_vector); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<1>>&, + const std::string& name, + const std::string& logging_prefix) { return new type(constant_vector, name, logging_prefix); }, "grid"_a, "constant_vector"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const FunctionInterface<d, r, rC, R>& vector_function, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<1>>&) { - return type(vector_function); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<1>>&, + const std::string& logging_prefix) { return new type(vector_function, logging_prefix); }, "grid"_a, "vector_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const GridFunctionInterface<E, r, rC, R>& vector_grid_function, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<1>>&) { - return type(vector_grid_function); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<1>>&, + const std::string& logging_prefix) { return new type(vector_grid_function, logging_prefix); }, "grid"_a, "vector_grid_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); } // ... factory (...) }; // struct dim_dependent<r, 1, anything>, the non scalar vector case @@ -382,11 +455,16 @@ private: dim_dependent<1, 1>::init(c); // .. and the matrix ones - c.def(py::init<const FieldMatrix<R, r, rC>&>(), "constant_square_matrix"_a); - c.def(py::init<const FunctionInterface<d, r, rC, R>&>(), "square_matrix_function"_a, py::keep_alive<1, 2>()); - c.def(py::init<const GridFunctionInterface<E, r, rC, R>&>(), + c.def(py::init<const FieldMatrix<R, r, rC>&, const std::string&, const std::string&>(), + "constant_square_matrix"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); + c.def(py::init<const FunctionInterface<d, r, rC, R>&, const std::string&>(), + "square_matrix_function"_a, + "logging_prefix"_a = ""); + c.def(py::init<const GridFunctionInterface<E, r, rC, R>&, const std::string&>(), "square_matrix_grid_function"_a, - py::keep_alive<1, 2>()); + "logging_prefix"_a = ""); } // ... init(...) static void factory(pybind11::module& m, const std::string& FactoryName) @@ -400,71 +478,76 @@ private: // .. and the matrix ones, without dimRange m.def( FactoryName.c_str(), - [](const GP&, const FieldMatrix<R, r, rC>& constant_square_matrix) { return type(constant_square_matrix); }, + [](const GP&, + const FieldMatrix<R, r, rC>& constant_square_matrix, + const std::string& name, + const std::string& logging_prefix) { return new type(constant_square_matrix, name, logging_prefix); }, "grid"_a, - "constant_square_matrix"_a); + "constant_square_matrix"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const FunctionInterface<d, r, rC, R>& square_matrix_function) { - return type(square_matrix_function); - }, + [](const GP&, + const FunctionInterface<d, r, rC, R>& square_matrix_function, + const std::string& logging_prefix) { return new type(square_matrix_function, logging_prefix); }, "grid"_a, "square_matrix_function"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GP&, const GridFunctionInterface<E, r, rC, R>& square_matrix_grid_function) { - return type(square_matrix_grid_function); - }, + [](const GP&, + const GridFunctionInterface<E, r, rC, R>& square_matrix_grid_function, + const std::string& logging_prefix) { return new type(square_matrix_grid_function, logging_prefix); }, "grid"_a, "square_matrix_grid_function"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), - [](const GridFunctionInterface<E, r, rC, R>& square_matrix_grid_function) { - return type(square_matrix_grid_function); + [](const GridFunctionInterface<E, r, rC, R>& square_matrix_grid_function, const std::string& logging_prefix) { + return new type(square_matrix_grid_function, logging_prefix); }, "square_matrix_grid_function"_a, - py::keep_alive<0, 1>()); + "logging_prefix"_a = ""); // .. and with dimRange m.def( FactoryName.c_str(), [](const GP&, const FieldMatrix<R, r, rC>& constant_square_matrix, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(constant_square_matrix); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& name, + const std::string& logging_prefix) { return new type(constant_square_matrix, name, logging_prefix); }, "grid"_a, "constant_square_matrix"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction", + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const FunctionInterface<d, r, rC, R>& square_matrix_function, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(square_matrix_function); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& logging_prefix) { return new type(square_matrix_function, logging_prefix); }, "grid"_a, "square_matrix_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); m.def( FactoryName.c_str(), [](const GP&, const GridFunctionInterface<E, r, rC, R>& square_matrix_grid_function, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return type(square_matrix_grid_function); - }, + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& logging_prefix) { return new type(square_matrix_grid_function, logging_prefix); }, "grid"_a, "square_matrix_grid_function"_a, "dim_range"_a, - py::keep_alive<0, 2>()); + "logging_prefix"_a = ""); } // ... factory (...) }; // struct dim_dependent<r_, r_, anything> the square matrix (but not scalar) case public: static bound_type bind(pybind11::module& m, - const std::string& grid_id = Grid::bindings::grid_name<G>::value(), + const std::string& grid_id, const std::string& layer_id = "", const std::string& class_id = "grid_function") { @@ -483,76 +566,87 @@ public: class_name += "_" + Common::Typename<R>::value(/*fail_wo_typeid=*/true); const auto ClassName = Common::to_camel_case(class_name); bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); - c.def(py::init([](int order, typename GFT::GenericEvaluateFunctionType evaluate) { - return new type({order, evaluate}); + c.def(py::init([](int order, typename GFT::GenericEvaluateFunctionType evaluate, const std::string& name) { + return new type({order, evaluate, name}); }), "order"_a, - "evaluate_lambda"_a); + "evaluate_lambda"_a, + "name"_a = "GridFunction"); c.def(py::init([](int order, typename GFT::GenericEvaluateFunctionType evaluate, - typename GFT::GenericJacobianFunctionType jacobian) { - return new type({order, evaluate, jacobian}); + typename GFT::GenericJacobianFunctionType jacobian, + const std::string& name) { + return new type({order, evaluate, jacobian, name}); }), "order"_a, "evaluate_lambda"_a, - "jacobian_lambda"_a); + "jacobian_lambda"_a, + "name"_a = "GridFunction"); dim_dependent<>::init(c); const auto FactoryName = Common::to_camel_case(class_id); - if (rC == 1) { // two variants opposed to four above + if (rC == 1) { // two variants here opposed to four above m.def( FactoryName.c_str(), [](const GP&, int order, typename GFT::GenericEvaluateFunctionType evaluate, - const Grid::bindings::Dimension<r>&) { - return new type({order, evaluate}); + const Grid::bindings::Dimension<r>&, + const std::string& name) { + return new type({order, evaluate, name}); }, "grid"_a, "order"_a, "evaluate_lambda"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction"); m.def( FactoryName.c_str(), [](const GP&, int order, typename GFT::GenericEvaluateFunctionType evaluate, typename GFT::GenericJacobianFunctionType jacobian, - const Grid::bindings::Dimension<r>&) { - return new type({order, evaluate, jacobian}); + const Grid::bindings::Dimension<r>&, + const std::string& name) { + return new type({order, evaluate, jacobian, name}); }, "grid"_a, "order"_a, "evaluate_lambda"_a, "jacobian_lambda"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction"); } else { m.def( FactoryName.c_str(), [](const GP&, int order, typename GFT::GenericEvaluateFunctionType evaluate, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return new type({order, evaluate}); + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& name) { + return new type({order, evaluate, name}); }, "grid"_a, "order"_a, "evaluate_lambda"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction"); m.def( FactoryName.c_str(), [](const GP&, int order, typename GFT::GenericEvaluateFunctionType evaluate, typename GFT::GenericJacobianFunctionType jacobian, - const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&) { - return new type({order, evaluate, jacobian}); + const std::pair<Grid::bindings::Dimension<r>, Grid::bindings::Dimension<rC>>&, + const std::string& name) { + return new type({order, evaluate, jacobian, name}); }, "grid"_a, "order"_a, "evaluate_lambda"_a, "jacobian_lambda"_a, - "dim_range"_a); + "dim_range"_a, + "name"_a = "GridFunction"); } dim_dependent<>::factory(m, FactoryName); return c; @@ -579,15 +673,15 @@ struct GridFunction_for_all_grids using Dune::XT::Functions::bindings::GridFunction; using Dune::XT::Grid::bindings::grid_name; - GridFunction<G, E, 1, 1>::bind(m); - GridFunction<G, E, 1, 2>::bind(m); - GridFunction<G, E, 1, 3>::bind(m); - GridFunction<G, E, 2, 1>::bind(m); - GridFunction<G, E, 2, 2>::bind(m); - GridFunction<G, E, 2, 3>::bind(m); - GridFunction<G, E, 3, 1>::bind(m); - GridFunction<G, E, 3, 2>::bind(m); - GridFunction<G, E, 3, 3>::bind(m); + GridFunction<G, E, 1, 1>::bind(m, grid_name<G>::value()); + GridFunction<G, E, 1, 2>::bind(m, grid_name<G>::value()); + GridFunction<G, E, 1, 3>::bind(m, grid_name<G>::value()); + GridFunction<G, E, 2, 1>::bind(m, grid_name<G>::value()); + GridFunction<G, E, 2, 2>::bind(m, grid_name<G>::value()); + GridFunction<G, E, 2, 3>::bind(m, grid_name<G>::value()); + GridFunction<G, E, 3, 1>::bind(m, grid_name<G>::value()); + GridFunction<G, E, 3, 2>::bind(m, grid_name<G>::value()); + GridFunction<G, E, 3, 3>::bind(m, grid_name<G>::value()); GridFunction_for_all_grids<typename GridTypes::tail_type>::bind(m); } @@ -607,9 +701,9 @@ PYBIND11_MODULE(_functions_gridfunction, m) py::module::import("dune.xt.common"); py::module::import("dune.xt.grid"); py::module::import("dune.xt.la"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_1d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_2d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_3d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); GridFunction_for_all_grids<>::bind(m); } // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/indicator.cc b/python/dune/xt/functions/indicator.cc index f866bfe89611430854c5ff8f1bbf270b9eda31cb..8c81752cbcef9fa71c0d0ad63289c7abfdf4d17e 100644 --- a/python/dune/xt/functions/indicator.cc +++ b/python/dune/xt/functions/indicator.cc @@ -57,9 +57,9 @@ PYBIND11_MODULE(_functions_indicator, m) py::module::import("dune.xt.common"); py::module::import("dune.xt.la"); py::module::import("dune.xt.grid"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_1d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_2d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_3d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); all_grids(m); diff --git a/python/dune/xt/functions/interfaces/grid-function.hh b/python/dune/xt/functions/interfaces/grid-function.hh new file mode 100644 index 0000000000000000000000000000000000000000..e8e7d752997e74216d76d68f984cecdb06464a68 --- /dev/null +++ b/python/dune/xt/functions/interfaces/grid-function.hh @@ -0,0 +1,202 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License +// (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#ifndef PYTHON_DUNE_XT_FUNCTIONS_INTERFACES_GRID_FUNCTION_HH +#define PYTHON_DUNE_XT_FUNCTIONS_INTERFACES_GRID_FUNCTION_HH + +#include <dune/pybindxi/pybind11.h> + +#include <dune/xt/common/string.hh> +#include <dune/xt/functions/interfaces/grid-function.hh> +#include <dune/xt/grid/gridprovider/provider.hh> + +#include <python/dune/xt/common/parameter.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace bindings { + + +template <class G, class E, size_t r = 1, size_t rC = 1, class R = double> +class GridFunctionInterface +{ + using GP = XT::Grid::GridProvider<G>; + static const constexpr size_t d = G::dimension; + + template <bool vector = (r != 1 && rC == 1), bool matrix = (rC != 1), bool anything = false> + struct product_helper // <true, false, ...> + { + template <class T, typename... options> + static void addbind(pybind11::class_<T, options...>& c) + { + namespace py = pybind11; + + c.def( + "__mul__", + [](const T& self, const Functions::GridFunctionInterface<E, r, 1, R>& other) { + return std::make_unique<decltype(self * other)>(self * other); + }, + py::is_operator()); + } + }; + + template <bool anything> + struct product_helper<false, true, anything> + { + template <class T, typename... options> + static void addbind(pybind11::class_<T, options...>& c) + { + namespace py = pybind11; + + c.def( + "__mul__", + [](const T& self, const Functions::GridFunctionInterface<E, rC, 1, R>& other) { + return std::make_unique<decltype(self * other)>(self * other); + }, + py::is_operator()); + c.def( + "__mul__", + [](const T& self, const Functions::GridFunctionInterface<E, rC, 2, R>& other) { + return std::make_unique<decltype(self * other)>(self * other); + }, + py::is_operator()); + c.def( + "__mul__", + [](const T& self, const Functions::GridFunctionInterface<E, rC, 3, R>& other) { + return std::make_unique<decltype(self * other)>(self * other); + }, + py::is_operator()); + } + }; + + template <bool scalar = (r == 1 && rC == 1), bool anything = false> + struct fraction_helper // <true, ...> + { + template <class T, typename... options> + static void addbind(pybind11::class_<T, options...>& c) + { + namespace py = pybind11; + + c.def( + "__truediv__", + [](const T& self, const type& other) { return std::make_unique<decltype(other / self)>(other / self); }, + py::is_operator()); + } + }; + + template <bool anything> + struct fraction_helper<false, anything> + { + template <class T, typename... options> + static void addbind(pybind11::class_<T, options...>& /*c*/) + {} + }; + +public: + using type = Functions::GridFunctionInterface<E, r, rC, R>; + using bound_type = pybind11::class_<type>; + + static std::string class_name(const std::string& grid_id, const std::string& layer_id, const std::string& class_id) + { + std::string ret = class_id; + ret += "_" + grid_id; + if (!layer_id.empty()) + ret += "_" + layer_id; + ret += "_to_" + Common::to_string(r); + if (rC > 1) + ret += "x" + Common::to_string(rC); + ret += "d"; + if (!std::is_same<R, double>::value) + ret += "_" + Common::Typename<R>::value(/*fail_wo_typeid=*/true); + return ret; + } // ... class_name(...) + + template <class T, typename... options> + static void addbind_methods(pybind11::class_<T, options...>& c) + { + namespace py = pybind11; + using namespace pybind11::literals; + + // our methods + c.def( + "visualize", + [](const T& self, const GP& grid_provider, const std::string& filename, const bool subsampling) { + self.visualize(grid_provider.leaf_view(), filename, subsampling); + }, + "grid"_a, + "filename"_a, + "subsampling"_a = true); + // our operators + c.def( + "__add__", + [](const T& self, const type& other) { return std::make_unique<decltype(self + other)>(self + other); }, + py::is_operator()); + c.def( + "__sub__", + [](const T& self, const type& other) { return std::make_unique<decltype(self - other)>(self - other); }, + py::is_operator()); + // we can always multiply with a scalar from the right ... + c.def( + "__mul__", + [](const T& self, const Functions::GridFunctionInterface<E, 1, 1, R>& other) { + return std::make_unique<decltype(self * other)>(self * other); + }, + py::is_operator()); + // .. and with lots of other dims + product_helper<>::addbind(c); + fraction_helper<>::addbind(c); + + if constexpr (r == 1 && rC == 1) + c.def( + "__pow__", + [](const T& self) { return std::make_unique<decltype(self * self)>(self * self); }, + py::is_operator()); + + // ParametricInterface methods + c.def( + "parse_parameter", [](const T& self, const Common::Parameter& mu) { return self.parse_parameter(mu); }, "mu"_a); + } // ... addbind_methods(...) + + static bound_type bind(pybind11::module& m, + const std::string& grid_id, + const std::string& layer_id = "", + const std::string& class_id = "grid_function_interface") + { + namespace py = pybind11; + using namespace pybind11::literals; + + const auto ClassName = Common::to_camel_case(class_name(grid_id, layer_id, class_id)); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + + // our properties + c.def_property_readonly("dim_domain", [](type&) { return size_t(d); }); + if (rC == 1) + c.def_property_readonly("dim_range", [](type&) { return size_t(r); }); + else + c.def_property_readonly("dim_range", [](type&) { return std::make_pair(size_t(r), size_t(rC)); }); + c.def_property_readonly("name", [](type& self) { return self.name(); }); + // ParametricInterface properties + c.def_property_readonly("is_parametric", [](type& self) { return self.is_parametric(); }); + c.def_property_readonly("parameter_type", [](type& self) { return self.parameter_type(); }); + + addbind_methods(c); + + return c; + } +}; // class GridFunctionInterface + + +} // namespace bindings +} // namespace Functions +} // namespace XT +} // namespace Dune + +#endif // PYTHON_DUNE_XT_FUNCTIONS_INTERFACES_GRID_FUNCTION_HH diff --git a/python/dune/xt/functions/interfaces/grid-function_1d.cc b/python/dune/xt/functions/interfaces/grid-function_1d.cc new file mode 100644 index 0000000000000000000000000000000000000000..a1048fb91ea661b3bf96a201a4ab205d7a0f6596 --- /dev/null +++ b/python/dune/xt/functions/interfaces/grid-function_1d.cc @@ -0,0 +1,29 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#include "config.h" + +#include <dune/xt/grid/grids.hh> + +#include "grid-function_for_all_grids.hh" + + +PYBIND11_MODULE(_functions_interfaces_grid_function_1d, m) +{ + namespace py = pybind11; + + py::module::import("dune.xt.common"); + py::module::import("dune.xt.grid"); + py::module::import("dune.xt.la"); + + // All of these need to be there ... + GridFunctionInterface_for_all_grids<boost::tuple<ONED_1D>>::bind_interface(m); + // ... before we start binding those. + GridFunctionInterface_for_all_grids<boost::tuple<ONED_1D>>::bind_combined(m); +} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/interfaces/grid-function_2d.cc b/python/dune/xt/functions/interfaces/grid-function_2d.cc new file mode 100644 index 0000000000000000000000000000000000000000..400780e7750aa43e0bc0b2b2b9929082cdcbf53f --- /dev/null +++ b/python/dune/xt/functions/interfaces/grid-function_2d.cc @@ -0,0 +1,39 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#include "config.h" + +#include <dune/xt/grid/grids.hh> + +#include "grid-function_for_all_grids.hh" + + +PYBIND11_MODULE(_functions_interfaces_grid_function_2d, m) +{ + namespace py = pybind11; + + py::module::import("dune.xt.common"); + py::module::import("dune.xt.grid"); + py::module::import("dune.xt.la"); + + // All of these need to be there ... + GridFunctionInterface_for_all_grids<boost::tuple<YASP_2D_EQUIDISTANT_OFFSET +#if HAVE_DUNE_ALUGRID + , + ALU_2D_SIMPLEX_CONFORMING +#endif + >>::bind_interface(m); + // ... before we start binding those. + GridFunctionInterface_for_all_grids<boost::tuple<YASP_2D_EQUIDISTANT_OFFSET +#if HAVE_DUNE_ALUGRID + , + ALU_2D_SIMPLEX_CONFORMING +#endif + >>::bind_combined(m); +} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/interfaces/grid-function_3d.cc b/python/dune/xt/functions/interfaces/grid-function_3d.cc new file mode 100644 index 0000000000000000000000000000000000000000..8660b8d549b82c218df58822598180164dca7917 --- /dev/null +++ b/python/dune/xt/functions/interfaces/grid-function_3d.cc @@ -0,0 +1,39 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#include "config.h" + +#include <dune/xt/grid/grids.hh> + +#include "grid-function_for_all_grids.hh" + + +PYBIND11_MODULE(_functions_interfaces_grid_function_3d, m) +{ + namespace py = pybind11; + + py::module::import("dune.xt.common"); + py::module::import("dune.xt.grid"); + py::module::import("dune.xt.la"); + + // All of these need to be there ... + GridFunctionInterface_for_all_grids<boost::tuple<YASP_3D_EQUIDISTANT_OFFSET +#if HAVE_DUNE_ALUGRID + , + ALU_3D_SIMPLEX_CONFORMING +#endif + >>::bind_interface(m); + // ... before we start binding those. + GridFunctionInterface_for_all_grids<boost::tuple<YASP_3D_EQUIDISTANT_OFFSET +#if HAVE_DUNE_ALUGRID + , + ALU_3D_SIMPLEX_CONFORMING +#endif + >>::bind_combined(m); +} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/interfaces/grid-function_for_all_grids.hh b/python/dune/xt/functions/interfaces/grid-function_for_all_grids.hh new file mode 100644 index 0000000000000000000000000000000000000000..9d35efff5d83a6fb1161c3f9617d493f54356421 --- /dev/null +++ b/python/dune/xt/functions/interfaces/grid-function_for_all_grids.hh @@ -0,0 +1,173 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#ifndef PYTHON_DUNE_XT_FUNCTIONS_INTERFACES_GRID_FUNCTION_FOR_ALL_GRIDS_HH +#define PYTHON_DUNE_XT_FUNCTIONS_INTERFACES_GRID_FUNCTION_FOR_ALL_GRIDS_HH + +#include <dune/xt/grid/type_traits.hh> + +#include <python/dune/xt/functions/base/combined-grid-function.hh> + +#include "grid-function.hh" + + +template <size_t ii> +struct Int +{ + static const constexpr size_t value = ii; +}; + + +template <class GridTypes> +struct GridFunctionInterface_for_all_grids +{ + using G = typename GridTypes::head_type; + using GV = typename G::LeafGridView; + using E = Dune::XT::Grid::extract_entity_t<GV>; + static const constexpr size_t d = G::dimension; + + template <size_t r, class Dims = boost::tuple<Int<1>, Int<2>, Int<3>>> + struct for_all_rC + { + static const constexpr size_t rC = Dims::head_type::value; + + template <bool vector = (r != 1 && rC == 1), bool matrix = (rC != 1), bool anything = false> + struct product_helper // <true, false, ...> + { + static void addbind(pybind11::module& m) + { + using Dune::XT::Functions::bindings::ProductGridFunction; + using Dune::XT::Grid::bindings::grid_name; + + // special case: vector * vector + ProductGridFunction<G, E, r, 1, r, 1>::bind(m, grid_name<G>::value()); + } + }; + + template <bool anything> + struct product_helper<false, true, anything> + { + static void addbind(pybind11::module& m) + { + using Dune::XT::Functions::bindings::ProductGridFunction; + using Dune::XT::Grid::bindings::grid_name; + + // general case: matrix * matrix or vector + ProductGridFunction<G, E, r, rC, rC, 1>::bind(m, grid_name<G>::value()); + ProductGridFunction<G, E, r, rC, rC, 2>::bind(m, grid_name<G>::value()); + ProductGridFunction<G, E, r, rC, rC, 3>::bind(m, grid_name<G>::value()); + } + }; + + template <bool scalar = (r == 1 && rC == 1), bool anything = true> + struct fraction_helper + { + static void addbind(pybind11::module& m) + { + using Dune::XT::Functions::bindings::FractionGridFunction; + using Dune::XT::Grid::bindings::grid_name; + + FractionGridFunction<G, E>::bind(m, grid_name<G>::value()); + } + }; + + template <bool a> + struct fraction_helper<false, a> + { + static void addbind(pybind11::module& /*m*/) {} + }; + + static void bind_interface(pybind11::module& m) + { + using Dune::XT::Functions::bindings::GridFunctionInterface; + using Dune::XT::Grid::bindings::grid_name; + + GridFunctionInterface<G, E, r, rC>::bind(m, grid_name<G>::value()); + + for_all_rC<r, typename Dims::tail_type>::bind_interface(m); + } + + static void bind_combined(pybind11::module& m) + { + using Dune::XT::Functions::bindings::DifferenceGridFunction; + using Dune::XT::Functions::bindings::ProductGridFunction; + using Dune::XT::Functions::bindings::SumGridFunction; + using Dune::XT::Grid::bindings::grid_name; + + DifferenceGridFunction<G, E, r, rC>::bind(m, grid_name<G>::value()); + SumGridFunction<G, E, r, rC>::bind(m, grid_name<G>::value()); + product_helper<>::addbind(m); + fraction_helper<>::addbind(m); + + for_all_rC<r, typename Dims::tail_type>::bind_combined(m); + } + }; + + template <size_t r> + struct for_all_rC<r, boost::tuples::null_type> + { + static void bind_interface(pybind11::module& /*m*/) {} + + static void bind_combined(pybind11::module& /*m*/) {} + }; + + + template <class Dims = boost::tuple<Int<1>, Int<2>, Int<3>>, bool anything = false> + struct for_all_r_and_rC + { + static const constexpr size_t r = Dims::head_type::value; + + static void bind_interface(pybind11::module& m) + { + for_all_rC<r>::bind_interface(m); + + for_all_r_and_rC<typename Dims::tail_type>::bind_interface(m); + } + + static void bind_combined(pybind11::module& m) + { + for_all_rC<r>::bind_combined(m); + + for_all_r_and_rC<typename Dims::tail_type>::bind_combined(m); + } + }; + + template <bool a> + struct for_all_r_and_rC<boost::tuples::null_type, a> + { + static void bind_interface(pybind11::module& /*m*/) {} + + static void bind_combined(pybind11::module& /*m*/) {} + }; + + static void bind_interface(pybind11::module& m) + { + for_all_r_and_rC<>::bind_interface(m); + + GridFunctionInterface_for_all_grids<typename GridTypes::tail_type>::bind_interface(m); + } + + static void bind_combined(pybind11::module& m) + { + for_all_r_and_rC<>::bind_combined(m); + + GridFunctionInterface_for_all_grids<typename GridTypes::tail_type>::bind_combined(m); + } +}; + +template <> +struct GridFunctionInterface_for_all_grids<boost::tuples::null_type> +{ + static void bind_interface(pybind11::module& /*m*/) {} + + static void bind_combined(pybind11::module& /*m*/) {} +}; + + +#endif // PYTHON_DUNE_XT_FUNCTIONS_INTERFACES_GRID_FUNCTION_FOR_ALL_GRIDS_HH diff --git a/python/dune/xt/functions/inverse.cc b/python/dune/xt/functions/inverse.cc new file mode 100644 index 0000000000000000000000000000000000000000..8ae670831efd5e21a9a3ff0c7b18416f58902380 --- /dev/null +++ b/python/dune/xt/functions/inverse.cc @@ -0,0 +1,140 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2019) + +#include "config.h" + +#include <string> +#include <vector> + +#include <dune/common/parallel/mpihelper.hh> + +#include <dune/pybindxi/pybind11.h> +#include <dune/pybindxi/functional.h> +#include <dune/pybindxi/stl.h> + +#include <dune/xt/common/string.hh> +#include <dune/xt/grid/gridprovider/provider.hh> +#include <dune/xt/grid/type_traits.hh> +#include <dune/xt/functions/grid-function.hh> +#include <dune/xt/functions/inverse.hh> + +#include <python/dune/xt/common/parameter.hh> +#include <python/dune/xt/common/fvector.hh> +#include <python/dune/xt/common/fmatrix.hh> +#include <python/dune/xt/common/bindings.hh> +#include <python/dune/xt/grid/traits.hh> +#include <python/dune/xt/common/exceptions.bindings.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace bindings { + + +template <class G, class E, size_t r = 1, size_t rC = 1> +class InverseGridFunction +{ + using GP = XT::Grid::GridProvider<G>; + static const size_t d = G::dimension; + using GF = Functions::GridFunction<E, r, rC>; + +public: + using type = Functions::InverseGridFunction<GF>; + using base_type = typename type::BaseType; + using bound_type = pybind11::class_<type, base_type>; + +public: + static bound_type bind(pybind11::module& m, + const std::string& grid_id = Grid::bindings::grid_name<G>::value(), + const std::string& layer_id = "", + const std::string& class_id = "inverse_grid_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + std::string class_name = class_id; + class_name += "_" + grid_id; + if (!layer_id.empty()) + class_name += "_" + layer_id; + class_name += "_to_" + Common::to_string(r); + if (rC > 1) + class_name += "x" + Common::to_string(rC); + class_name += "d"; + const auto ClassName = Common::to_camel_case(class_name); + bound_type c(m, ClassName.c_str(), Common::to_camel_case(class_id).c_str()); + c.def( + py::init<GF, const int, const std::string&>(), "grid_function"_a, "order"_a, "name"_a = "InverseGridFunction"); + + m.def( + "inverse", + [](const GridFunctionInterface<E, r, rC>& grid_function, const int order, const std::string& name) { + return new type(grid_function, order, name); + }, + "grid_function"_a, + "order"_a, + "name"_a = "InverseGridFunction"); + m.def( + "inverse", + [](GF grid_function, const int order, const std::string& name) { return new type(grid_function, order, name); }, + "grid_function"_a, + "order"_a, + "name"_a = "InverseGridFunction"); + + return c; + } +}; // class GridFunction + + +} // namespace bindings +} // namespace Functions +} // namespace XT +} // namespace Dune + + +template <class GridTypes = Dune::XT::Grid::AvailableGridTypes> +struct InverseGridFunction_for_all_grids +{ + using G = typename GridTypes::head_type; + using GV = typename G::LeafGridView; + using E = Dune::XT::Grid::extract_entity_t<GV>; + + static void bind(pybind11::module& m) + { + using Dune::XT::Functions::bindings::InverseGridFunction; + using Dune::XT::Grid::bindings::grid_name; + + InverseGridFunction<G, E, 1, 1>::bind(m, grid_name<G>::value()); + InverseGridFunction<G, E, 2, 2>::bind(m, grid_name<G>::value()); + InverseGridFunction<G, E, 3, 3>::bind(m, grid_name<G>::value()); + + InverseGridFunction_for_all_grids<typename GridTypes::tail_type>::bind(m); + } +}; + +template <> +struct InverseGridFunction_for_all_grids<boost::tuples::null_type> +{ + static void bind(pybind11::module& /*m*/) {} +}; + + +PYBIND11_MODULE(_functions_inverse, m) +{ + namespace py = pybind11; + + py::module::import("dune.xt.common"); + py::module::import("dune.xt.grid"); + py::module::import("dune.xt.la"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); + py::module::import("dune.xt.functions._functions_gridfunction"); + + InverseGridFunction_for_all_grids<>::bind(m); +} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/parametric-expression.cc b/python/dune/xt/functions/parametric-expression.cc new file mode 100644 index 0000000000000000000000000000000000000000..2622420aa54fac7c63d64ab9bdd535c7ee6b251b --- /dev/null +++ b/python/dune/xt/functions/parametric-expression.cc @@ -0,0 +1,118 @@ +// This file is part of the dune-xt project: +// https://github.com/dune-community/dune-xt +// Copyright 2009-2020 dune-xt developers and contributors. All rights reserved. +// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) +// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) +// with "runtime exception" (http://www.dune-project.org/license.html) +// Authors: +// Felix Schindler (2020) + +#include "config.h" + +#include <string> +#include <vector> + +#include <dune/common/parallel/mpihelper.hh> + +#include <dune/pybindxi/pybind11.h> +#include <dune/pybindxi/stl.h> + +#include <dune/xt/common/string.hh> +#include <dune/xt/grid/gridprovider/provider.hh> +#include <dune/xt/grid/type_traits.hh> +#include <dune/xt/functions/expression/parametric.hh> + +#include <python/dune/xt/common/fvector.hh> +#include <python/dune/xt/common/fmatrix.hh> +#include <python/dune/xt/common/bindings.hh> +#include <python/dune/xt/common/parameter.hh> +#include <python/dune/xt/grid/traits.hh> +#include <python/dune/xt/common/exceptions.bindings.hh> + +namespace Dune { +namespace XT { +namespace Functions { +namespace bindings { + + +template <size_t d, size_t r = 1, class R = double> +class ParametricExpressionFunction +{ + static const constexpr size_t rC = 1; + + using type = Functions::ParametricExpressionFunction<d, r, rC, R>; + using base_type = Functions::FunctionInterface<d, r, rC, R>; + using bound_type = pybind11::class_<type, base_type>; + +public: + static bound_type bind(pybind11::module& m, const std::string& class_id = "parametric_expression_function") + { + namespace py = pybind11; + using namespace pybind11::literals; + + std::string class_name = class_id + "_" + Common::to_string(d) + "d_to_" + Common::to_string(r); + if (rC > 1) + class_name += "x" + Common::to_string(rC); + class_name += "d"; + const auto ClassName = Common::to_camel_case(class_name); + bound_type c(m, ClassName.c_str(), XT::Common::to_camel_case(class_id).c_str()); + c.def(py::init<const std::string&, + const Common::ParameterType&, + const Common::FieldVector<std::string, r>&, + const size_t, + const std::string>(), + "variable"_a, + "param_type"_a, + "expressions"_a, + "order"_a, + "name"_a = type::static_id()); + + m.def( + Common::to_camel_case(class_id).c_str(), + [](Grid::bindings::Dimension<d> /*dim_domain*/, + const std::string& variable, + const Common::ParameterType& param_type, + const Common::FieldVector<std::string, r>& expressions, + const size_t order, + const std::string& name) { return new type(variable, param_type, expressions, order, name); }, + "dim_domain"_a, + "variable"_a, + "param_type"_a, + "expressions"_a, + "order"_a, + "name"_a = type::static_id()); + + return c; + } +}; // class ParametricExpressionFunction + + +} // namespace bindings +} // namespace Functions +} // namespace XT +} // namespace Dune + + +PYBIND11_MODULE(_functions_parametric_expression, m) +{ + namespace py = pybind11; + + py::module::import("dune.xt.common"); + py::module::import("dune.xt.grid"); + py::module::import("dune.xt.la"); + py::module::import("dune.xt.functions._functions_function_interface_1d"); + py::module::import("dune.xt.functions._functions_function_interface_2d"); + py::module::import("dune.xt.functions._functions_function_interface_3d"); + + Dune::XT::Functions::bindings::ParametricExpressionFunction<1, 1>::bind(m); + Dune::XT::Functions::bindings::ParametricExpressionFunction<1, 2>::bind(m); + Dune::XT::Functions::bindings::ParametricExpressionFunction<1, 3>::bind(m); + + Dune::XT::Functions::bindings::ParametricExpressionFunction<2, 1>::bind(m); + Dune::XT::Functions::bindings::ParametricExpressionFunction<2, 2>::bind(m); + Dune::XT::Functions::bindings::ParametricExpressionFunction<2, 3>::bind(m); + + Dune::XT::Functions::bindings::ParametricExpressionFunction<3, 1>::bind(m); + Dune::XT::Functions::bindings::ParametricExpressionFunction<3, 2>::bind(m); + Dune::XT::Functions::bindings::ParametricExpressionFunction<3, 3>::bind(m); +} // PYBIND11_MODULE(...) diff --git a/python/dune/xt/functions/spe10.cc b/python/dune/xt/functions/spe10.cc index e451c4881bb7368356a84267ee67a8ab51b27429..f83009d4ac5501ff126d1162b154df26f0406320 100644 --- a/python/dune/xt/functions/spe10.cc +++ b/python/dune/xt/functions/spe10.cc @@ -60,9 +60,9 @@ PYBIND11_MODULE(_functions_spe10, m) py::module::import("dune.xt.common"); py::module::import("dune.xt.la"); py::module::import("dune.xt.grid"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_1d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_2d"); - py::module::import("dune.xt.functions._functions_gridfunction_interface_3d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_1d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_2d"); + py::module::import("dune.xt.functions._functions_interfaces_grid_function_3d"); all_grids(m); } diff --git a/python/dune/xt/functions/spe10.hh b/python/dune/xt/functions/spe10.hh index 000ed9d96d59668516fabb479594edacf44a1ff4..ad5c2d0a3298e2b74529124b0247813e9023915d 100644 --- a/python/dune/xt/functions/spe10.hh +++ b/python/dune/xt/functions/spe10.hh @@ -104,6 +104,8 @@ auto bind_Spe10Model1Function_2D(pybind11::module& m, const std::string& grid_id "min"_a = Spe10::internal::model1_min_value, "max"_a = Spe10::internal::model1_max_value, "name"_a = C::static_id()); + + return c; } // ... bind_Spe10Model1Function(...) template <class G, size_t d, size_t r, size_t rC> diff --git a/python/dune/xt/grid/CMakeLists.txt b/python/dune/xt/grid/CMakeLists.txt index def3baa246d50e5ec5a731e3de3b708eabbbb1ce..f0f914f99f6ff482a3bb5de3b82f00218af01dc4 100644 --- a/python/dune/xt/grid/CMakeLists.txt +++ b/python/dune/xt/grid/CMakeLists.txt @@ -20,7 +20,6 @@ dune_pybindxi_add_module(_grid_boundaryinfo_normalbased EXCLUDE_FROM_ALL boundar dune_pybindxi_add_module(_grid_boundaryinfo_types EXCLUDE_FROM_ALL boundaryinfo/types.cc) dune_pybindxi_add_module(_grid_filters_base EXCLUDE_FROM_ALL filters/base.cc) dune_pybindxi_add_module(_grid_filters_element EXCLUDE_FROM_ALL filters/element.cc) -dune_pybindxi_add_module(_grid_filters_intersection EXCLUDE_FROM_ALL filters/intersection.cc) dune_pybindxi_add_module(_grid_functors_boundary_detector EXCLUDE_FROM_ALL functors/boundary-detector.cc) # dune_pybindxi_add_module(_grid_functors_bounding_box EXCLUDE_FROM_ALL functors/bounding-box.cc) dune_pybindxi_add_module(_grid_functors_interfaces EXCLUDE_FROM_ALL functors/interfaces.cc) diff --git a/python/dune/xt/grid/__init__.py b/python/dune/xt/grid/__init__.py index 4cac944ead617b50f22455ee8cb7e04274ed29bf..fb8c1542fa91c161e4c0e6e0102582ced726f9ba 100644 --- a/python/dune/xt/grid/__init__.py +++ b/python/dune/xt/grid/__init__.py @@ -12,8 +12,10 @@ # ~~~ from numbers import Number +from tempfile import NamedTemporaryFile from dune.xt import guarded_import +from dune.xt.common.vtk.plot import plot for mod_name in ( '_grid_boundaryinfo_alldirichlet', @@ -24,7 +26,6 @@ for mod_name in ( '_grid_boundaryinfo_types', '_grid_filters_base', '_grid_filters_element', - '_grid_filters_intersection', '_grid_functors_boundary_detector', # '_grid_functors_bounding_box', '_grid_functors_interfaces', @@ -44,3 +45,10 @@ def Dim(d): if f'Dimension{d}' not in globals(): raise RuntimeError(f'Dimension {d} not available, extend <python/dune/xt/grid/traits.cc>!') return globals()[f'Dimension{d}']() + + +def visualize_grid(grid): + tmpfile = NamedTemporaryFile(mode='wb', delete=False, suffix='.vtu').name + grid.visualize(tmpfile[:-4]) + return plot( + tmpfile, color_attribute_name='Element index') # see visualize in python/dune/xt/grid/gridprovider.hh diff --git a/python/dune/xt/grid/filters/element.hh b/python/dune/xt/grid/filters/element.hh index c36c574d6eb7f8aecf8fcab689bf9c535c704ac7..a6e565aa87110c0edd82ef86bbcf8d6663380b4d 100644 --- a/python/dune/xt/grid/filters/element.hh +++ b/python/dune/xt/grid/filters/element.hh @@ -46,7 +46,7 @@ public: c.def(py::init([]() { return std::make_unique<type>(); })); c.def("__repr__", [ClassId](type&) { return ClassId + "()"; }); - m.def(ClassId.c_str(), [](const Grid::GridProvider<G>&) { return type(); }); + m.def(ClassId.c_str(), [](const Grid::GridProvider<G>&) { return new type(); }); return c; } // ... bind(...) diff --git a/python/dune/xt/grid/filters/intersection.cc b/python/dune/xt/grid/filters/intersection.cc deleted file mode 100644 index bd1f8cc54d922a6c3a3389afeb5c842da57ef257..0000000000000000000000000000000000000000 --- a/python/dune/xt/grid/filters/intersection.cc +++ /dev/null @@ -1,81 +0,0 @@ -// This file is part of the dune-xt project: -// https://github.com/dune-community/dune-xt -// Copyright 2009-2018 dune-xt developers and contributors. All rights reserved. -// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) -// or GPL-2.0+ (http://opensource.org/licenses/gpl-license) -// with "runtime exception" (http://www.dune-project.org/license.html) -// Authors: -// Felix Schindler (2020) - -#include "config.h" - -#include <dune/xt/grid/grids.hh> - -#include <python/dune/xt/grid/filters/intersection.hh> - - -template <template <class> class Filter, class GridTypes = Dune::XT::Grid::AvailableGridTypes> -struct InitlessIntersectionFilter_for_all_grids -{ - static void bind(pybind11::module& m, const std::string& class_id) - { - Dune::XT::Grid::bindings::InitlessIntersectionFilter<Filter, typename GridTypes::head_type>::bind(m, class_id); - InitlessIntersectionFilter_for_all_grids<Filter, typename GridTypes::tail_type>::bind(m, class_id); - } -}; - -template <template <class> class Filter> -struct InitlessIntersectionFilter_for_all_grids<Filter, boost::tuples::null_type> -{ - static void bind(pybind11::module& /*m*/, const std::string& /*class_id*/) {} -}; - - -template <class GridTypes = Dune::XT::Grid::AvailableGridTypes> -struct CustomBoundaryIntersectionFilter_for_all_grids -{ - static void bind(pybind11::module& m) - { - Dune::XT::Grid::bindings::CustomBoundaryIntersectionsFilter<typename GridTypes::head_type>::bind(m); - CustomBoundaryIntersectionFilter_for_all_grids<typename GridTypes::tail_type>::bind(m); - } -}; - -template <> -struct CustomBoundaryIntersectionFilter_for_all_grids<boost::tuples::null_type> -{ - static void bind(pybind11::module& /*m*/) {} -}; - - -PYBIND11_MODULE(_grid_filters_intersection, m) -{ - namespace py = pybind11; - using namespace Dune::XT::Grid; - - py::module::import("dune.xt.common.timedlogging"); - py::module::import("dune.xt.grid._grid_boundaryinfo_interfaces"); - py::module::import("dune.xt.grid._grid_boundaryinfo_types"); - py::module::import("dune.xt.grid._grid_filters_base"); - py::module::import("dune.xt.grid._grid_gridprovider_provider"); - -#define BIND_(NAME) InitlessIntersectionFilter_for_all_grids<ApplyOn::NAME>::bind(m, std::string("ApplyOn") + #NAME) - - BIND_(AllIntersections); - BIND_(AllIntersectionsOnce); - BIND_(NoIntersections); - BIND_(InnerIntersections); - BIND_(InnerIntersectionsOnce); - // BIND_(PartitionSetInnerIntersectionsOnce); <- requires partition set as template argument - BIND_(BoundaryIntersections); - BIND_(NonPeriodicBoundaryIntersections); - BIND_(PeriodicBoundaryIntersections); - BIND_(PeriodicBoundaryIntersectionsOnce); - // BIND_(GenericFilteredIntersections); <- requires lambda in init - // BIND_(CustomBoundaryAndProcessIntersections); <- requires boundary type and info in init - BIND_(ProcessIntersections); - -#undef BIND_ - - CustomBoundaryIntersectionFilter_for_all_grids<>::bind(m); -} diff --git a/python/dune/xt/grid/filters/intersection.hh b/python/dune/xt/grid/filters/intersection.hh index f9ebba17b89863904f51d143861e099a2f8a682d..ca8071aa46007f58b63d7ca48e990ca05ea6687c 100644 --- a/python/dune/xt/grid/filters/intersection.hh +++ b/python/dune/xt/grid/filters/intersection.hh @@ -47,7 +47,7 @@ public: c.def(py::init([]() { return std::make_unique<type>(); })); c.def("__repr__", [ClassId](type&) { return ClassId + "()"; }); - m.def(ClassId.c_str(), [](const Grid::GridProvider<G>&) { return type(); }); + m.def(ClassId.c_str(), [](const Grid::GridProvider<G>&) { return new type(); }); return c; } // ... bind(...) @@ -79,7 +79,7 @@ public: c.def(py::init([](const BoundaryInfo<I>& boundary_info, const BoundaryType& boundary_type, const std::string& logging_prefix) { - return type(boundary_info, boundary_type.copy(), logging_prefix); + return new type(boundary_info, boundary_type.copy(), logging_prefix); }), "boundary_info"_a, "boundary_type"_a, @@ -92,7 +92,7 @@ public: [](const Grid::GridProvider<G>&, const BoundaryInfo<I>& boundary_info, const BoundaryType& boundary_type, - const std::string& logging_prefix) { return type(boundary_info, boundary_type.copy(), logging_prefix); }, + const std::string& logging_prefix) { return new type(boundary_info, boundary_type.copy(), logging_prefix); }, "grid_provider"_a, "boundary_info"_a, "boundary_type"_a, diff --git a/python/dune/xt/grid/functors/refinement.cc b/python/dune/xt/grid/functors/refinement.cc index f454327becd7bce701cd51bfa18066342750fc7e..fe4d242e30707547be1ed346a7a6f3e1dfd4a52b 100644 --- a/python/dune/xt/grid/functors/refinement.cc +++ b/python/dune/xt/grid/functors/refinement.cc @@ -11,6 +11,8 @@ #include <dune/pybindxi/pybind11.h> #include <dune/xt/grid/functors/refinement.hh> +#include <dune/xt/grid/grids.hh> +#include <dune/xt/grid/type_traits.hh> #include "interfaces.hh" @@ -22,14 +24,14 @@ namespace bindings { template <class G> -class MaximumEntityVolumeRefineFunctorFunctor +class MaximumEntityVolumeRefineFunctor { static_assert(is_grid<G>::value, ""); using GV = typename G::LeafGridView; using I = extract_intersection_t<GV>; public: - using type = Grid::MaximumEntityVolumeRefineFunctorFunctor<GV>; + using type = Grid::MaximumEntityVolumeRefineFunctor<GV>; using base_type = Grid::ElementFunctor<GV>; using bound_type = pybind11::class_<type, base_type>; @@ -42,7 +44,8 @@ public: auto ClassId = Common::to_camel_case(class_id); auto ClassName = Common::to_camel_case(class_id + "_" + grid_id); - bound_type c(m, ClassName.c_str(), std::string(ClassId + "( " + grid_id + " variant)").c_str()); + const std::string doc{ClassId + "( " + grid_id + " variant)"}; + bound_type c(m, ClassName.c_str(), doc.c_str()); c.def(py::init([](GridProvider<G>& grid_provider, const double& volume) { return std::make_unique<type>(grid_provider.grid(), volume, 1.); }), @@ -50,7 +53,8 @@ public: "volume"_a, py::keep_alive<0, 1>()); c.def("__repr__", [ClassId](type&) { return ClassId + "(grid_provider=\?\?\?, volume=\?\?\?)"; }); - c.def_property_readonly("result", [](const type& self) { return self.result(); }); + // there's no result member in the functor?? + // c.def_property_readonly("result", [](const type& self) { return self.result(); }); m.def( ClassId.c_str(), @@ -63,7 +67,7 @@ public: return c; } // ... bind(...) -}; // class MaximumEntityVolumeRefineFunctorFunctor +}; // class MaximumEntityVolumeRefineFunctor } // namespace bindings @@ -73,17 +77,17 @@ public: template <class GridTypes = Dune::XT::Grid::AvailableGridTypes> -struct MaximumEntityVolumeRefineFunctorFunctor_for_all_grids +struct MaximumEntityVolumeRefineFunctor_for_all_grids { static void bind(pybind11::module& m) { - Dune::XT::Grid::bindings::MaximumEntityVolumeRefineFunctorFunctor<typename GridTypes::head_type>::bind(m); - MaximumEntityVolumeRefineFunctorFunctor_for_all_grids<typename GridTypes::tail_type>::bind(m); + Dune::XT::Grid::bindings::MaximumEntityVolumeRefineFunctor<typename GridTypes::head_type>::bind(m); + MaximumEntityVolumeRefineFunctor_for_all_grids<typename GridTypes::tail_type>::bind(m); } }; template <> -struct MaximumEntityVolumeRefineFunctorFunctor_for_all_grids<boost::tuples::null_type> +struct MaximumEntityVolumeRefineFunctor_for_all_grids<boost::tuples::null_type> { static void bind(pybind11::module& /*m*/) {} }; @@ -98,5 +102,5 @@ PYBIND11_MODULE(_grid_functors_refinement, m) py::module::import("dune.xt.grid._grid_gridprovider_provider"); py::module::import("dune.xt.grid._grid_functors_interfaces"); - MaximumEntityVolumeRefineFunctorFunctor_for_all_grids<>::bind(m); + MaximumEntityVolumeRefineFunctor_for_all_grids<>::bind(m); } diff --git a/python/dune/xt/grid/gridprovider.hh b/python/dune/xt/grid/gridprovider.hh index 538f0738166fc74055e2a9b377a92af78a43583c..ed407707c1e3c1ea9a989d9b04d2f6a0e284ef23 100644 --- a/python/dune/xt/grid/gridprovider.hh +++ b/python/dune/xt/grid/gridprovider.hh @@ -12,17 +12,24 @@ #ifndef PYTHON_DUNE_XT_GRID_GRIDPROVIDER_HH #define PYTHON_DUNE_XT_GRID_GRIDPROVIDER_HH +#include <algorithm> + #include <dune/geometry/type.hh> #include <dune/grid/common/mcmgmapper.hh> #include <dune/pybindxi/pybind11.h> #include <dune/pybindxi/stl.h> -#include <dune/xt/common/parallel/mpi_comm_wrapper.hh> #include <dune/xt/common/numeric_cast.hh> +#include <dune/xt/common/parallel/mpi_comm_wrapper.hh> +#include <dune/xt/common/ranges.hh> +#include <dune/xt/la/container/common/vector/dense.hh> #include <dune/xt/grid/entity.hh> +#include <dune/xt/grid/element.hh> #include <dune/xt/grid/exceptions.hh> #include <dune/xt/grid/gridprovider/dgf.hh> #include <dune/xt/grid/gridprovider/provider.hh> +#include <dune/xt/grid/filters/intersection.hh> +#include <dune/xt/grid/mapper.hh> #include <dune/xt/functions/generic/grid-function.hh> #include <python/dune/xt/common/configuration.hh> @@ -42,71 +49,186 @@ public: using type = Grid::GridProvider<G>; using bound_type = pybind11::class_<type>; + using GV = typename type::LeafGridViewType; + static bound_type bind(pybind11::module& m, const std::string& class_id = "grid_provider", const std::string& grid_id = grid_name<G>::value()) { namespace py = pybind11; using namespace pybind11::literals; - const int dim = type::GridType::dimension; + constexpr const int dim = type::GridType::dimension; const std::string class_name = class_id + "_" + grid_id; const auto ClassName = XT::Common::to_camel_case(class_name); bound_type c(m, ClassName.c_str(), (XT::Common::to_camel_case(class_id) + " (" + grid_id + " variant)").c_str()); - c.def_property_readonly("dimension", [dim](type&) { return dim; }); + c.def_property_readonly("dimension", [](type&) { return dim; }); c.def_property_readonly("max_level", &type::max_level); c.def( "size", - [dim](type& self, const int codim) { + [](type& self, const int codim) { DUNE_THROW_IF( codim < 0 || codim > dim, Exceptions::wrong_codimension, "dim = " << dim << "\n codim = " << codim); - auto grid_view = self.leaf_view(); - MultipleCodimMultipleGeomTypeMapper<decltype(grid_view)> mapper( - grid_view, - [codim](GeometryType gt, int dimgrid) { return dimgrid - Common::numeric_cast<int>(gt.dim()) == codim; }); + DUNE_THROW_IF(codim != dim && codim != 0 && !G::LeafGridView::conforming, + XT::Common::Exceptions::requirements_not_met, + "This is not yet implemented for non-conforming grids and codim " << codim << "!"); + const LeafMultipleCodimMultipleGeomTypeMapper<G> mapper(self.grid(), [codim](GeometryType gt, int dimgrid) { + return dimgrid - Common::numeric_cast<int>(gt.dim()) == codim; + }); return mapper.size(); }, "codim"_a); c.def( "centers", - [dim](type& self, const int codim) { - DUNE_THROW_IF(codim != 0, NotImplemented, "Only for codim 0 at the moment!"); + [](type& self, const int codim) { DUNE_THROW_IF( codim < 0 || codim > dim, Exceptions::wrong_codimension, "dim = " << dim << "\n codim = " << codim); + DUNE_THROW_IF(codim != dim && codim != 0 && !G::LeafGridView::conforming, + XT::Common::Exceptions::requirements_not_met, + "This is not yet implemented for non-conforming grids and codim " << codim << "!"); auto grid_view = self.leaf_view(); - MultipleCodimMultipleGeomTypeMapper<decltype(grid_view)> mapper( - grid_view, - [codim](GeometryType gt, int dimgrid) { return dimgrid - Common::numeric_cast<int>(gt.dim()) == codim; }); - XT::LA::CommonDenseMatrix<double> centers(mapper.size(), Common::numeric_cast<size_t>(dim), 0.); + const LeafMultipleCodimMultipleGeomTypeMapper<G> mapper(self.grid(), [codim](GeometryType gt, int dimgrid) { + return dimgrid - Common::numeric_cast<int>(gt.dim()) == codim; + }); + auto centers = + std::make_unique<XT::LA::CommonDenseMatrix<double>>(mapper.size(), Common::numeric_cast<size_t>(dim), 0.); for (auto&& element : elements(grid_view)) { - auto index = mapper.index(element); - auto center = element.geometry().center(); - for (size_t jj = 0; jj < Common::numeric_cast<size_t>(dim); ++jj) - centers.set_entry(index, jj, center[jj]); + for (auto&& ii : Common::value_range(element.subEntities(codim))) { + auto index = sub_entity_index(mapper, element, codim, ii); + auto center = sub_entity_center(element, codim, ii); + for (size_t jj = 0; jj < Common::numeric_cast<size_t>(dim); ++jj) + centers->set_entry(index, jj, center[jj]); + } } return centers; }, "codim"_a = 0, py::call_guard<py::gil_scoped_release>()); c.def( - "visualize", - [](type& self, const std::string& filename, const std::string& layer) { - DUNE_THROW_IF(layer != "leaf", NotImplemented, "Visualization of level views not implemented yet!"); + "inner_intersection_indices", + [](type& self) { + DUNE_THROW_IF(!G::LeafGridView::conforming, + XT::Common::Exceptions::requirements_not_met, + "This is not yet implemented for non-conforming grids!"); + auto grid_view = self.leaf_view(); + const LeafMultipleCodimMultipleGeomTypeMapper<G> mapper(self.grid(), mcmgLayout(Codim<1>())); + std::set<size_t> global_indices; + Grid::ApplyOn::InnerIntersections<GV> filter; + for (auto&& element : elements(grid_view)) { + for (auto&& intersection : intersections(grid_view, element)) { + if (filter.contains(grid_view, intersection)) { + const auto intersection_entity = element.template subEntity<1>(intersection.indexInInside()); + global_indices.insert(Common::numeric_cast<size_t>(mapper.index(intersection_entity))); + } + } + } + LA::CommonDenseVector<size_t> ret(global_indices.size()); + size_t ii = 0; + for (const auto& index : global_indices) { + ret[ii] = index; + ++ii; + } + return ret; + }, + py::call_guard<py::gil_scoped_release>()); + c.def( + "inside_element_indices", + [](type& self) { + DUNE_THROW_IF(!G::LeafGridView::conforming, + XT::Common::Exceptions::requirements_not_met, + "This is not yet implemented for non-conforming grids!"); + auto grid_view = self.leaf_view(); + const LeafMultipleCodimMultipleGeomTypeMapper<G> element_mapper(self.grid(), mcmgElementLayout()); + const LeafMultipleCodimMultipleGeomTypeMapper<G> intersection_mapper(self.grid(), mcmgLayout(Codim<1>())); + LA::CommonDenseVector<size_t> element_indices(intersection_mapper.size(), std::numeric_limits<size_t>::max()); + Grid::ApplyOn::AllIntersectionsOnce<GV> filter; + for (auto&& element : elements(grid_view)) { + const auto element_index = Common::numeric_cast<size_t>(element_mapper.index(element)); + for (auto&& intersection : intersections(grid_view, element)) { + if (filter.contains(grid_view, intersection)) { + const auto intersection_entity = element.template subEntity<1>(intersection.indexInInside()); + const auto intersection_index = + Common::numeric_cast<size_t>(intersection_mapper.index(intersection_entity)); + element_indices[intersection_index] = element_index; + } + } + } + return element_indices; + }, + py::call_guard<py::gil_scoped_release>()); + c.def( + "outside_element_indices", + [](type& self) { + DUNE_THROW_IF(!G::LeafGridView::conforming, + XT::Common::Exceptions::requirements_not_met, + "This is not yet implemented for non-conforming grids!"); + auto grid_view = self.leaf_view(); + const LeafMultipleCodimMultipleGeomTypeMapper<G> element_mapper(self.grid(), mcmgElementLayout()); + const LeafMultipleCodimMultipleGeomTypeMapper<G> intersection_mapper(self.grid(), mcmgLayout(Codim<1>())); + LA::CommonDenseVector<size_t> element_indices(intersection_mapper.size(), std::numeric_limits<size_t>::max()); + Grid::ApplyOn::InnerIntersectionsOnce<GV> filter; + for (auto&& element : elements(grid_view)) { + for (auto&& intersection : intersections(grid_view, element)) { + if (filter.contains(grid_view, intersection)) { + const auto intersection_entity = element.template subEntity<1>(intersection.indexInInside()); + const auto intersection_index = + Common::numeric_cast<size_t>(intersection_mapper.index(intersection_entity)); + const auto outside_element_index = + Common::numeric_cast<size_t>(element_mapper.index(intersection.outside())); + element_indices[intersection_index] = outside_element_index; + } + } + } + return element_indices; + }, + py::call_guard<py::gil_scoped_release>()); + c.def( + "boundary_intersection_indices", + [](type& self, const Grid::IntersectionFilter<GV>& filter) { + DUNE_THROW_IF(!G::LeafGridView::conforming, + XT::Common::Exceptions::requirements_not_met, + "This is not yet implemented for non-conforming grids!"); auto grid_view = self.leaf_view(); - using GV = decltype(grid_view); - const MultipleCodimMultipleGeomTypeMapper<GV> mapper( - grid_view, [](GeometryType gt, int dimgrid) { return dimgrid == Common::numeric_cast<int>(gt.dim()); }); - double element_index = 0; - Functions::GenericGridFunction<extract_entity_t<GV>> element_index_function( + const LeafMultipleCodimMultipleGeomTypeMapper<G> mapper(self.grid(), mcmgLayout(Codim<1>())); + std::set<size_t> global_indices; + for (auto&& element : elements(grid_view)) { + for (auto&& intersection : intersections(grid_view, element)) { + if (filter.contains(grid_view, intersection)) { + const auto intersection_entity = element.template subEntity<1>(intersection.indexInInside()); + global_indices.insert(Common::numeric_cast<size_t>(mapper.index(intersection_entity))); + } + } + } + LA::CommonDenseVector<size_t> ret(global_indices.size()); + size_t ii = 0; + for (const auto& index : global_indices) { + ret[ii] = index; + ++ii; + } + return ret; + }, + "intersection_filter"_a = Grid::ApplyOn::BoundaryIntersections<GV>(), + py::call_guard<py::gil_scoped_release>()); + c.def( + "visualize", + [](type& self, const std::string& filename) { + const LeafMultipleCodimMultipleGeomTypeMapper<G> mapper(self.grid(), [](GeometryType gt, int dimgrid) { + return dimgrid - Common::numeric_cast<int>(gt.dim()) == 0; + }); + double element_index = 0; // not thread safe! + Functions::GenericGridFunction<extract_entity_t<typename G::LeafGridView>> element_index_function( /*order=*/[](const auto&) { return 0; }, - /*post_bind=*/[&mapper, &element_index](const auto& element) { element_index = mapper.index(element); }, - /*evaluate=*/[&element_index](const auto&, const auto&) { return element_index; }, + /*post_bind=*/ + [&mapper, &element_index](const auto& element) { element_index = mapper.index(element); }, + /*evaluate=*/ + [&element_index](const auto&, const auto&) { return element_index; }, /*param_type=*/{}, /*name=*/"Element index"); - element_index_function.visualize(grid_view, filename, /*subsampling=*/false); + element_index_function.visualize(self.leaf_view(), + filename, + /*subsampling=*/false); }, "filename"_a, - "layer"_a = "leaf", py::call_guard<py::gil_scoped_release>()); c.def( "global_refine", diff --git a/python/dune/xt/grid/gridprovider/provider.cc b/python/dune/xt/grid/gridprovider/provider.cc index 3d7ea98c308d8eb2ebcdde0c799f533b60400987..13786789760e1e5cc39e5cba871e5566a15095f9 100644 --- a/python/dune/xt/grid/gridprovider/provider.cc +++ b/python/dune/xt/grid/gridprovider/provider.cc @@ -14,6 +14,41 @@ #include <dune/xt/grid/grids.hh> #include <python/dune/xt/grid/gridprovider.hh> +#include <python/dune/xt/grid/filters/intersection.hh> + + +template <template <class> class Filter, class GridTypes = Dune::XT::Grid::AvailableGridTypes> +struct InitlessIntersectionFilter_for_all_grids +{ + static void bind(pybind11::module& m, const std::string& class_id) + { + Dune::XT::Grid::bindings::InitlessIntersectionFilter<Filter, typename GridTypes::head_type>::bind(m, class_id); + InitlessIntersectionFilter_for_all_grids<Filter, typename GridTypes::tail_type>::bind(m, class_id); + } +}; + +template <template <class> class Filter> +struct InitlessIntersectionFilter_for_all_grids<Filter, boost::tuples::null_type> +{ + static void bind(pybind11::module& /*m*/, const std::string& /*class_id*/) {} +}; + + +template <class GridTypes = Dune::XT::Grid::AvailableGridTypes> +struct CustomBoundaryIntersectionFilter_for_all_grids +{ + static void bind(pybind11::module& m) + { + Dune::XT::Grid::bindings::CustomBoundaryIntersectionsFilter<typename GridTypes::head_type>::bind(m); + CustomBoundaryIntersectionFilter_for_all_grids<typename GridTypes::tail_type>::bind(m); + } +}; + +template <> +struct CustomBoundaryIntersectionFilter_for_all_grids<boost::tuples::null_type> +{ + static void bind(pybind11::module& /*m*/) {} +}; template <class GridTypes = Dune::XT::Grid::AvailableGridTypes> @@ -36,8 +71,33 @@ struct GridProvider_for_all_grids<boost::tuples::null_type> PYBIND11_MODULE(_grid_gridprovider_provider, m) { namespace py = pybind11; + using namespace Dune::XT::Grid; py::module::import("dune.xt.common"); + py::module::import("dune.xt.la"); + py::module::import("dune.xt.grid._grid_boundaryinfo_interfaces"); + py::module::import("dune.xt.grid._grid_boundaryinfo_types"); + py::module::import("dune.xt.grid._grid_filters_base"); + +#define BIND_(NAME) InitlessIntersectionFilter_for_all_grids<ApplyOn::NAME>::bind(m, std::string("ApplyOn") + #NAME) + + BIND_(AllIntersections); + BIND_(AllIntersectionsOnce); + BIND_(NoIntersections); + BIND_(InnerIntersections); + BIND_(InnerIntersectionsOnce); + // BIND_(PartitionSetInnerIntersectionsOnce); <- requires partition set as template argument + BIND_(BoundaryIntersections); + BIND_(NonPeriodicBoundaryIntersections); + BIND_(PeriodicBoundaryIntersections); + BIND_(PeriodicBoundaryIntersectionsOnce); + // BIND_(GenericFilteredIntersections); <- requires lambda in init + // BIND_(CustomBoundaryAndProcessIntersections); <- requires boundary type and info in init + BIND_(ProcessIntersections); + +#undef BIND_ + + CustomBoundaryIntersectionFilter_for_all_grids<>::bind(m); GridProvider_for_all_grids<>::bind(m); } diff --git a/python/dune/xt/grid/intersection.cc b/python/dune/xt/grid/intersection.cc index c0c8af779a378da8e63febc35984930defd0abfa..5c6d3a88b89a958aabb00f6f5ba3efab38037977 100644 --- a/python/dune/xt/grid/intersection.cc +++ b/python/dune/xt/grid/intersection.cc @@ -18,7 +18,7 @@ #include <dune/xt/grid/type_traits.hh> #include <dune/xt/grid/grids.hh> #include <dune/xt/grid/intersection.hh> -#include <dune/xt/common/print.hh> +#include <dune/xt/grid/print.hh> #include <python/dune/xt/common/fvector.hh> #include <python/dune/xt/grid/grids.bindings.hh> @@ -72,12 +72,12 @@ public: // special methods/operators c.def("__str__", [](type& self) { std::stringstream ss; - ss << Common::print(self); + ss << print(self); return ss.str(); }); c.def("__repr__", [](type& self) { std::stringstream ss; - ss << Common::repr(self); + ss << repr(self); return ss.str(); }); c.def( diff --git a/python/dune/xt/grid/walker.hh b/python/dune/xt/grid/walker.hh index 4edb6091c56ff5d11d677d63bb45342f238ce8b8..69c2150c61e84639234947f4788c9503491f54e6 100644 --- a/python/dune/xt/grid/walker.hh +++ b/python/dune/xt/grid/walker.hh @@ -78,14 +78,15 @@ public: auto ClassName = Common::to_camel_case(class_id + "_" + grid_id); bound_type c(m, ClassName.c_str(), ClassName.c_str()); - c.def(py::init([](GridProvider<G>& grid_provider) { return type(grid_provider.leaf_view()); }), "grid_provider"_a); + c.def(py::init([](GridProvider<G>& grid_provider) { return new type(grid_provider.leaf_view()); }), + "grid_provider"_a); addbind_methods(c); // factories m.def( Common::to_camel_case(class_id).c_str(), - [](GridProvider<G>& grid_provider) { return type(grid_provider.leaf_view()); }, + [](GridProvider<G>& grid_provider) { return new type(grid_provider.leaf_view()); }, "grid_provider"_a); return c; diff --git a/python/dune/xt/grid/walker/apply-on.bindings.hh b/python/dune/xt/grid/walker/apply-on.bindings.hh index c030f11c5f1c796c218245c45ce087e58111e245..c067b7a5d146ffd8253e6160ac1d71114cd0c70c 100644 --- a/python/dune/xt/grid/walker/apply-on.bindings.hh +++ b/python/dune/xt/grid/walker/apply-on.bindings.hh @@ -59,13 +59,13 @@ private: m.def( makename(class_name, layer_name).c_str(), [](const BoundaryInfoType& boundary_info, XT::Grid::BoundaryType*&& boundary_type) { - return type(boundary_info, std::move(boundary_type)); + return new type(boundary_info, std::move(boundary_type)); }, "boundary_info"_a, "boundary_type"_a); } else { c.def(pybind11::init<>()); - m.def(makename(class_name, layer_name).c_str(), []() { return type(); }); + m.def(makename(class_name, layer_name).c_str(), []() { return new type(); }); } } diff --git a/python/dune/xt/la/container/matrix-interface.hh b/python/dune/xt/la/container/matrix-interface.hh index 210a1630ae2e1be6ab65d63156b04fbbb57c25a1..eb167b05e12b63afa2aefd9fd6301a786d39316d 100644 --- a/python/dune/xt/la/container/matrix-interface.hh +++ b/python/dune/xt/la/container/matrix-interface.hh @@ -208,6 +208,55 @@ auto bind_Matrix(pybind11::module& m) "min_cols"_a = -1, "mode"_a = "ascii"); + c.def( + "__add__", [](const C& self, const C& other) { return std::make_unique<C>(self + other); }, py::is_operator()); + c.def("__iadd__", // function ptr signature required for the right return type + (C & (C::*)(const C&)) & C::operator+=, + py::is_operator()); + c.def( + "__sub__", [](const C& self, const C& other) { return std::make_unique<C>(self - other); }, py::is_operator()); + c.def("__isub__", // function ptr signature required for the right return type + (C & (C::*)(const C&)) & C::operator-=, + py::is_operator()); + c.def( + "__mul__", + [](const C& self, const S& alpha) { + auto ret = std::make_unique<C>(self.copy()); + (*ret) *= alpha; + return ret; + }, + py::is_operator()); + c.def( + "__rmul__", + [](const C& self, const S& alpha) { + auto ret = std::make_unique<C>(self.copy()); + (*ret) *= alpha; + return ret; + }, + py::is_operator()); + c.def("__imul__", // function ptr signature required for the right return type + (C & (C::*)(const C&)) & C::operator*=, + py::is_operator()); + c.def( + "__truediv__", + [](const C& self, const S& alpha) { + auto ret = std::make_unique<C>(self.copy()); + (*ret) /= alpha; + return ret; + }, + py::is_operator()); + c.def("__itruediv__", // function ptr signature required for the right return type + (C & (C::*)(const C&)) & C::operator/=, + py::is_operator()); + c.def( + "neg", + [](const C& self) { + auto ret = std::make_unique<C>(self.copy()); + (*ret) *= -1; + return ret; + }, + py::is_operator()); + addbind_ContainerInterface(c); return c; @@ -221,11 +270,25 @@ void addbind_Matrix_Vector_interaction(pybind11::class_<M>& mat, pybind11::class mat.def( "mv", [](const M& self, const V& xx, V& yy) { self.mv(xx, yy); }, "source", "range"); + mat.def( + "dot", + [](const M& self, const V& xx) { + V yy(self.rows()); + self.mv(xx, yy); + return yy; + }, + "source"); + mat.def( + "__matmul__", + [](const M& self, const V& xx) { + V yy(self.rows()); + self.mv(xx, yy); + return yy; + }, + "source"); mat.def( "mtv", [](const M& self, const V& xx, V& yy) { self.mtv(xx, yy); }, "source", "range"); - mat.def(py::self * V()); - mat.def("vector_type", [vec](M& /*self*/) { return vec; }); vec.def("matrix_type", [mat](V& /*self*/) { return mat; }); } // ... addbind_Matrix_Vector_interaction(...) diff --git a/python/dune/xt/la/container/vector-interface.hh b/python/dune/xt/la/container/vector-interface.hh index 8eadd4d9f8bcaa92950f72367279f33d62ed2813..8a7d7141f0085ac43d6cf90538bfc9b5813032df 100644 --- a/python/dune/xt/la/container/vector-interface.hh +++ b/python/dune/xt/la/container/vector-interface.hh @@ -112,14 +112,54 @@ auto bind_Vector(pybind11::module& m) }, pybind11::keep_alive<0, 1>() /*Essential: keep object alive while iterator exists!*/); - c.def(py::self == py::self); - c.def(py::self != py::self); - c.def(py::self + py::self); - c.def(py::self += py::self); - c.def(py::self -= py::self); - c.def(py::self * py::self); - c.def(py::self *= R()); - c.def(py::self /= R()); + c.def( + "__add__", [](const C& self, const C& other) { return std::make_unique<C>(self + other); }, py::is_operator()); + c.def("__iadd__", // function ptr signature required for the right return type + (C & (C::*)(const C&)) & C::operator+=, + py::is_operator()); + c.def( + "__sub__", [](const C& self, const C& other) { return std::make_unique<C>(self - other); }, py::is_operator()); + c.def("__isub__", // function ptr signature required for the right return type + (C & (C::*)(const C&)) & C::operator-=, + py::is_operator()); + c.def( + "__mul__", + [](const C& self, const R& alpha) { + auto ret = std::make_unique<C>(self.copy()); + (*ret) *= alpha; + return ret; + }, + py::is_operator()); + c.def( + "__rmul__", + [](const C& self, const R& alpha) { + auto ret = std::make_unique<C>(self.copy()); + (*ret) *= alpha; + return ret; + }, + py::is_operator()); + c.def("__imul__", // function ptr signature required for the right return type + (C & (C::*)(const C&)) & C::operator*=, + py::is_operator()); + c.def( + "__truediv__", + [](const C& self, const R& alpha) { + auto ret = std::make_unique<C>(self.copy()); + (*ret) /= alpha; + return ret; + }, + py::is_operator()); + c.def("__itruediv__", // function ptr signature required for the right return type + (C & (C::*)(const C&)) & C::operator/=, + py::is_operator()); + c.def( + "neg", + [](const C& self) { + auto ret = std::make_unique<C>(self.copy()); + (*ret) *= -1; + return ret; + }, + py::is_operator()); c.def_property_readonly("size", [](const C& self) { return self.size(); }); c.def( diff --git a/python/setup.py.in b/python/setup.py.in index dcfd0b0e3b28063d928592965be86295f10e2c14..36c831b851ea87f5e199bd61e7186a5bd065062f 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -17,7 +17,7 @@ from setuptools import setup, find_packages requires=['binpacking==1.3', 'cython', 'jinja2', 'docopt', 'pylicense3>=0.4.1', 'ipython', 'pytest', 'pytest-cov', 'cmake_format==0.4.1', - 'codecov', 'yapf==0.25', 'loguru', 'numpy', 'scipy', + 'codecov', 'yapf==0.25', 'loguru', 'numpy', 'scipy', 'matplotlib', 'k3d==2.6.6', 'vtk', 'ipywidgets', 'lxml', 'xmljson'] extras_require = [] if '${HAVE_MPI}' == 'TRUE':