From 255b3b2a312aa5fc5b99cc4a8ddfb9c62d0dc344 Mon Sep 17 00:00:00 2001
From: Felix Schindler <felix.schindler@wwu.de>
Date: Sat, 14 Mar 2020 21:28:41 +0100
Subject: [PATCH] [local.functionals] update intersection functionals according
 to integrands

---
 dune/gdt/functionals/l2.hh                    | 12 +--
 dune/gdt/functionals/vector-based.hh          | 21 ++++-
 .../local/assembler/functional-assemblers.hh  | 79 +++++++++++++++++++
 dune/gdt/local/functionals/integrals.hh       | 63 ++++++++-------
 dune/gdt/local/functionals/interfaces.hh      | 24 +++---
 5 files changed, 148 insertions(+), 51 deletions(-)

diff --git a/dune/gdt/functionals/l2.hh b/dune/gdt/functionals/l2.hh
index e71cd509b..87e6b44b8 100644
--- a/dune/gdt/functionals/l2.hh
+++ b/dune/gdt/functionals/l2.hh
@@ -67,10 +67,8 @@ public:
                            const ElementFilterType& filter = ApplyOnAllElements())
     : BaseType(assembly_grid_view, source_spc, vec)
   {
-    this->append(LocalFunctionalType(local_binary_to_unary_element_integrand(inducing_function, LocalIntegrandType(1)),
-                                     over_integrate),
-                 param,
-                 filter);
+    this->append(
+        LocalFunctionalType(LocalIntegrandType(1).with_ansatz(inducing_function), over_integrate), param, filter);
   }
 
   L2VolumeVectorFunctional(AssemblyGridView assembly_grid_view,
@@ -81,10 +79,8 @@ public:
                            const ElementFilterType& filter = ApplyOnAllElements())
     : BaseType(assembly_grid_view, source_spc)
   {
-    this->append(LocalFunctionalType(local_binary_to_unary_element_integrand(inducing_function, LocalIntegrandType(1)),
-                                     over_integrate),
-                 param,
-                 filter);
+    this->append(
+        LocalFunctionalType(LocalIntegrandType(1).with_ansatz(inducing_function), over_integrate), param, filter);
   }
 }; // class L2VolumeVectorFunctional
 
diff --git a/dune/gdt/functionals/vector-based.hh b/dune/gdt/functionals/vector-based.hh
index 0841e094f..8f6c037b8 100644
--- a/dune/gdt/functionals/vector-based.hh
+++ b/dune/gdt/functionals/vector-based.hh
@@ -158,10 +158,11 @@ public:
   using typename FunctionalBaseType::SourceVectorType;
 
   using typename WalkerBaseType::ElementType;
+  using typename WalkerBaseType::IntersectionType;
   using ElementFilterType = XT::Grid::ElementFilter<AssemblyGridViewType>;
   using IntersectionFilterType = XT::Grid::IntersectionFilter<AssemblyGridViewType>;
   using ApplyOnAllElements = XT::Grid::ApplyOn::AllElements<AssemblyGridViewType>;
-  using ApplyOnAllIntersection = XT::Grid::ApplyOn::AllIntersections<AssemblyGridViewType>;
+  using ApplyOnAllIntersections = XT::Grid::ApplyOn::AllIntersections<AssemblyGridViewType>;
 
   /**
    * \name Ctors which accept an existing vector into which to assemble.
@@ -230,7 +231,23 @@ public:
         local_functional, param, XT::Grid::ApplyOn::GenericFilteredElements<AssemblyGridViewType>(filter_lambda));
   }
 
-  // similar append for LocalIntersectionFunctionalInterface ...
+  ThisType& append(const LocalIntersectionFunctionalInterface<IntersectionType, r, rC, F, DofFieldType>& local_functional,
+                   const XT::Common::Parameter& param = {},
+                   const IntersectionFilterType& filter = ApplyOnAllIntersections())
+  {
+    LocalIntersectionFunctionalAssembler<V, AssemblyGridViewType, r, rC, F, GV> tmp(
+        this->source_space(), local_functional, VectorStorage::access(), param);
+    this->append(tmp, filter);
+    return *this;
+  }
+
+  ThisType& append(const LocalIntersectionFunctionalInterface<IntersectionType, r, rC, F, DofFieldType>& local_functional,
+                   const XT::Common::Parameter& param,
+                   std::function<bool(const AssemblyGridViewType&, const IntersectionType&)> filter_lambda)
+  {
+    return append(
+        local_functional, param, XT::Grid::ApplyOn::GenericFilteredIntersections<AssemblyGridViewType>(filter_lambda));
+  }
 
   void assemble(const bool use_tbb = false) override final
   {
diff --git a/dune/gdt/local/assembler/functional-assemblers.hh b/dune/gdt/local/assembler/functional-assemblers.hh
index 841fb6ade..8827fed64 100644
--- a/dune/gdt/local/assembler/functional-assemblers.hh
+++ b/dune/gdt/local/assembler/functional-assemblers.hh
@@ -96,6 +96,85 @@ private:
 }; // class LocalElementFunctionalAssembler
 
 
+template <class Vector, class GridView, size_t r, size_t rC, class R = double, class SpaceGridView = GridView>
+class LocalIntersectionFunctionalAssembler : public XT::Grid::IntersectionFunctor<GridView>
+{
+  static_assert(XT::LA::is_vector<Vector>::value, "");
+  static_assert(XT::Grid::is_view<GridView>::value, "");
+  static_assert(XT::Grid::is_view<SpaceGridView>::value, "");
+
+  using ThisType = LocalIntersectionFunctionalAssembler<Vector, GridView, r, rC, R, SpaceGridView>;
+  using BaseType = XT::Grid::IntersectionFunctor<GridView>;
+
+public:
+  using typename BaseType::ElementType;
+  using typename BaseType::IntersectionType;
+  using VectorType = Vector;
+  using FieldType = typename VectorType::ScalarType;
+  using SpaceType = SpaceInterface<SpaceGridView, r, rC, R>;
+  using LocalFunctionalType = LocalIntersectionFunctionalInterface<IntersectionType, r, rC, R, FieldType>;
+
+  LocalIntersectionFunctionalAssembler(const SpaceType& space,
+                                       const LocalFunctionalType& local_functional,
+                                       VectorType& global_vector,
+                                       const XT::Common::Parameter& param = {})
+    : space_(space)
+    , local_functional_(local_functional.copy())
+    , global_vector_(global_vector)
+    , param_(param)
+    , local_vector_(space_.mapper().max_local_size())
+    , global_indices_(space_.mapper().max_local_size())
+    , basis_(space_.basis().localize())
+  {
+    DUNE_THROW_IF(global_vector_.size() != space_.mapper().size(),
+                  XT::Common::Exceptions::shapes_do_not_match,
+                  "global_vector.size() = " << global_vector_.size() << "\n  "
+                                            << "space.mapper().size()" << space_.mapper().size());
+  }
+
+  LocalIntersectionFunctionalAssembler(const ThisType& other)
+    : BaseType()
+    , space_(other.space_)
+    , local_functional_(other.local_functional_->copy())
+    , global_vector_(other.global_vector_)
+    , param_(other.param_)
+    , local_vector_(other.local_vector_)
+    , global_indices_(other.global_indices_)
+    , basis_(space_.basis().localize())
+  {}
+
+  LocalIntersectionFunctionalAssembler(ThisType&& source) = default;
+
+  BaseType* copy() override final
+  {
+    return new ThisType(*this);
+  }
+
+  void apply_local(const IntersectionType& intersection,
+                   const ElementType& inside_element,
+                   const ElementType& outside_element) override final
+  {
+    const auto& element = local_functional_->inside() ? inside_element : outside_element;
+    // apply functional
+    basis_->bind(element);
+    local_functional_->apply(intersection, *basis_, local_vector_, param_);
+    // copy local vector to global
+    space_.mapper().global_indices(element, global_indices_);
+    for (size_t jj = 0; jj < basis_->size(param_); ++jj)
+      global_vector_.add_to_entry(global_indices_[jj], local_vector_[jj]);
+  }
+
+private:
+  const SpaceType& space_;
+  std::unique_ptr<LocalFunctionalType> local_functional_;
+  VectorType& global_vector_;
+  XT::Common::Parameter param_;
+  DynamicVector<FieldType> local_vector_;
+  DynamicVector<size_t> global_indices_;
+  mutable std::unique_ptr<typename SpaceType::GlobalBasisType::LocalizedType> basis_;
+}; // class LocalIntersectionFunctionalAssembler
+
+
 } // namespace GDT
 } // namespace Dune
 
diff --git a/dune/gdt/local/functionals/integrals.hh b/dune/gdt/local/functionals/integrals.hh
index a27b88a75..dff5877ce 100644
--- a/dune/gdt/local/functionals/integrals.hh
+++ b/dune/gdt/local/functionals/integrals.hh
@@ -38,7 +38,7 @@ public:
 
   LocalElementIntegralFunctional(const IntegrandType& integrand, const int over_integrate = 0)
     : BaseType(integrand.parameter_type())
-    , integrand_(integrand.copy())
+    , integrand_(integrand.copy_as_unary_element_integrand())
     , over_integrate_(over_integrate)
   {}
 
@@ -49,13 +49,13 @@ public:
                                  const XT::Common::ParameterType& param_type = {},
                                  const int over_integrate = 0)
     : BaseType(param_type)
-    , integrand_(GenericIntegrand(order_function, evaluate_function, post_bind_function).copy())
+    , integrand_(GenericIntegrand(order_function, evaluate_function, post_bind_function).copy_as_unary_element_integrand())
     , over_integrate_(over_integrate)
   {}
 
   LocalElementIntegralFunctional(const ThisType& other)
     : BaseType(other.parameter_type())
-    , integrand_(other.integrand_->copy())
+    , integrand_(other.integrand_->copy_as_unary_element_integrand())
     , over_integrate_(other.over_integrate_)
   {}
 
@@ -114,29 +114,27 @@ public:
   using typename BaseType::D;
   using typename BaseType::IntersectionType;
   using typename BaseType::LocalBasisType;
-  using IntegrandType = LocalBinaryIntersectionIntegrandInterface<I, r, rC, R>;
-  using GenericIntegrand = GenericLocalBinaryIntersectionIntegrand<I, r, rC, R>;
+  using IntegrandType = LocalUnaryIntersectionIntegrandInterface<I, r, rC, R>;
+  //  using GenericIntegrand = GenericLocalUnaryIntersectionIntegrand<I, r, rC, R>;
 
   LocalIntersectionIntegralFunctional(const IntegrandType& integrand, const int over_integrate = 0)
     : BaseType(integrand.parameter_type())
-    , integrand_(integrand.copy())
+    , integrand_(integrand.copy_as_unary_intersection_integrand())
     , over_integrate_(over_integrate)
   {}
 
-  LocalIntersectionIntegralFunctional(typename GenericIntegrand::GenericOrderFunctionType order_function,
-                                      typename GenericIntegrand::GenericEvaluateFunctionType evaluate_function,
-                                      typename GenericIntegrand::GenericPostBindFunctionType post_bind_function =
-                                          [](const I&) {},
-                                      const XT::Common::ParameterType& param_type = {},
-                                      const int over_integrate = 0)
-    : BaseType(param_type)
-    , integrand_(GenericIntegrand(order_function, evaluate_function, post_bind_function).copy())
-    , over_integrate_(over_integrate)
-  {}
+  //  LocalIntersectionIntegralFunctional(typename GenericIntegrand::GenericOrderFunctionType order_function,
+  //                                      typename GenericIntegrand::GenericEvalauteFunctionType evaluate_function,
+  //                                      const XT::Common::ParameterType& param_type = {},
+  //                                      const int over_integrate = 0)
+  //    : BaseType(param_type)
+  //    , integrand_(GenericIntegrand(order_function, evaluate_function).copy())
+  //    , over_integrate_(over_integrate)
+  //  {}
 
   LocalIntersectionIntegralFunctional(const ThisType& other)
     : BaseType(other.parameter_type())
-    , integrand_(other.integrand_->copy())
+    , integrand_(other.integrand_->copy_as_unary_intersection_integrand())
     , over_integrate_(other.over_integrate_)
   {}
 
@@ -147,44 +145,45 @@ public:
     return std::make_unique<ThisType>(*this);
   }
 
+  bool inside() const override final
+  {
+    return integrand_->inside();
+  }
+
   using BaseType::apply;
 
   void apply(const IntersectionType& intersection,
-             const LocalBasisType& inside_basis,
-             const LocalBasisType& outside_basis,
-             DynamicMatrix<F>& result,
+             const LocalBasisType& test_basis,
+             DynamicVector<F>& result,
              const XT::Common::Parameter& param = {}) const override final
   {
     // prepare integand
     integrand_->bind(intersection);
     // prepare storage
-    const size_t rows = inside_basis.size(param);
-    const size_t cols = outside_basis.size(param);
-    if (result.rows() < rows || result.cols() < cols)
-      result.resize(rows, cols);
+    const size_t size = test_basis.size(param);
+    if (result.size() < size)
+      result.resize(size);
     result *= 0;
     // loop over all quadrature points
-    const auto integrand_order = integrand_->order(inside_basis, outside_basis, param) + over_integrate_;
+    const auto integrand_order = integrand_->order(test_basis, param) + over_integrate_;
     for (const auto& quadrature_point : QuadratureRules<D, d - 1>::rule(intersection.type(), integrand_order)) {
       const auto point_in_reference_intersection = quadrature_point.position();
       // integration factors
       const auto integration_factor = intersection.geometry().integrationElement(point_in_reference_intersection);
       const auto quadrature_weight = quadrature_point.weight();
       // evaluate the integrand
-      integrand_->evaluate(inside_basis, outside_basis, point_in_reference_intersection, integrand_values_, param);
-      assert(integrand_values_.rows() >= rows && "This must not happen!");
-      assert(integrand_values_.cols() >= cols && "This must not happen!");
+      integrand_->evaluate(test_basis, point_in_reference_intersection, integrand_values_, param);
+      assert(integrand_values_.size() >= size && "This must not happen!");
       // compute integral
-      for (size_t ii = 0; ii < rows; ++ii)
-        for (size_t jj = 0; jj < cols; ++jj)
-          result[ii][jj] += integrand_values_[ii][jj] * integration_factor * quadrature_weight;
+      for (size_t ii = 0; ii < size; ++ii)
+        result[ii] += integrand_values_[ii] * integration_factor * quadrature_weight;
     } // loop over all quadrature points
   } // ... apply(...)
 
 private:
   mutable std::unique_ptr<IntegrandType> integrand_;
   const int over_integrate_;
-  mutable DynamicMatrix<F> integrand_values_;
+  mutable DynamicVector<F> integrand_values_;
 }; // class LocalIntersectionIntegralFunctional
 
 
diff --git a/dune/gdt/local/functionals/interfaces.hh b/dune/gdt/local/functionals/interfaces.hh
index a9cb21a82..6424b4bda 100644
--- a/dune/gdt/local/functionals/interfaces.hh
+++ b/dune/gdt/local/functionals/interfaces.hh
@@ -126,24 +126,30 @@ public:
   virtual std::unique_ptr<ThisType> copy() const = 0;
 
   /**
-   * Computes the application of this functional for each combination of basis functions.
+   * Flag to document which element the basis is expected to be bound to.
+   */
+  virtual bool inside() const
+  {
+    return true;
+  }
+
+  /**
+   * Computes the application of this functional for each basis function.
    */
   virtual void apply(const IntersectionType& intersection,
-                     const LocalBasisType& inside_basis,
-                     const LocalBasisType& outside_basis,
-                     DynamicMatrix<F>& result,
+                     const LocalBasisType& test_basis,
+                     DynamicVector<F>& result,
                      const XT::Common::Parameter& param = {}) const = 0;
 
   /**
    * This method is provided for convenience and should not be used within library code.
    */
-  virtual DynamicMatrix<F> apply(const IntersectionType& intersection,
-                                 const LocalBasisType& inside_basis,
-                                 const LocalBasisType& outside_basis,
+  virtual DynamicVector<F> apply(const IntersectionType& intersection,
+                                 const LocalBasisType& test_basis,
                                  const XT::Common::Parameter& param = {}) const
   {
-    DynamicMatrix<F> ret(inside_basis.size(param), outside_basis.size(param), 0);
-    this->apply(intersection, inside_basis, outside_basis, ret, param);
+    DynamicVector<F> ret(test_basis.size(param), 0);
+    this->apply(intersection, test_basis, ret, param);
     return ret;
   }
 }; // class LocalIntersectionFunctionalInterface
-- 
GitLab