From b07e84cd1d604b10f75f06ae61f61fa5698b6cfa Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Thu, 1 Feb 2018 11:18:27 +0100
Subject: [PATCH] Correctly pass grid function types into the local operator

---
 python/dune/perftool/pdelab/driver/solve.py  |  6 +-
 python/dune/perftool/pdelab/localoperator.py | 28 +++++++-
 test/coeffeval/coeffeval_poisson.cc          | 75 ++++++++++++++------
 3 files changed, 84 insertions(+), 25 deletions(-)

diff --git a/python/dune/perftool/pdelab/driver/solve.py b/python/dune/perftool/pdelab/driver/solve.py
index 2e9b3ee1..29b0e268 100644
--- a/python/dune/perftool/pdelab/driver/solve.py
+++ b/python/dune/perftool/pdelab/driver/solve.py
@@ -9,6 +9,7 @@ from dune.perftool.pdelab.driver import (get_form_ident,
                                          name_initree,
                                          )
 from dune.perftool.pdelab.driver.gridfunctionspace import (name_trial_gfs,
+                                                           type_domainfield,
                                                            type_trial_gfs,
                                                            )
 from dune.perftool.pdelab.driver.constraints import (type_constraintscontainer,
@@ -82,8 +83,9 @@ def name_vector(form_ident):
 
 @preamble
 def typedef_vector(name, form_ident):
-    go_type = type_gridoperator(form_ident)
-    return "using {} = {}::Traits::Domain;".format(name, go_type)
+    gfs = type_trial_gfs()
+    df = type_domainfield()
+    return "using {} = Dune::PDELab::Backend::Vector<{},{}>;".format(name, gfs, df)
 
 
 def type_vector(form_ident):
diff --git a/python/dune/perftool/pdelab/localoperator.py b/python/dune/perftool/pdelab/localoperator.py
index ea0dad53..336062fc 100644
--- a/python/dune/perftool/pdelab/localoperator.py
+++ b/python/dune/perftool/pdelab/localoperator.py
@@ -157,6 +157,26 @@ def localoperator_basename(form_ident):
     return get_form_option("classname", form_ident)
 
 
+def name_gridfunction_member(coeff):
+    name = "gridfunction_{}".format(coeff.count())
+    define_gridfunction_member(name)
+    return name
+
+
+@class_member(classtag="operator")
+def define_gridfunction_member(name):
+    _type = type_gridfunction_template_parameter(name)
+    param = "{}_".format(name)
+    constructor_parameter("const {}&".format(_type), param, classtag="operator")
+    initializer_list(name, [param], classtag="operator")
+    return "const {}& {};".format(_type, name)
+
+
+@template_parameter(classtag="operator")
+def type_gridfunction_template_parameter(name):
+    return name.upper()
+
+
 def class_type_from_cache(classtag):
     from dune.perftool.generation import retrieve_cache_items
 
@@ -702,10 +722,14 @@ def generate_localoperator_kernels(operator):
     lop_template_test_gfs()
     lop_template_range_field()
 
-    # Make sure there is always the same constructor arguments (even if parameter class is empty)
-    from dune.perftool.pdelab.localoperator import name_initree_member
+    # Make sure there is always the same constructor arguments, even if some of them are
+    # not strictly needed. Also ensure the order.
     name_initree_member()
 
+    # Iterate over the needed grid functions in correct order
+    for c in sorted(filter(lambda c: c.count() > 2, form.coefficients()), key=lambda c: c.count()):
+        name_gridfunction_member(c)
+
     # Set some options!
     from dune.perftool.pdelab.driver import isQuadrilateral
     if isQuadrilateral(form.coefficients()[0].ufl_element().cell()):
diff --git a/test/coeffeval/coeffeval_poisson.cc b/test/coeffeval/coeffeval_poisson.cc
index 5fdf803b..cd80eb74 100644
--- a/test/coeffeval/coeffeval_poisson.cc
+++ b/test/coeffeval/coeffeval_poisson.cc
@@ -18,64 +18,95 @@
 #include "poisson_localoperator.hh"
 #include "dune/pdelab/stationary/linearproblem.hh"
 #include "dune/grid/io/file/vtk/subsamplingvtkwriter.hh"
+#include "dune/pdelab/function/discretegridviewfunction.hh"
 
 
 int main(int argc, char** argv)
 {
+  // MPI helper stuff
   Dune::MPIHelper& helper = Dune::MPIHelper::instance(argc, argv);
-  using VectorBackendP1 = Dune::PDELab::ISTL::VectorBackend<Dune::PDELab::ISTL::Blocking::none>;
+
+  // Parse the ini file
+  Dune::ParameterTree initree;
+  Dune::ParameterTreeParser::readINITree(argv[1], initree);
+
+  // Build a grid
   using Grid = Dune::ALUGrid<2, 2, Dune::simplex, Dune::conforming>;
   using GV = Grid::LeafGridView;
+  IniGridFactory<Grid> factory(initree);
+  std::shared_ptr<Grid> grid = factory.getGrid();
+  GV gv = grid->leafGridView();
+
+  // General types and stuff
   using DF = Grid::ctype;
   using RangeType = double;
+
+  // Finite Element Maps
   using P1_FEM = Dune::PDELab::PkLocalFiniteElementMap<GV, DF, RangeType, 1>;
+  P1_FEM p1_fem(gv);
+
+  // Grid Function Spaces
+  using VectorBackendP1 = Dune::PDELab::ISTL::VectorBackend<Dune::PDELab::ISTL::Blocking::none>;
   using DirichletConstraintsAssember = Dune::PDELab::ConformingDirichletConstraints;
   using P1_dirichlet_GFS = Dune::PDELab::GridFunctionSpace<GV, P1_FEM, DirichletConstraintsAssember, VectorBackendP1>;
-  using LOP_R = PoissonLocalOperator<P1_dirichlet_GFS, P1_dirichlet_GFS, RangeType>;
-  using P1_dirichlet_GFS_CC = P1_dirichlet_GFS::ConstraintsContainer<RangeType>::Type;
-  using MatrixBackend = Dune::PDELab::ISTL::BCRSMatrixBackend<>;
-  using GO_r = Dune::PDELab::GridOperator<P1_dirichlet_GFS, P1_dirichlet_GFS, LOP_R, MatrixBackend, DF, RangeType, RangeType, P1_dirichlet_GFS_CC, P1_dirichlet_GFS_CC>;
-  using LinearSolver = Dune::PDELab::ISTLBackend_SEQ_SuperLU;
-  using V_R = GO_r::Traits::Domain;
-  using SLP = Dune::PDELab::StationaryLinearProblemSolver<GO_r, LinearSolver, V_R>;
-  Dune::ParameterTree initree;
-  Dune::ParameterTreeParser::readINITree(argv[1], initree);
-  IniGridFactory<Grid> factory(initree);
-  std::shared_ptr<Grid> grid = factory.getGrid();
-  GV gv = grid->leafGridView();
-  P1_FEM p1_fem(gv);
   P1_dirichlet_GFS p1_dirichlet_gfs_(gv, p1_fem);
   p1_dirichlet_gfs_.name("p1_dirichlet_gfs_");
+  p1_dirichlet_gfs_.update();
+  std::cout << "gfs with " << p1_dirichlet_gfs_.size() << " dofs generated  "<< std::endl;
+
+  // Solution vectors / Grid Functions
+  using V_R = Dune::PDELab::Backend::Vector<P1_dirichlet_GFS,DF>;
+  V_R x_r(p1_dirichlet_gfs_);
+  V_R sol(p1_dirichlet_gfs_);
+
+  using GF = Dune::PDELab::DiscreteGridViewFunction<P1_dirichlet_GFS, V_R>;
+  GF sol_gf(p1_dirichlet_gfs_, sol);
+
+  // Local Operator
+  using LOP_R = PoissonLocalOperator<P1_dirichlet_GFS, P1_dirichlet_GFS, RangeType, GF>;
+  LOP_R lop_r(p1_dirichlet_gfs_, p1_dirichlet_gfs_, initree, sol_gf);
+
+  // Constraints stuff
+  using P1_dirichlet_GFS_CC = P1_dirichlet_GFS::ConstraintsContainer<RangeType>::Type;
   P1_dirichlet_GFS_CC p1_dirichlet_gfs__cc;
   p1_dirichlet_gfs__cc.clear();
   auto p1_bctype_lambda = [&](const auto& x){ return 1.0; };
   auto p1_bctype = Dune::PDELab::makeBoundaryConditionFromCallable(gv, p1_bctype_lambda);
   Dune::PDELab::constraints(p1_bctype, p1_dirichlet_gfs_, p1_dirichlet_gfs__cc);
-  LOP_R lop_r(p1_dirichlet_gfs_, p1_dirichlet_gfs_, initree);
-  p1_dirichlet_gfs_.update();
+  std::cout << "cc with " << p1_dirichlet_gfs__cc.size() << " dofs generated  "<< std::endl;
+
+  // Matrix Backend
+  using MatrixBackend = Dune::PDELab::ISTL::BCRSMatrixBackend<>;
   int generic_dof_estimate =  6 * p1_dirichlet_gfs_.maxLocalSize();
   int dofestimate = initree.get<int>("istl.number_of_nnz", generic_dof_estimate);
   MatrixBackend mb(dofestimate);
+
+  // Grid Operator
+  using GO_r = Dune::PDELab::GridOperator<P1_dirichlet_GFS, P1_dirichlet_GFS, LOP_R, MatrixBackend, DF, RangeType, RangeType, P1_dirichlet_GFS_CC, P1_dirichlet_GFS_CC>;
   GO_r go_r(p1_dirichlet_gfs_, p1_dirichlet_gfs__cc, p1_dirichlet_gfs_, p1_dirichlet_gfs__cc, lop_r, mb);
-  std::cout << "gfs with " << p1_dirichlet_gfs_.size() << " dofs generated  "<< std::endl;
-  std::cout << "cc with " << p1_dirichlet_gfs__cc.size() << " dofs generated  "<< std::endl;
+
+  // Solver
+  using LinearSolver = Dune::PDELab::ISTLBackend_SEQ_SuperLU;
   LinearSolver ls(false);
-  V_R x_r(p1_dirichlet_gfs_);
-  V_R sol(p1_dirichlet_gfs_);
+  using SLP = Dune::PDELab::StationaryLinearProblemSolver<GO_r, LinearSolver, V_R>;
+
+  // Interpolation
   x_r = 0.0;
   std::size_t seed = 0;
   auto rng = std::mt19937_64(seed);
   auto dist = std::uniform_real_distribution<>(-1., 1.);
   for (auto& v : sol)
     v = dist(rng);
-
   auto lambda_0000 = [&](const auto& x){ return (double)exp((-1.0) * ((0.5 - x[1]) * (0.5 - x[1]) + (0.5 - x[0]) * (0.5 - x[0]))); };
   auto func_0000 = Dune::PDELab::makeGridFunctionFromCallable(gv, lambda_0000);
   Dune::PDELab::interpolate(func_0000, p1_dirichlet_gfs_, sol);
 
+  // Solving
   double reduction = initree.get<double>("reduction", 1e-12);
   SLP slp(go_r, ls, x_r, reduction);
   slp.apply();
+
+  // VTK visualization
   using VTKWriter = Dune::SubsamplingVTKWriter<GV>;
   Dune::RefinementIntervals subint(initree.get<int>("vtk.subsamplinglevel", 1));
   VTKWriter vtkwriter(gv, subint);
@@ -83,6 +114,8 @@ int main(int argc, char** argv)
   CuttingPredicate predicate;
   Dune::PDELab::addSolutionToVTKWriter(vtkwriter, p1_dirichlet_gfs_, x_r, Dune::PDELab::vtk::defaultNameScheme(), predicate);
   vtkwriter.write(vtkfile, Dune::VTK::ascii);
+
+  // Error calculation
   using P1_DIRICHLET_GFS__DGF = Dune::PDELab::DiscreteGridFunction<decltype(p1_dirichlet_gfs_),decltype(x_r)>;
   P1_DIRICHLET_GFS__DGF p1_dirichlet_gfs__dgf(p1_dirichlet_gfs_,x_r);
   RangeType l2error(0.0);
-- 
GitLab