Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
local-mass-matrix.hh 5.23 KiB
// 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_TOOLS_local_mass_matrices_HH
#define DUNE_GDT_TOOLS_local_mass_matrices_HH

#include <mutex>
#include <vector>

#include <dune/xt/common/parallel/threadstorage.hh>
#include <dune/xt/la/container/common.hh>
#include <dune/xt/la/container/conversion.hh>
#include <dune/xt/la/matrix-inverter.hh>
#include <dune/xt/grid/functors/interfaces.hh>
#include <dune/xt/grid/type_traits.hh>

#include <dune/gdt/exceptions.hh>
#include <dune/gdt/local/bilinear-forms/integrals.hh>
#include <dune/gdt/local/integrands/product.hh>
#include <dune/gdt/spaces/interface.hh>
#include <dune/gdt/spaces/mapper/finite-volume.hh>

namespace Dune {
namespace GDT {


template <class GV, size_t r = 1, size_t rC = 1, class F = double, class AGV = GV>
class LocalMassMatrixProvider
  : public XT::Grid::ElementFunctor<GV>
  , public XT::Common::ThreadResultPropagator<
        LocalMassMatrixProvider<GV, r, rC, F>,
        std::map<size_t, std::pair<XT::LA::CommonDenseMatrix<F>, XT::LA::CommonDenseMatrix<F>>>,
        XT::Common::merge_container<
            std::map<size_t, std::pair<XT::LA::CommonDenseMatrix<F>, XT::LA::CommonDenseMatrix<F>>>>>
{
  static_assert(XT::Grid::is_view<AGV>::value, "");

  using ThisType = LocalMassMatrixProvider<GV, r, rC, F>;
  using BaseType = XT::Grid::ElementFunctor<GV>;
  using Propagator = XT::Common::ThreadResultPropagator<
      LocalMassMatrixProvider<GV, r, rC, F>,
      std::map<size_t, std::pair<XT::LA::CommonDenseMatrix<F>, XT::LA::CommonDenseMatrix<F>>>,
      XT::Common::merge_container<
          std::map<size_t, std::pair<XT::LA::CommonDenseMatrix<F>, XT::LA::CommonDenseMatrix<F>>>>>;
  friend Propagator;

public:
  using AssemblyGridView = AGV;
  using SpaceType = SpaceInterface<GV, r, rC, F>;
  using typename BaseType::E;
  using typename BaseType::ElementType;

  LocalMassMatrixProvider(const AssemblyGridView& grid_view, const SpaceType& space)
    : Propagator(this)
    , grid_view_(grid_view)
    , space_(space)
    , element_mapper_(grid_view_)
    , instance_counter_(0)
    , local_basis_(space_.basis().localize())
  {}

  LocalMassMatrixProvider(const ThisType& other)
    : Propagator(this)
    , grid_view_(other.grid_view_)
    , space_(other.space_)
    , element_mapper_(grid_view_)
    , instance_counter_(other.instance_counter_ + 1)
    , local_basis_(space_.basis().localize())
  {}

  void apply_local(const ElementType& element)
  {
    local_basis_->bind(element);
    const size_t id = element_mapper_.global_index(element, 0);
    const LocalElementIntegralBilinearForm<E, r, rC, F, F> local_l2_bilinear_form(
        LocalElementProductIntegrand<E, r, rC, F, F>(1.));
    auto matrix =
        XT::LA::convert_to<XT::LA::CommonDenseMatrix<F>>(local_l2_bilinear_form.apply2(*local_basis_, *local_basis_));
    auto inverse = XT::LA::invert_matrix(matrix);
    local_mass_matrices_.insert(std::make_pair(id, std::make_pair(std::move(matrix), std::move(inverse))));
  } // ... apply_local(...)

  BaseType* copy() override final
  {
    return Propagator::copy_imp();
  }

  void finalize() override final
  {
    this->finalize_imp();
  }

  /**
   * \note This is only used to merge the thread-local results after the grid walk, you are probably interested in
   *       local_mass_matrix() and local_mass_matrix_inverse().
   */
  std::map<size_t, std::pair<XT::LA::CommonDenseMatrix<F>, XT::LA::CommonDenseMatrix<F>>> result() const
  {
    return local_mass_matrices_;
  }

  void set_result(std::map<size_t, std::pair<XT::LA::CommonDenseMatrix<F>, XT::LA::CommonDenseMatrix<F>>> res)
  {
    local_mass_matrices_ = res;
  }

  const XT::LA::CommonDenseMatrix<F>& local_mass_matrix(const ElementType& element) const
  {
    const size_t id = element_mapper_.global_index(element, 0);
    DUNE_THROW_IF(local_mass_matrices_.count(id) == 0,
                  XT::Common::Exceptions::this_should_not_happen,
                  "Missing local mass matrix for id " << id << "!");
    return local_mass_matrices_.at(id).first;
  }

  const XT::LA::CommonDenseMatrix<F>& local_mass_matrix_inverse(const ElementType& element) const
  {
    const size_t id = element_mapper_.global_index(element, 0);
    DUNE_THROW_IF(local_mass_matrices_.count(id) == 0,
                  XT::Common::Exceptions::this_should_not_happen,
                  "Missing local mass matrix for id " << id << "!");
    return local_mass_matrices_.at(id).second;
  }

private:
  const AssemblyGridView& grid_view_;
  const SpaceType& space_;
  const FiniteVolumeMapper<GV> element_mapper_;
  size_t instance_counter_;
  std::unique_ptr<typename SpaceType::GlobalBasisType::LocalizedBasisType> local_basis_;
  std::map<size_t, std::pair<XT::LA::CommonDenseMatrix<F>, XT::LA::CommonDenseMatrix<F>>> local_mass_matrices_;
}; // class LocalMassMatrixProvider

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_TOOLS_local_mass_matrices_HH