From 832254047a18f14834024db7e080037ee05fe53e Mon Sep 17 00:00:00 2001
From: Felix Schindler <felix.schindler@wwu.de>
Date: Sun, 5 Aug 2018 17:57:56 +0200
Subject: [PATCH] [test.linear-transport] add some 1d tests

---
 dune/gdt/test/linear-transport/base.hh        |  75 +++++++++
 .../linear_transport__1d__explicit__fv.cc     | 157 ++++++++++++++++++
 2 files changed, 232 insertions(+)
 create mode 100644 dune/gdt/test/linear-transport/base.hh
 create mode 100644 dune/gdt/test/linear-transport/linear_transport__1d__explicit__fv.cc

diff --git a/dune/gdt/test/linear-transport/base.hh b/dune/gdt/test/linear-transport/base.hh
new file mode 100644
index 000000000..11bfddd49
--- /dev/null
+++ b/dune/gdt/test/linear-transport/base.hh
@@ -0,0 +1,75 @@
+// 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 (2018)
+
+#ifndef DUNE_GDT_TEST_LINEAR_TRANSPORT_BASE_HH
+#define DUNE_GDT_TEST_LINEAR_TRANSPORT_BASE_HH
+
+#include <cmath>
+
+#include <dune/xt/common/float_cmp.hh>
+#include <dune/xt/common/fvector.hh>
+#include <dune/xt/functions/lambda/function.hh>
+#include <dune/xt/grid/gridprovider/cube.hh>
+
+#include <dune/gdt/interpolations.hh>
+#include <dune/gdt/spaces/interface.hh>
+
+namespace Dune {
+namespace GDT {
+namespace Test {
+
+
+template <class G>
+struct LinearTransportProblem
+{
+  static const constexpr size_t d = G::dimension;
+  using DomainType = XT::Common::FieldVector<double, d>;
+
+  const DomainType direction;
+  const XT::Functions::LambdaFunction<1, d, 1> flux;
+  const double T_end;
+
+  LinearTransportProblem()
+    : direction(XT::Common::from_string<DomainType>("[1 0 0]"))
+    , flux(1,
+           [&](const auto& u, const auto& /*param*/) { return direction * u; },
+           "linear_transport",
+           {},
+           [&](const auto& /*u*/, const auto& /*param*/) { return direction; })
+    , T_end(1.)
+  {
+  }
+
+  XT::Grid::GridProvider<G> make_initial_grid() const
+  {
+    return XT::Grid::make_cube_grid<G>(0., 1., 16u);
+  }
+
+  template <class Vector, class GV>
+  DiscreteFunction<Vector, GV> make_exact_solution__periodic_boundaries(const SpaceInterface<GV, 1>& space,
+                                                                        const double& time) const
+  {
+    DUNE_THROW_IF(time > 1., XT::Common::Exceptions::wrong_input_given, "time = " << time);
+    const auto indicator = [](const auto& x) {
+      if (0.25 <= x && x <= 0.5)
+        return 1.;
+      else
+        return 0.;
+    };
+    return interpolate<Vector>(
+        0, [&](const auto& xx, const auto& /*mu*/) { return indicator(std::fmod(xx[0] - time + 1., 1.)); }, space);
+  } // ... make_exact_solution__periodic_boundaries(...)
+}; // struct LinearTransportProblem
+
+
+} // namespace Test
+} // namespace GDT
+} // namespace Dune
+
+#endif // DUNE_GDT_TEST_LINEAR_TRANSPORT_BASE_HH
diff --git a/dune/gdt/test/linear-transport/linear_transport__1d__explicit__fv.cc b/dune/gdt/test/linear-transport/linear_transport__1d__explicit__fv.cc
new file mode 100644
index 000000000..f198959a9
--- /dev/null
+++ b/dune/gdt/test/linear-transport/linear_transport__1d__explicit__fv.cc
@@ -0,0 +1,157 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2017 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 (2018)
+
+#define DUNE_XT_COMMON_TEST_MAIN_ENABLE_TIMED_LOGGING 1
+#define DUNE_XT_COMMON_TEST_MAIN_ENABLE_INFO_LOGGING 1
+
+#include <dune/xt/common/test/main.hxx> // <- this one has to come first (includes the config.h)!
+
+#include <dune/xt/common/memory.hh>
+#include <dune/xt/grid/grids.hh>
+
+#include <dune/gdt/test/instationary-eocstudies/hyperbolic-fv.hh>
+
+#include "base.hh"
+
+using namespace Dune;
+using namespace Dune::GDT::Test;
+
+
+template <class G>
+class LinearTransportExplicitFvTest : XT::Common::ConstStorageProvider<LinearTransportProblem<G>>,
+                                      public InstationaryHyperbolicFiniteVolumeEocStudy<G, 1>
+{
+  using Problem = XT::Common::ConstStorageProvider<LinearTransportProblem<G>>;
+  using BaseType = InstationaryHyperbolicFiniteVolumeEocStudy<G, 1>;
+
+protected:
+  using BaseType::d;
+  using typename BaseType::F;
+  using typename BaseType::DF;
+  using typename BaseType::GP;
+  using typename BaseType::S;
+  using typename BaseType::BS;
+  using typename BaseType::V;
+
+public:
+  LinearTransportExplicitFvTest(const size_t num_refinements = 3,
+                                const size_t num_additional_refinements_for_reference = 1) // Not exact, but enough.
+      : Problem(new LinearTransportProblem<G>()),
+        BaseType(Problem::access().T_end,
+                 num_refinements,
+                 num_additional_refinements_for_reference,
+                 [&](const auto& solution, const auto& prefix) {
+                   for (size_t ii = 0; ii < this->visualization_steps_; ++ii) {
+                     const double time = ii * (this->T_end_ / this->visualization_steps_);
+                     const auto u_t = solution.evaluate(time);
+                     make_discrete_function(solution.space().spatial_space(), u_t)
+                         .visualize(prefix + "_solution_" + XT::Common::to_string(ii));
+                   }
+                 }),
+        visualization_steps_(0)
+  {
+  }
+
+  std::vector<std::string> targets() const override final
+  {
+    if (d == 1) // in 1d dt depends linearly on h, so no need to pollute the EOC table with dt-related values
+      return {"h"};
+    else
+      return BaseType::targets();
+  }
+
+  double estimate_dt(const S& space) override final
+  {
+    if (d == 1) { // in 1d we know that dt = h is a good choice
+      double grid_width = 0.;
+      for (auto&& grid_element : elements(space.grid_view())) {
+        grid_width = std::max(grid_width, XT::Grid::entity_diameter(grid_element));
+      }
+      return grid_width;
+    } else
+      return BaseType::estimate_dt(space);
+  } // ... estimate_dt(...)
+
+protected:
+  const F& flux() const override final
+  {
+    return Problem::access().flux;
+  }
+
+  DF make_initial_values(const S& space) override final
+  {
+    return Problem::access().template make_exact_solution__periodic_boundaries<V>(space, 0.);
+  }
+
+  GP make_initial_grid() override final
+  {
+    return Problem::access().make_initial_grid();
+  }
+
+  XT::LA::ListVectorArray<V> solve(const S& space, const double T_end, const double dt) override final
+  {
+    const auto u_0 = this->make_initial_values(space);
+    const auto op = this->make_lhs_operator(space);
+    return solve_instationary_system_explicit_euler(u_0, *op, T_end, dt);
+  }
+
+  void compute_reference_solution() override final
+  {
+    auto& self = *this;
+    if (self.reference_solution_on_reference_grid_)
+      return;
+    self.reference_grid_ = std::make_unique<GP>(make_initial_grid());
+    for (size_t ref = 0; ref < self.num_refinements_ + self.num_additional_refinements_for_reference_; ++ref)
+      self.reference_grid_->global_refine(DGFGridInfo<G>::refineStepsForHalf());
+    self.reference_space_ = self.make_space(*self.reference_grid_);
+    const auto dt = estimate_dt(*self.reference_space_);
+    self.reference_solution_on_reference_grid_ = std::make_unique<XT::LA::ListVectorArray<V>>(
+        self.reference_space_->mapper().size(), /*length=*/0, /*reserve=*/std::ceil(self.T_end_ / (dt)));
+    double time = 0.;
+    while (time < self.T_end_ + dt) {
+      auto u_t = Problem::access().template make_exact_solution__periodic_boundaries<V>(*self.reference_space_, time);
+      self.reference_solution_on_reference_grid_->append(u_t.dofs().vector(), {"_t", time});
+      time += dt;
+    }
+    // visualize
+    const BS reference_bochner_space(*self.reference_space_,
+                                     self.time_points_from_vector_array(*self.reference_solution_on_reference_grid_));
+    self.visualize_(
+        make_discrete_bochner_function(reference_bochner_space, *self.reference_solution_on_reference_grid_),
+        "reference_solution_on_refinement_"
+            + XT::Common::to_string(self.num_refinements_ + self.num_additional_refinements_for_reference_));
+  } // ... compute_reference_solution(...)
+
+protected:
+  size_t visualization_steps_;
+}; // class LinearTransportExplicitFvTest
+
+
+using LinearTransport1dExplicitFvTest = LinearTransportExplicitFvTest<YASP_1D_EQUIDISTANT_OFFSET>;
+TEST_F(LinearTransport1dExplicitFvTest, periodic_boundaries__numerical_upwind_flux)
+{
+  //  this->visualization_steps_ = 100; // <- something like this to visualize
+  this->set_numerical_flux("upwind");
+  this->run();
+}
+TEST_F(LinearTransport1dExplicitFvTest, periodic_boundaries__numerical_lax_riedrichs_flux)
+{
+  this->set_numerical_flux("lax_friedrichs");
+  this->run();
+}
+TEST_F(LinearTransport1dExplicitFvTest, periodic_boundaries__numerical_engquist_osher_flux)
+{
+  this->set_numerical_flux("engquist_osher");
+  this->run();
+}
+TEST_F(LinearTransport1dExplicitFvTest, periodic_boundaries__numerical_vijayasundaram_flux)
+{
+  this->set_numerical_flux("vijayasundaram");
+  this->run();
+}
-- 
GitLab