diff --git a/dune/gdt/local/integrands/combined.hh b/dune/gdt/local/integrands/combined.hh new file mode 100644 index 0000000000000000000000000000000000000000..2da49d4f9891d981f40f838340a49392b5825399 --- /dev/null +++ b/dune/gdt/local/integrands/combined.hh @@ -0,0 +1,355 @@ +// This file is part of the dune-gdt project: +// https://github.com/dune-community/dune-gdt +// Copyright 2010-2018 dune-gdt 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) + +#ifndef DUNE_GDT_LOCAL_INTEGRANDS_COMBINED_HH +#define DUNE_GDT_LOCAL_INTEGRANDS_COMBINED_HH + +#include <dune/xt/common/memory.hh> + +#include "interfaces.hh" + +namespace Dune { +namespace GDT { + + +/// \todo add LocalUnaryElementIntegrandSum +/// \todo add operator+ to LocalUnaryElementIntegrandInterface +/// \sa LocalQuaternaryIntersectionIntegrandSum +// template <class E, size_t r, size_t rC, class R, class F> +// class LocalUnaryElementIntegrandSum +// : public XT::Common::ParametricInterface +// , public XT::Grid::ElementBoundObject<Element> +//{ +// static_assert(XT::Grid::is_entity<Element>::value, ""); + +// using ThisType = LocalUnaryElementIntegrandInterface<Element, range_dim, range_dim_cols, RangeField, Field>; + +// public: +// using E = Element; +// using D = typename Element::Geometry::ctype; +// static const constexpr size_t d = E::dimension; +// using F = Field; + +// using R = RangeField; +// static const constexpr size_t r = range_dim; +// static const constexpr size_t rC = range_dim_cols; + +// using typename XT::Grid::ElementBoundObject<Element>::ElementType; +// using DomainType = FieldVector<D, d>; +// using LocalBasisType = XT::Functions::ElementFunctionSetInterface<E, r, rC, R>; + +// LocalUnaryElementIntegrandInterface(const XT::Common::ParameterType& param_type = {}) +// : XT::Common::ParametricInterface(param_type) +// {} + +// virtual ~LocalUnaryElementIntegrandInterface() = default; + +// virtual std::unique_ptr<ThisType> copy() const = 0; + +// /** +// * Returns the polynomial order of the integrand, given the basis. +// * +// * \note Will throw Exceptions::not_bound_to_an_element_yet error if not bound yet! +// **/ +// virtual int order(const LocalBasisType& basis, const XT::Common::Parameter& param = {}) const = 0; + +// /** +// * Computes the evaluation of this integrand at the given point for each function in the basis. +// * +// * \note Will throw Exceptions::not_bound_to_an_element_yet error if not bound yet! +// **/ +// virtual void evaluate(const LocalBasisType& basis, +// const DomainType& point_in_reference_element, +// DynamicVector<F>& result, +// const XT::Common::Parameter& param = {}) const = 0; + +// /** +// * This method is provided for convenience and should not be used within library code. +// * +// * \note Will throw Exceptions::not_bound_to_an_element_yet error if not bound yet! +// **/ +// virtual DynamicVector<F> evaluate(const LocalBasisType& basis, +// const DomainType& point_in_reference_element, +// const XT::Common::Parameter& param = {}) const +// { +// DynamicVector<F> result(basis.size(param)); +// evaluate(basis, point_in_reference_element, result, param); +// return result; +// } +//}; // class LocalUnaryElementIntegrandSum + + +/// \todo add LocalBinaryElementIntegrandSum +/// \todo add operator+ to LocalBinaryElementIntegrandInterface +/// \sa LocalQuaternaryIntersectionIntegrandSum +// template <class E, size_t t_r, size_t t_RC, class TF, class F, size_t a_r, size_t a_rC, class AF> +// class LocalBinaryElementIntegrandSum +// : public XT::Common::ParametricInterface +// , public XT::Grid::ElementBoundObject<Element> +//{ +// static_assert(XT::Grid::is_entity<Element>::value, ""); + +// using ThisType = LocalBinaryElementIntegrandInterface<Element, +// test_range_dim, +// test_range_dim_cols, +// TestRangeField, +// Field, +// ansatz_range_dim, +// ansatz_range_dim_cols, +// AnsatzRangeField>; + +// public: +// using E = Element; +// using D = typename Element::Geometry::ctype; +// static const constexpr size_t d = E::dimension; +// using F = Field; + +// using TR = TestRangeField; +// static const constexpr size_t t_r = test_range_dim; +// static const constexpr size_t t_rC = test_range_dim_cols; + +// using AR = AnsatzRangeField; +// static const constexpr size_t a_r = ansatz_range_dim; +// static const constexpr size_t a_rC = ansatz_range_dim_cols; + +// using typename XT::Grid::ElementBoundObject<Element>::ElementType; +// using DomainType = FieldVector<D, d>; +// using LocalTestBasisType = XT::Functions::ElementFunctionSetInterface<E, t_r, t_rC, TR>; +// using LocalAnsatzBasisType = XT::Functions::ElementFunctionSetInterface<E, a_r, a_rC, AR>; + +// LocalBinaryElementIntegrandInterface(const XT::Common::ParameterType& param_type = {}) +// : XT::Common::ParametricInterface(param_type) +// {} + +// virtual ~LocalBinaryElementIntegrandInterface() = default; + +// virtual std::unique_ptr<ThisType> copy() const = 0; + +// /** +// * Returns the polynomial order of the integrand, given the bases. +// * +// * \note Will throw Exceptions::not_bound_to_an_element_yet error if not bound yet! +// **/ +// virtual int order(const LocalTestBasisType& test_basis, +// const LocalAnsatzBasisType& ansatz_basis, +// const XT::Common::Parameter& param = {}) const = 0; + +// /** +// * Computes the evaluation of this integrand at the given point for each combination of functions from the two +// bases. +// * +// * \note Will throw Exceptions::not_bound_to_an_element_yet error if not bound yet! +// **/ +// virtual void evaluate(const LocalTestBasisType& test_basis, +// const LocalAnsatzBasisType& ansatz_basis, +// const DomainType& point_in_reference_element, +// DynamicMatrix<F>& result, +// const XT::Common::Parameter& param = {}) const = 0; + +// /** +// * This method is provided for convenience and should not be used within library code. +// * +// * \note Will throw Exceptions::not_bound_to_an_element_yet error if not bound yet! +// **/ +// virtual DynamicMatrix<F> evaluate(const LocalTestBasisType& test_basis, +// const LocalAnsatzBasisType& ansatz_basis, +// const DomainType& point_in_reference_element, +// const XT::Common::Parameter& param = {}) const +// { +// DynamicMatrix<F> result(test_basis.size(param), ansatz_basis.size(param), 0); +// evaluate(test_basis, ansatz_basis, point_in_reference_element, result, param); +// return result; +// } +//}; // class LocalBinaryElementIntegrandInterface + + +/// \todo add LocalBinaryIntersectionIntegrandSum +/// \todo add operator+ to LocalBinaryIntersectionIntegrandInterface +/// \sa LocalQuaternaryIntersectionIntegrandSum +// template <class I, size_t r, size_t rC, class R, class F> +// class LocalBinaryIntersectionIntegrandSum +// : public XT::Common::ParametricInterface +// , public XT::Grid::IntersectionBoundObject<Intersection> +//{ +// static_assert(XT::Grid::is_intersection<Intersection>::value, ""); + +// using ThisType = +// LocalBinaryIntersectionIntegrandInterface<Intersection, range_dim, range_dim_cols, RangeField, Field>; + +// public: +// using typename XT::Grid::IntersectionBoundObject<Intersection>::IntersectionType; +// using ElementType = XT::Grid::extract_inside_element_t<Intersection>; + +// using I = Intersection; +// using E = ElementType; +// using D = typename ElementType::Geometry::ctype; +// static const constexpr size_t d = E::dimension; +// using F = Field; + +// using RF = RangeField; +// static const constexpr size_t r = range_dim; +// static const constexpr size_t rC = range_dim_cols; + +// using DomainType = FieldVector<D, d - 1>; +// using LocalBasisType = XT::Functions::ElementFunctionSetInterface<E, r, rC, RF>; + +// LocalBinaryIntersectionIntegrandInterface(const XT::Common::ParameterType& param_type = {}) +// : XT::Common::ParametricInterface(param_type) +// {} + +// virtual ~LocalBinaryIntersectionIntegrandInterface() = default; + +// virtual std::unique_ptr<ThisType> copy() const = 0; + +// /** +// * Returns the polynomial order of the integrand, given the bases. +// * +// * \note Will throw Exceptions::not_bound_to_an_element_yet error if not bound yet! +// **/ +// virtual int order(const LocalBasisType& inside_basis, +// const LocalBasisType& outside_basis, +// const XT::Common::Parameter& param = {}) const = 0; + +// /** +// * Computes the evaluation of this integrand at the given point for each combination of functions from the two +// bases. +// * +// * \note Will throw Exceptions::not_bound_to_an_element_yet error if not bound yet! +// **/ +// virtual void evaluate(const LocalBasisType& inside_basis, +// const LocalBasisType& outside_basis, +// const DomainType& point_in_reference_element, +// DynamicMatrix<F>& result, +// const XT::Common::Parameter& param = {}) const = 0; + +// /** +// * This method is provided for convenience and should not be used within library code. +// * +// * \note Will throw Exceptions::not_bound_to_an_element_yet error if not bound yet! +// **/ +// virtual DynamicMatrix<F> evaluate(const LocalBasisType& inside_basis, +// const LocalBasisType& outside_basis, +// const DomainType& point_in_reference_element, +// const XT::Common::Parameter& param = {}) const +// { +// DynamicMatrix<F> result(inside_basis.size(param), outside_basis.size(param), 0); +// evaluate(inside_basis, inside_basis, point_in_reference_element, result, param); +// return result; +// } +//}; // class LocalBinaryIntersectionIntegrandSum + + +template <class I, size_t t_r, size_t t_rC, class TF, class F, size_t a_r, size_t a_rC, class AF> +class LocalQuaternaryIntersectionIntegrandSum + : public LocalQuaternaryIntersectionIntegrandInterface<I, t_r, t_rC, TF, F, a_r, a_rC, AF> +{ + using BaseType = LocalQuaternaryIntersectionIntegrandInterface<I, t_r, t_rC, TF, F, a_r, a_rC, AF>; + using ThisType = LocalQuaternaryIntersectionIntegrandSum<I, t_r, t_rC, TF, F, a_r, a_rC, AF>; + +public: + using typename BaseType::DomainType; + using typename BaseType::LocalAnsatzBasisType; + using typename BaseType::LocalTestBasisType; + + LocalQuaternaryIntersectionIntegrandSum(const BaseType& left, const BaseType& right) + : left_(left.copy().release()) + , right_(right.copy().release()) + {} + + LocalQuaternaryIntersectionIntegrandSum(const ThisType& other) + : left_(other.left_) + , right_(other.right_) + {} + + LocalQuaternaryIntersectionIntegrandSum(ThisType&& source) = default; + + std::unique_ptr<BaseType> copy() const override final + { + return std::make_unique<ThisType>(*this); + } + + int order(const LocalTestBasisType& test_basis_inside, + const LocalAnsatzBasisType& ansatz_basis_inside, + const LocalTestBasisType& test_basis_outside, + const LocalAnsatzBasisType& ansatz_basis_outside, + const XT::Common::Parameter& param = {}) const override final + { + return std::max( + left_.access().order(test_basis_inside, ansatz_basis_inside, test_basis_outside, ansatz_basis_outside, param), + right_.access().order(test_basis_inside, ansatz_basis_inside, test_basis_outside, ansatz_basis_outside, param)); + } + + using BaseType::evaluate; + + void evaluate(const LocalTestBasisType& test_basis_inside, + const LocalAnsatzBasisType& ansatz_basis_inside, + const LocalTestBasisType& test_basis_outside, + const LocalAnsatzBasisType& ansatz_basis_outside, + const DomainType& point_in_reference_intersection, + DynamicMatrix<F>& result_in_in, + DynamicMatrix<F>& result_in_out, + DynamicMatrix<F>& result_out_in, + DynamicMatrix<F>& result_out_out, + const XT::Common::Parameter& param = {}) const override final + { + // Each integrand clears its storage, so we let the left one write into ... + left_.access().evaluate(test_basis_inside, + ansatz_basis_inside, + test_basis_outside, + ansatz_basis_outside, + point_in_reference_intersection, + result_in_in, + result_in_out, + result_out_in, + result_out_out, + param); + // ..., the right one into ... + right_.access().evaluate(test_basis_inside, + ansatz_basis_inside, + test_basis_outside, + ansatz_basis_outside, + point_in_reference_intersection, + result_in_in_, + result_in_out_, + result_out_in_, + result_out_out_, + param); + // ... and simply add them up (cannot use += here, matrices might be larger). + const size_t rows_in = test_basis_inside.size(param); + const size_t rows_out = test_basis_outside.size(param); + const size_t cols_in = ansatz_basis_inside.size(param); + const size_t cols_out = ansatz_basis_outside.size(param); + for (size_t ii = 0; ii < rows_in; ++ii) + for (size_t jj = 0; jj < cols_in; ++jj) + result_in_in[ii][jj] += result_in_in_[ii][jj]; + for (size_t ii = 0; ii < rows_in; ++ii) + for (size_t jj = 0; jj < cols_out; ++jj) + result_in_out[ii][jj] += result_in_out_[ii][jj]; + for (size_t ii = 0; ii < rows_out; ++ii) + for (size_t jj = 0; jj < cols_in; ++jj) + result_out_in[ii][jj] += result_out_in_[ii][jj]; + for (size_t ii = 0; ii < rows_out; ++ii) + for (size_t jj = 0; jj < cols_out; ++jj) + result_out_out[ii][jj] += result_out_out_[ii][jj]; + } // ... evaluate(...) + +private: + XT::Common::ConstStorageProvider<BaseType> left_; + XT::Common::ConstStorageProvider<BaseType> right_; + mutable DynamicMatrix<F> result_in_in_; + mutable DynamicMatrix<F> result_in_out_; + mutable DynamicMatrix<F> result_out_in_; + mutable DynamicMatrix<F> result_out_out_; +}; // class LocalQuaternaryIntersectionIntegrandSum + + +} // namespace GDT +} // namespace Dune + +#endif // DUNE_GDT_LOCAL_INTEGRANDS_COMBINED_HH diff --git a/dune/gdt/local/integrands/interfaces.hh b/dune/gdt/local/integrands/interfaces.hh index cb6b15f872390708db877ec0a1b72514fd57ca11..96798d086941ed4f1156bb1c9a870df823618cf3 100644 --- a/dune/gdt/local/integrands/interfaces.hh +++ b/dune/gdt/local/integrands/interfaces.hh @@ -26,6 +26,20 @@ namespace Dune { namespace GDT { +// forwards (required for operator+, include are below) +template <class E, size_t r, size_t rC, class R, class F> +class LocalUnaryElementIntegrandSum; + +template <class E, size_t t_r, size_t t_RC, class TF, class F, size_t a_r, size_t a_rC, class AF> +class LocalBinaryElementIntegrandSum; + +template <class I, size_t r, size_t rC, class R, class F> +class LocalBinaryIntersectionIntegrandSum; + +template <class I, size_t t_r, size_t t_rC, class TF, class F, size_t a_r, size_t a_rC, class AF> +class LocalQuaternaryIntersectionIntegrandSum; + + /** * Interface for integrands in integrals over grid elements, which depend on one argument only (usually the test basis * in an integral-based functional). @@ -334,6 +348,11 @@ public: virtual std::unique_ptr<ThisType> copy() const = 0; + LocalQuaternaryIntersectionIntegrandSum<I, t_r, t_rC, TR, F, a_r, a_rC, AR> operator+(const ThisType& other) const + { + return LocalQuaternaryIntersectionIntegrandSum<I, t_r, t_rC, TR, F, a_r, a_rC, AR>(*this, other); + } + /** * Returns the polynomial order of the integrand, given the bases. * @@ -390,12 +409,37 @@ public: return {result_in_in, result_in_out, result_out_in, result_out_out}; } // ... apply(...) -private: - std::unique_ptr<IntersectionType> intersection_; +protected: + void ensure_size_and_clear_results(const LocalTestBasisType& test_basis_inside, + const LocalAnsatzBasisType& ansatz_basis_inside, + const LocalTestBasisType& test_basis_outside, + const LocalAnsatzBasisType& ansatz_basis_outside, + DynamicMatrix<F>& result_in_in, + DynamicMatrix<F>& result_in_out, + DynamicMatrix<F>& result_out_in, + DynamicMatrix<F>& result_out_out, + const XT::Common::Parameter& param) const + { + const size_t rows_in = test_basis_inside.size(param); + const size_t rows_out = test_basis_outside.size(param); + const size_t cols_in = ansatz_basis_inside.size(param); + const size_t cols_out = ansatz_basis_outside.size(param); + const auto ensure_size_and_clear = [](auto& m, const auto& r, const auto& c) { + if (m.rows() < r || m.cols() < c) + m.resize(r, c); + m *= 0; + }; + ensure_size_and_clear(result_in_in, rows_in, cols_in); + ensure_size_and_clear(result_in_out, rows_in, cols_out); + ensure_size_and_clear(result_out_in, rows_out, cols_in); + ensure_size_and_clear(result_out_out, rows_out, cols_out); + } // ... ensure_size_and_clear_results(...) }; // class LocalQuaternaryIntersectionIntegrandInterface } // namespace GDT } // namespace Dune +#include "combined.hh" + #endif // DUNE_GDT_LOCAL_INTEGRANDS_INTERFACES_HH