diff --git a/.gitignore b/.gitignore
index 516eb4db88a4767b762b848f0a2166e93fba8390..6f452aaa54521d54dc8243e9d1032109f1785d8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,4 @@ demos-*
 *.vtu
 *.pc
 build-*
+*.pyc
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 14ac3d2a1425f44cb61e396915d8a63c8167217c..8371812975807df2293c569c4d9ab524607e3dd5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,8 +52,18 @@ find_file(SPE10MODEL1DATA
 add_subdirectory(doc)
 add_subdirectory(dune)
 add_subdirectory(cmake/modules)
-dune_install_python_package(PATH python)
 
+if(dune-pybindxi_FOUND)
+  foreach(_file
+          dune/__init__.py
+          dune/gdt/__init__.py
+         )
+  execute_process(COMMAND ln -s ${CMAKE_CURRENT_SOURCE_DIR}/python/${_file} ${CMAKE_CURRENT_BINARY_DIR}/${_file})
+  endforeach()
+endif()
+
+# enable headercheck
+add_definitions("-DENABLE_HEADERCHECK=1")
 add_format(${CMAKE_CURRENT_SOURCE_DIR})
 add_tidy(${CMAKE_CURRENT_SOURCE_DIR})
 
diff --git a/dune/gdt/CMakeLists.txt b/dune/gdt/CMakeLists.txt
index 383a3b23a51728ef78dbe7394f487f035f0cf8f3..4cd9213a830cc13b9bea961ebcf4feb30b3f44f8 100644
--- a/dune/gdt/CMakeLists.txt
+++ b/dune/gdt/CMakeLists.txt
@@ -1,9 +1,58 @@
 # This file is part of the dune-gdt project:
 #   https://github.com/dune-community/dune-gdt
 # Copyright 2010-2016 dune-gdt developers and contributors. All rights reserved.
-# License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
+# 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 (2010, 2013 - 2016)
+#   Felix Schindler (2010, 2013 - 2017)
+
+if(dune-pybindxi_FOUND)
+  dune_pybindxi_add_helper_lib(_gdt_bindings_helper
+                               assembler/system.bindings.cc
+                               discretefunction/default.bindings.cc
+                               #operators/elliptic-ipdg.bindings/alu_common_fem.cc
+                               #operators/elliptic-ipdg.bindings/alu_common_gdt.cc
+                               #operators/elliptic-ipdg.bindings/alu_common_pdelab.cc
+                               #operators/elliptic-ipdg.bindings/alu_eigen_fem.cc
+                               #operators/elliptic-ipdg.bindings/alu_eigen_gdt.cc
+                               #operators/elliptic-ipdg.bindings/alu_eigen_pdelab.cc
+                               operators/elliptic-ipdg.bindings/alu_istl_fem.cc
+                               #operators/elliptic-ipdg.bindings/alu_istl_gdt.cc
+                               #operators/elliptic-ipdg.bindings/alu_istl_pdelab.cc
+                               #operators/elliptic-ipdg.bindings/yasp_common_fem.cc
+                               #operators/elliptic-ipdg.bindings/yasp_common_gdt.cc
+                               #operators/elliptic-ipdg.bindings/yasp_common_pdelab.cc
+                               #operators/elliptic-ipdg.bindings/yasp_eigen_fem.cc
+                               #operators/elliptic-ipdg.bindings/yasp_eigen_gdt.cc
+                               #operators/elliptic-ipdg.bindings/yasp_eigen_pdelab.cc
+                               #operators/elliptic-ipdg.bindings/yasp_istl_fem.cc
+                               #operators/elliptic-ipdg.bindings/yasp_istl_gdt.cc
+                               #operators/elliptic-ipdg.bindings/yasp_istl_pdelab.cc
+                               #operators/elliptic.bindings/common_fem.cc
+                               #operators/elliptic.bindings/common_gdt.cc
+                               #operators/elliptic.bindings/common_pdelab.cc
+                               #operators/elliptic.bindings/eigen_fem.cc
+                               #operators/elliptic.bindings/eigen_gdt.cc
+                               #operators/elliptic.bindings/eigen_pdelab.cc
+                               operators/elliptic.bindings/istl_fem.cc
+                               #operators/elliptic.bindings/istl_gdt.cc
+                               #operators/elliptic.bindings/istl_pdelab.cc
+                               projections/dirichlet.bindings.cc
+                               spaces/cg.bindings.cc
+                               spaces/constraints.bindings.cc
+                               spaces/dg.bindings.cc
+                               #spaces/fv.bindings.cc
+                               )
+  dune_pybindxi_add_module(_gdt bindings.cc)
+  target_link_dune_default_libraries(_gdt)
+  target_link_libraries(_gdt _gdt_bindings_helper)
+  if(DUNE_XT_WITH_PYTHON_BINDINGS)
+    add_custom_target(bindings ALL DEPENDS _gdt)
+  else()
+    add_custom_target(bindings DEPENDS _gdt)
+  endif()
+endif()
 
 add_subdirectory(test EXCLUDE_FROM_ALL)
 
diff --git a/dune/gdt/assembler/system.bindings.cc b/dune/gdt/assembler/system.bindings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..841c53500a9d2f0718f17e60ebb5b97aa23f9ce3
--- /dev/null
+++ b/dune/gdt/assembler/system.bindings.cc
@@ -0,0 +1,45 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "system.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET);
+#if HAVE_DUNE_FEM
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING);
+#if HAVE_DUNE_FEM
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/assembler/system.bindings.hh b/dune/gdt/assembler/system.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..df13e64bdf77e7cfaee980e0cf7274e787505904
--- /dev/null
+++ b/dune/gdt/assembler/system.bindings.hh
@@ -0,0 +1,134 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_ASSEMBLER_SYSTEM_BINDINGS_HH
+#define DUNE_GDT_ASSEMBLER_SYSTEM_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include <dune/xt/common/memory.hh>
+#include <dune/xt/grid/grids.bindings.hh>
+
+#include <dune/gdt/spaces.bindings.hh>
+
+#include "system.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+template <class T /*, class GV = typename T::GridViewType, class A = T*/>
+class SystemAssembler
+{
+  static_assert(is_space<T>::value, "");
+
+public:
+  typedef GDT::SystemAssembler<T /*, G, A*/> type;
+  typedef pybind11::class_<type> bound_type;
+
+private:
+  typedef typename type::TestSpaceType TestSpaceType;
+  typedef typename type::GridViewType GridViewType;
+  typedef typename type::AnsatzSpaceType AnsatzSpaceType;
+
+  template <bool do_bind = (std::is_same<TestSpaceType, AnsatzSpaceType>::value
+                            && std::is_same<GridViewType, typename TestSpaceType::GridViewType>::value),
+            bool anything = true>
+  struct addbind_ctor_single
+  {
+    void operator()(bound_type& c)
+    {
+      namespace py = pybind11;
+      using namespace pybind11::literals;
+      c.def(py::init<T>(),
+            "space"_a,
+            "Uses given space as test and ansatz space, and the grid view of the given space as grid view.",
+            py::keep_alive<1, 2>());
+    }
+  }; // struct addbind_ctor_single
+
+  template <bool anything>
+  struct addbind_ctor_single<false, anything>
+  {
+    void operator()(bound_type& /*c*/)
+    {
+    }
+  }; // struct addbind_ctor_single
+
+public:
+  static bound_type bind(pybind11::module& m, const std::string& space_id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    bound_type c(
+        m, std::string("SystemAssembler__" + space_id).c_str(), std::string("SystemAssembler__" + space_id).c_str());
+    addbind_ctor_single<>()(c);
+
+    c.def("append", [](type& self, type& other) { self.append(other); }, "system_assembler"_a, py::keep_alive<1, 2>());
+    c.def("append",
+          [](type& self, XT::Grid::Walker<GridViewType>& other) { self.append(other); },
+          "grid_walker"_a,
+          py::keep_alive<1, 2>());
+    c.def("assemble", [](type& self, const bool use_tbb) { self.assemble(use_tbb); }, "use_tbb"_a = false);
+
+    m.def("make_system_assembler",
+          [](const TestSpaceType& space) { return new type(space); },
+          "space"_a,
+          py::keep_alive<0, 1>());
+    return c;
+  } // ... bind(...)
+}; // class SystemAssembler
+
+
+#define DUNE_GDT_ASSEMBLER_SYSTEM_BIND_GDT(_prefix, _GRID)                                                             \
+  _prefix class SystemAssembler<FV_SPACE(_GRID, leaf, gdt, 1, 1)>;                                                     \
+  _prefix class SystemAssembler<FV_SPACE(_GRID, level, gdt, 1, 1)>
+
+#define DUNE_GDT_ASSEMBLER_SYSTEM_BIND_FEM(_prefix, _GRID)                                                             \
+  _prefix class SystemAssembler<CG_SPACE(_GRID, leaf, fem, 1, 1, 1)>;                                                  \
+  _prefix class SystemAssembler<CG_SPACE(_GRID, level, fem, 1, 1, 1)>;                                                 \
+  _prefix class SystemAssembler<DG_SPACE(_GRID, leaf, fem, 1, 1, 1)>;                                                  \
+  _prefix class SystemAssembler<DG_SPACE(_GRID, level, fem, 1, 1, 1)>;                                                 \
+  _prefix class SystemAssembler<DG_SPACE(_GRID, leaf, fem, 2, 1, 1)>;                                                  \
+  _prefix class SystemAssembler<DG_SPACE(_GRID, level, fem, 2, 1, 1)>
+
+#define DUNE_GDT_ASSEMBLER_SYSTEM_BIND_PDELAB(_prefix, _GRID)                                                          \
+  _prefix class SystemAssembler<CG_SPACE(_GRID, leaf, pdelab, 1, 1, 1)>;                                               \
+  _prefix class SystemAssembler<CG_SPACE(_GRID, level, pdelab, 1, 1, 1)>
+
+
+// these lines have to match the corresponding ones in the .cc source file
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_GDT(extern template, YASP_2D_EQUIDISTANT_OFFSET);
+#if HAVE_DUNE_FEM
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_GDT(extern template, ALU_2D_SIMPLEX_CONFORMING);
+#if HAVE_DUNE_FEM
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_ASSEMBLER_SYSTEM_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_ASSEMBLER_SYSTEM_BINDINGS_HH
diff --git a/dune/gdt/bindings.cc b/dune/gdt/bindings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bc3e4064aefade846501a0d0b0fba6bea5ce976a
--- /dev/null
+++ b/dune/gdt/bindings.cc
@@ -0,0 +1,446 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <dune/pybindxi/pybind11.h>
+#include <dune/pybindxi/stl.h>
+
+#if HAVE_DUNE_FEM
+#include <dune/fem/misc/mpimanager.hh>
+#endif
+
+#include <dune/xt/common/string.hh>
+#include <dune/xt/common/timedlogging.hh>
+#include <dune/xt/common/configuration.pbh>
+#include <dune/xt/common/fvector.pbh>
+
+#include <dune/xt/grid/intersection.hh>
+#include <dune/xt/grid/type_traits.hh>
+
+#include <dune/xt/la/container.hh>
+
+#include <dune/gdt/functionals/l2.pbh>
+#include <dune/gdt/functionals/elliptic-ipdg.pbh>
+
+#include "bindings.hh"
+
+namespace py = pybind11;
+using namespace pybind11::literals;
+using namespace Dune;
+using namespace Dune::GDT::bindings;
+
+
+template <class I, bool required = true>
+struct for_Grid_and_Intersection
+{
+  template <class G>
+  static void addbind(py::module& m, const std::string& grid_id, const std::string& id)
+  {
+    auto constraints = DirichletConstraints<I>::bind(m, grid_id + id);
+//    DirichletConstraints<I>::template addbind<Dune::XT::LA::Backends::common_dense>(constraints);
+//#if HAVE_EIGEN
+//    DirichletConstraints<I>::template addbind<Dune::XT::LA::Backends::eigen_dense>(constraints);
+//    DirichletConstraints<I>::template addbind<Dune::XT::LA::Backends::eigen_sparse>(constraints);
+//#endif
+#if HAVE_DUNE_ISTL
+    DirichletConstraints<I>::template addbind<Dune::XT::LA::Backends::istl_sparse>(constraints);
+#endif
+  }
+};
+
+template <class I>
+struct for_Grid_and_Intersection<I, false>
+{
+  template <class G>
+  static void addbind(py::module& /*m*/, const std::string& /*grid_id*/, const std::string& /*id*/)
+  {
+  }
+};
+
+
+template <class S, class V, class F, bool lagrange = Dune::GDT::is_cg_space<S>::value>
+struct addbind_for_lagrange_space
+{
+  template <class BSA>
+  void operator()(py::module& m, BSA& bound_system_assembler, const std::string& space_id, const std::string& la_id)
+  {
+    // DirichletProjectionLocalizableOperator
+    DirichletProjectionLocalizableOperator<typename S::GridViewType, F, Dune::GDT::DiscreteFunction<S, V>>::bind(
+        m, space_id, la_id);
+    // DirichletConstraints
+    DirichletConstraints<typename XT::Grid::Intersection<typename S::GridViewType>::type>::addbind(
+        bound_system_assembler);
+  } // ... operator()(...)
+}; // struct addbind_for_lagrange_space
+
+template <class S, class V, class F>
+struct addbind_for_lagrange_space<S, V, F, false>
+{
+  template <class BSA>
+  void operator()(py::module& /*m*/,
+                  BSA& /*bound_system_assembler*/,
+                  const std::string& /*space_id*/,
+                  const std::string& /*la_id*/)
+  {
+  }
+}; // struct addbind_for_lagrange_space< ..., false>
+
+
+template <class SP>
+void addbind_for_space(py::module& m,
+                       const std::string& grid_id,
+                       const std::string& layer_id,
+                       const std::string& space_id,
+                       const std::string& backend)
+{
+  using namespace Dune;
+  using namespace Dune::XT;
+  using Common::to_string;
+  using Common::to_lower;
+
+  typedef typename SP::type S;
+  typedef typename XT::Grid::extract_grid<typename S::GridViewType>::type G;
+  typedef typename S::EntityType E;
+  typedef typename S::DomainFieldType D;
+  static const size_t d = S::dimDomain;
+  typedef typename S::RangeFieldType R;
+  typedef typename LA::Container<R, LA::Backends::istl_sparse>::MatrixType M;
+  typedef typename LA::Container<R, LA::Backends::istl_sparse>::VectorType V;
+  static const size_t r = S::dimRange;
+  static const size_t rC = S::dimRangeCols;
+  typedef Functions::LocalizableFunctionInterface<E, D, d, R, 1, 1> ScalarFunction;
+  typedef Functions::LocalizableFunctionInterface<E, D, d, R, d, d> TensorFunction;
+  const std::string r_ = to_string(r);
+  const std::string rC_ = to_string(rC);
+  const std::string p_ = to_string(int(S::polOrder)); // without the int(...) we get linker errors on module import
+  const std::string space_suffix = r_ + "x" + rC_ + "__p" + p_ + backend;
+  // Space
+  SpaceInterface<S>::bind(m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix);
+  m.def(std::string("make_" + to_lower(space_id) + "_space__" + space_suffix + "__" + layer_id).c_str(),
+        [](XT::Grid::GridProvider<G>& grid_provider, const int level) { return SP::create(grid_provider, level); },
+        "grid_provider"_a,
+        "level"_a = 0,
+        py::keep_alive<0, 1>());
+// DiscreteFunction
+//  ConstDiscreteFunction<S, COMMON_DENSE_VECTOR>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "common_dense");
+//  DiscreteFunction<S, COMMON_DENSE_VECTOR>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "common_dense");
+//#if HAVE_EIGEN
+//  ConstDiscreteFunction<S, EIGEN_DENSE_VECTOR>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "eigen_dense");
+//  DiscreteFunction<S, EIGEN_DENSE_VECTOR>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "eigen_dense");
+//#endif // HAVE_EIGEN
+#if HAVE_DUNE_ISTL
+  ConstDiscreteFunction<S, ISTL_DENSE_VECTOR>::bind(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_dense");
+  DiscreteFunction<S, ISTL_DENSE_VECTOR>::bind(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_dense");
+#endif // HAVE_DUNE_ISTL
+  // SystemAssembler
+  auto system_assembler =
+      SystemAssembler<S>::bind(m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix);
+  addbind_for_lagrange_space<S, COMMON_DENSE_VECTOR, ScalarFunction>()(
+      m, system_assembler, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "common_dense");
+//#if HAVE_EIGEN
+//  addbind_for_lagrange_space<S, EIGEN_DENSE_VECTOR, ScalarFunction>()(
+//      m, system_assembler, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "eigen_dense");
+//#endif
+//#if HAVE_DUNE_ISTL
+//  addbind_for_lagrange_space<S, ISTL_DENSE_VECTOR, ScalarFunction>()(
+//      m, system_assembler, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_dense");
+//#endif
+// EllipticMatrixOperator
+//  EllipticMatrixOperator<ScalarFunction, TensorFunction, S, COMMON_DENSE_MATRIX>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "common_dense");
+//  EllipticMatrixOperator<ScalarFunction, void, S, COMMON_DENSE_MATRIX>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "common_dense");
+//  EllipticMatrixOperator<TensorFunction, void, S, COMMON_DENSE_MATRIX>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "common_dense");
+//#if HAVE_EIGEN
+//  EllipticMatrixOperator<ScalarFunction, TensorFunction, S, EIGEN_DENSE_MATRIX>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "eigen_dense");
+//  EllipticMatrixOperator<ScalarFunction, void, S, EIGEN_DENSE_MATRIX>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "eigen_dense");
+//  EllipticMatrixOperator<TensorFunction, void, S, EIGEN_DENSE_MATRIX>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "eigen_dense");
+//  EllipticMatrixOperator<ScalarFunction, TensorFunction, S, EIGEN_SPARSE_MATRIX>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "eigen_sparse");
+//  EllipticMatrixOperator<ScalarFunction, void, S, EIGEN_SPARSE_MATRIX>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "eigen_sparse");
+//  EllipticMatrixOperator<TensorFunction, void, S, EIGEN_SPARSE_MATRIX>::bind(
+//      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "eigen_sparse");
+//#endif // HAVE_EIGEN
+#if HAVE_DUNE_ISTL
+  EllipticMatrixOperator<ScalarFunction, TensorFunction, S, ISTL_SPARSE_MATRIX>::bind(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_sparse");
+  EllipticMatrixOperator<ScalarFunction, void, S, ISTL_SPARSE_MATRIX>::bind(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_sparse");
+  EllipticMatrixOperator<TensorFunction, void, S, ISTL_SPARSE_MATRIX>::bind(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_sparse");
+#endif // HAVE_DUNE_ISTL
+// EllipticIpdgMatrixOperator
+#define BIND_ELLIPTIT_IPDG_OP(_MAT, _la, _MET, _met)                                                                   \
+  EllipticIpdgMatrixOperator<ScalarFunction,                                                                           \
+                             TensorFunction,                                                                           \
+                             S,                                                                                        \
+                             GDT::LocalEllipticIpdgIntegrands::Method::_MET,                                           \
+                             _MAT>::bind(m,                                                                            \
+                                         space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix,      \
+                                         _la,                                                                          \
+                                         _met);                                                                        \
+  EllipticIpdgMatrixOperator<ScalarFunction, void, S, GDT::LocalEllipticIpdgIntegrands::Method::_MET, _MAT>::bind(     \
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, _la, _met);                          \
+  EllipticIpdgMatrixOperator<TensorFunction, void, S, GDT::LocalEllipticIpdgIntegrands::Method::_MET, _MAT>::bind(     \
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, _la, _met)
+
+//  BIND_ELLIPTIT_IPDG_OP(COMMON_DENSE_MATRIX, "common_dense", sipdg, "Sipdg");
+//  BIND_ELLIPTIT_IPDG_OP(COMMON_DENSE_MATRIX, "common_dense", swipdg, "Swipdg");
+//  BIND_ELLIPTIT_IPDG_OP(COMMON_DENSE_MATRIX, "common_dense", swipdg_affine_factor, "SwipdgAffineFactor");
+//  BIND_ELLIPTIT_IPDG_OP(COMMON_DENSE_MATRIX, "common_dense", swipdg_affine_tensor, "SwipdgAffineTensor");
+//#if HAVE_EIGEN
+//  BIND_ELLIPTIT_IPDG_OP(EIGEN_DENSE_MATRIX, "eigen_dense", sipdg, "Sipdg");
+//  BIND_ELLIPTIT_IPDG_OP(EIGEN_DENSE_MATRIX, "eigen_dense", swipdg, "Swipdg");
+//  BIND_ELLIPTIT_IPDG_OP(EIGEN_DENSE_MATRIX, "eigen_dense", swipdg_affine_factor, "SwipdgAffineFactor");
+//  BIND_ELLIPTIT_IPDG_OP(EIGEN_DENSE_MATRIX, "eigen_dense", swipdg_affine_tensor, "SwipdgAffineTensor");
+//  BIND_ELLIPTIT_IPDG_OP(EIGEN_SPARSE_MATRIX, "eigen_sparse", sipdg, "SIPDG");
+//  BIND_ELLIPTIT_IPDG_OP(EIGEN_SPARSE_MATRIX, "eigen_sparse", sipdg, "Sipdg");
+//  BIND_ELLIPTIT_IPDG_OP(EIGEN_SPARSE_MATRIX, "eigen_sparse", swipdg, "Swipdg");
+//  BIND_ELLIPTIT_IPDG_OP(EIGEN_SPARSE_MATRIX, "eigen_sparse", swipdg_affine_factor, "SwipdgAffineFactor");
+//  BIND_ELLIPTIT_IPDG_OP(EIGEN_SPARSE_MATRIX, "eigen_sparse", swipdg_affine_tensor, "SwipdgAffineTensor");
+//#endif
+#if HAVE_DUNE_ISTL
+  BIND_ELLIPTIT_IPDG_OP(ISTL_SPARSE_MATRIX, "istl_sparse", sipdg, "Sipdg");
+  BIND_ELLIPTIT_IPDG_OP(ISTL_SPARSE_MATRIX, "istl_sparse", swipdg, "Swipdg");
+  BIND_ELLIPTIT_IPDG_OP(ISTL_SPARSE_MATRIX, "istl_sparse", swipdg_affine_factor, "SwipdgAffineFactor");
+  BIND_ELLIPTIT_IPDG_OP(ISTL_SPARSE_MATRIX, "istl_sparse", swipdg_affine_tensor, "SwipdgAffineTensor");
+#endif
+
+  // L2VolumeVectorFunctional
+  GDT::bind_l2_volume_vector_functional<ScalarFunction, S, V>(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_sparse");
+  // L2FaceVectorFunctional
+  GDT::bind_l2_face_vector_functional<ScalarFunction, S, V>(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_sparse");
+  // EllipticIpdgDirichletVectorFunctional
+  // - SIPDG
+  GDT::bind_elliptic_ipdg_dirichlet_vector_functional<ScalarFunction,
+                                                      ScalarFunction,
+                                                      TensorFunction,
+                                                      S,
+                                                      GDT::LocalEllipticIpdgIntegrands::Method::sipdg,
+                                                      V>(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_sparse", "Sipdg");
+  GDT::bind_elliptic_ipdg_dirichlet_vector_functional<ScalarFunction,
+                                                      ScalarFunction,
+                                                      void,
+                                                      S,
+                                                      GDT::LocalEllipticIpdgIntegrands::Method::sipdg,
+                                                      V>(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_sparse", "Sipdg");
+  // - SWIPDG
+  GDT::bind_elliptic_ipdg_dirichlet_vector_functional<ScalarFunction,
+                                                      ScalarFunction,
+                                                      TensorFunction,
+                                                      S,
+                                                      GDT::LocalEllipticIpdgIntegrands::Method::swipdg,
+                                                      V>(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_sparse", "Swipdg");
+  GDT::bind_elliptic_ipdg_dirichlet_vector_functional<ScalarFunction,
+                                                      ScalarFunction,
+                                                      void,
+                                                      S,
+                                                      GDT::LocalEllipticIpdgIntegrands::Method::swipdg,
+                                                      V>(
+      m, space_id + "Space__" + grid_id + "_" + layer_id + "_to_" + space_suffix, "istl_sparse", "Swipdg");
+  // SWIPDG, affine wrt diffusion factor
+  GDT::bind_elliptic_ipdg_dirichlet_vector_functional<ScalarFunction,
+                                                      ScalarFunction,
+                                                      TensorFunction,
+                                                      S,
+                                                      GDT::LocalEllipticIpdgIntegrands::Method::swipdg_affine_factor,
+                                                      V>(m,
+                                                         space_id + "Space__" + grid_id + "_" + layer_id + "_to_"
+                                                             + space_suffix,
+                                                         "istl_sparse",
+                                                         "Swipdg_Affine_Factor");
+  GDT::bind_elliptic_ipdg_dirichlet_vector_functional<ScalarFunction,
+                                                      ScalarFunction,
+                                                      void,
+                                                      S,
+                                                      GDT::LocalEllipticIpdgIntegrands::Method::swipdg_affine_factor,
+                                                      V>(m,
+                                                         space_id + "Space__" + grid_id + "_" + layer_id + "_to_"
+                                                             + space_suffix,
+                                                         "istl_sparse",
+                                                         "Swipdg_Affine_Factor");
+  // SWIPDG, affine wrt diffusion tensor
+  GDT::bind_elliptic_ipdg_dirichlet_vector_functional<ScalarFunction,
+                                                      ScalarFunction,
+                                                      TensorFunction,
+                                                      S,
+                                                      GDT::LocalEllipticIpdgIntegrands::Method::swipdg_affine_tensor,
+                                                      V>(m,
+                                                         space_id + "Space__" + grid_id + "_" + layer_id + "_to_"
+                                                             + space_suffix,
+                                                         "istl_sparse",
+                                                         "Swipdg_Affine_Tensor");
+  GDT::bind_elliptic_ipdg_dirichlet_vector_functional<ScalarFunction,
+                                                      ScalarFunction,
+                                                      void,
+                                                      S,
+                                                      GDT::LocalEllipticIpdgIntegrands::Method::swipdg_affine_tensor,
+                                                      V>(m,
+                                                         space_id + "Space__" + grid_id + "_" + layer_id + "_to_"
+                                                             + space_suffix,
+                                                         "istl_sparse",
+                                                         "Swipdg_Affine_Tensor");
+} // ... addbind_for_space(...)
+
+
+template <class G>
+void addbind_for_grid(py::module& m, const std::string& grid_id)
+{
+  using namespace Dune;
+  using namespace Dune::XT;
+  using namespace Dune::GDT;
+//  // FV
+//  addbind_for_space<FvSpaceProvider<G, XT::Grid::Layers::leaf, ChooseSpaceBackend::gdt, double, 1, 1>>(
+//      m, grid_id, "leaf", "Fv", "");
+//  addbind_for_space<FvSpaceProvider<G, XT::Grid::Layers::level, ChooseSpaceBackend::gdt, double, 1, 1>>(
+//      m, grid_id, "level", "Fv", "");
+// CG
+#if HAVE_DUNE_FEM
+  addbind_for_space<CgSpaceProvider<G, XT::Grid::Layers::leaf, ChooseSpaceBackend::fem, 1, double, 1, 1>>(
+      m, grid_id, "leaf", "Cg", "__fem");
+  addbind_for_space<CgSpaceProvider<G, XT::Grid::Layers::level, ChooseSpaceBackend::fem, 1, double, 1, 1>>(
+      m, grid_id, "level", "Cg", "__fem");
+#endif
+//#if HAVE_DUNE_PDELAB
+//  addbind_for_space<CgSpaceProvider<G, XT::Grid::Layers::leaf, ChooseSpaceBackend::pdelab, 1, double, 1, 1>>(
+//      m, grid_id, "leaf", "Cg", "__pdelab");
+//  addbind_for_space<CgSpaceProvider<G, XT::Grid::Layers::level, ChooseSpaceBackend::pdelab, 1, double, 1, 1>>(
+//      m, grid_id, "level", "Cg", "__pdelab");
+//#endif
+// DG
+#if HAVE_DUNE_FEM
+  addbind_for_space<DgSpaceProvider<G, XT::Grid::Layers::leaf, ChooseSpaceBackend::fem, 1, double, 1, 1>>(
+      m, grid_id, "leaf", "Dg", "__fem");
+  addbind_for_space<DgSpaceProvider<G, XT::Grid::Layers::level, ChooseSpaceBackend::fem, 1, double, 1, 1>>(
+      m, grid_id, "level", "Dg", "__fem");
+#endif
+  //#if HAVE_DUNE_PDELAB //                                            these need to be guarded against simplicial grids
+  //  addbind_for_space<DgSpaceProvider<G, XT::Grid::Layers::leaf, ChooseSpaceBackend::pdelab, 1, double, 1, 1>>(
+  //      m, grid_id, "leaf", "Dg", "__pdelab");
+  //  addbind_for_space<DgSpaceProvider<G, XT::Grid::Layers::level, ChooseSpaceBackend::pdelab, 1, double, 1, 1>>(
+  //      m, grid_id, "level", "Dg", "__pdelab");
+  //#endif
+  //// RT
+  //#if HAVE_DUNE_PDELAB //      enabling those leads to problems in bindings of the functionals and vectors, those need
+  //  addbind_for_space<RtSpaceProvider<G, //                                                     to be disabled for bad
+  //  dimensions
+  //                                    XT::Grid::Layers::leaf,
+  //                                    ChooseSpaceBackend::pdelab,
+  //                                    0,
+  //                                    double,
+  //                                    G::dimension,
+  //                                    1>>(m, grid_id, "leaf", "Rt", "__pdelab");
+  //  addbind_for_space<RtSpaceProvider<G, XT::Grid::Layers::level, ChooseSpaceBackend::pdelab, 0, double, G::dimension,
+  //  1>>(
+  //      m, grid_id, "level", "Rt", "__pdelab");
+  //#endif
+
+  typedef typename XT::Grid::Layer<G, XT::Grid::Layers::level, XT::Grid::Backends::view>::type LevelView;
+  typedef typename XT::Grid::Layer<G, XT::Grid::Layers::leaf, XT::Grid::Backends::view>::type LeafView;
+  typedef typename XT::Grid::Intersection<LeafView>::type FVI;
+  typedef typename XT::Grid::Intersection<LevelView>::type LVI;
+#if HAVE_DUNE_FEM
+  typedef typename XT::Grid::Layer<G, XT::Grid::Layers::level, XT::Grid::Backends::part>::type LevelPart;
+  typedef typename XT::Grid::Layer<G, XT::Grid::Layers::leaf, XT::Grid::Backends::part>::type LeafPart;
+  typedef typename XT::Grid::Intersection<LeafPart>::type FPI;
+  typedef typename XT::Grid::Intersection<LevelPart>::type LPI;
+#endif
+  for_Grid_and_Intersection<FVI, true>::template addbind<G>(m,
+                                                            grid_id,
+                                                            (std::is_same<FVI, LVI>::value
+#if HAVE_DUNE_FEM
+                                                             && std::is_same<FVI, FPI>::value
+                                                             && std::is_same<FVI, LPI>::value
+#endif
+                                                             )
+                                                                ? ""
+                                                                : "_leaf_view");
+  for_Grid_and_Intersection<LVI, !(std::is_same<LVI, FVI>::value)>::template addbind<G>(m, grid_id, "_level_view");
+#if HAVE_DUNE_FEM
+  for_Grid_and_Intersection<FPI,
+                            !(std::is_same<FPI, FVI>::value
+                              || std::is_same<FPI, LVI>::value)>::template addbind<G>(m, grid_id, "_leaf_part");
+  for_Grid_and_Intersection<LPI,
+                            !(std::is_same<LPI, FVI>::value || std::is_same<LPI, LVI>::value
+                              || std::is_same<LPI, FPI>::value)>::template addbind<G>(m, grid_id, "_level_part");
+#endif // HAVE_DUNE_FEM
+} // ... addbind_for_grid(...)
+
+
+PYBIND11_PLUGIN(_gdt)
+{
+  py::module m("_gdt", "dune-gdt");
+
+  py::module::import("dune.xt.common");
+  py::module::import("dune.xt.grid");
+  py::module::import("dune.xt.functions");
+  py::module::import("dune.xt.la");
+
+  m.def("init_mpi",
+        [](const std::vector<std::string>& args) {
+          int argc = boost::numeric_cast<int>(args.size());
+          char** argv = Dune::XT::Common::vector_to_main_args(args);
+#if HAVE_DUNE_FEM
+          Dune::Fem::MPIManager::initialize(argc, argv);
+#else
+          Dune::MPIHelper::instance(argc, argv);
+#endif
+        },
+        "args"_a = std::vector<std::string>());
+
+//  addbind_for_grid<Dune::YaspGrid<2, Dune::EquidistantOffsetCoordinates<double, 2>>>(m, "2d_cube_yaspgrid");
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+  addbind_for_grid<Dune::ALUGrid<2, 2, Dune::simplex, Dune::conforming>>(m, "2d_simplex_aluconform");
+#endif
+
+  m.def("init_logger",
+        [](const ssize_t max_info_level,
+           const ssize_t max_debug_level,
+           const bool enable_warnings,
+           const bool enable_colors,
+           const std::string& info_color,
+           const std::string& debug_color,
+           const std::string& warning_color) {
+          Dune::XT::Common::TimedLogger().create(
+              max_info_level, max_debug_level, enable_warnings, enable_colors, info_color, debug_color, warning_color);
+        },
+        "max_info_level"_a = -1,
+        "max_debug_level"_a = -1,
+        "enable_warnings"_a = true,
+        "enable_colors"_a = true,
+        "info_color"_a = "blue",
+        "debug_color"_a = "darkgray",
+        "warning_color"_a = "red");
+
+  return m.ptr();
+}
+
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/bindings.hh b/dune/gdt/bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..9eac5a3ec10f993eb63cba84f5efce942819129f
--- /dev/null
+++ b/dune/gdt/bindings.hh
@@ -0,0 +1,22 @@
+#ifndef DUNE_GDT_BINDINGS_HH
+#define DUNE_GDT_BINDINGS_HH
+
+#include <dune/xt/grid/grids.bindings.hh>
+#include <dune/xt/la/container.bindings.hh>
+
+#include <dune/gdt/assembler/system.bindings.hh>
+#include <dune/gdt/discretefunction/default.bindings.hh>
+#include <dune/gdt/operators/elliptic.bindings.hh>
+#include <dune/gdt/operators/elliptic-ipdg.bindings.hh>
+#include <dune/gdt/projections/dirichlet.bindings.hh>
+#include <dune/gdt/spaces.bindings.hh>
+#include <dune/gdt/spaces/constraints.bindings.hh>
+
+namespace Dune {
+namespace GDT {
+
+
+} // namespace GDT
+} // namespace Dune
+
+#endif // DUNE_GDT_BINDINGS_HH
diff --git a/dune/gdt/discretefunction/default.bindings.cc b/dune/gdt/discretefunction/default.bindings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7d09001cb9238bb4bcb2b3747757631de8401866
--- /dev/null
+++ b/dune/gdt/discretefunction/default.bindings.cc
@@ -0,0 +1,72 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "default.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_FEM
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_PDELAB
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_FEM
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/discretefunction/default.bindings.hh b/dune/gdt/discretefunction/default.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..31809ab5ec0b6d92397d68205610f7087ebe30e1
--- /dev/null
+++ b/dune/gdt/discretefunction/default.bindings.hh
@@ -0,0 +1,233 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BINDINGS_HH
+#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include <dune/xt/grid/grids.bindings.hh>
+#include <dune/xt/la/type_traits.hh>
+#include <dune/xt/la/container.bindings.hh>
+
+#include <dune/gdt/type_traits.hh>
+#include <dune/gdt/spaces.bindings.hh>
+
+#include "default.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+template <class S, class V>
+class ConstDiscreteFunction
+{
+  static_assert(is_space<S>::value, "");
+  static_assert(XT::LA::is_vector<V>::value, "");
+
+public:
+  typedef GDT::ConstDiscreteFunction<S, V> type;
+
+private:
+  typedef XT::Functions::LocalizableFunctionInterface<typename S::EntityType,
+                                                      typename S::DomainFieldType,
+                                                      S::dimDomain,
+                                                      typename S::RangeFieldType,
+                                                      S::dimRange,
+                                                      S::dimRangeCols>
+      BaseType;
+
+public:
+  typedef pybind11::class_<type, BaseType> bound_type;
+
+  static bound_type bind(pybind11::module& m, const std::string& space_id, const std::string& la_id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    bound_type c(m, std::string("ConstDiscreteFunction__" + space_id + "__" + la_id).c_str());
+    c.def(py::init<const S&, V&, const std::string>(),
+          "space"_a,
+          "vector"_a,
+          "name"_a = "gdt.constdiscretefunction",
+          py::keep_alive<1, 2>(),
+          py::keep_alive<1, 3>());
+    c.def("space", [](type& self) { return self.space(); });
+    c.def("vector", [](type& self) { return self.vector(); });
+    c.def("visualize",
+          [](type& self, const std::string filename, const bool subsampling) {
+            return self.visualize(filename, subsampling);
+          },
+          "filename"_a,
+          "subsampling"_a = (S::polOrder > 1));
+
+    m.def(std::string("make_const_discrete_function").c_str(),
+          [](const S& space, V& vector, const std::string& name) {
+            return make_const_discrete_function(space, vector, name);
+          },
+          "space"_a,
+          "vector"_a,
+          "name"_a = "gdt.constdiscretefunction",
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>());
+
+    return c;
+  } // ... bind(...)
+}; // class ConstDiscreteFunction
+
+
+template <class S, class V>
+class DiscreteFunction
+{
+  static_assert(is_space<S>::value, "");
+  static_assert(XT::LA::is_vector<V>::value, "");
+
+public:
+  typedef GDT::DiscreteFunction<S, V> type;
+
+private:
+  typedef XT::Functions::LocalizableFunctionInterface<typename S::EntityType,
+                                                      typename S::DomainFieldType,
+                                                      S::dimDomain,
+                                                      typename S::RangeFieldType,
+                                                      S::dimRange,
+                                                      S::dimRangeCols>
+      BaseType;
+
+public:
+  typedef pybind11::class_<type, BaseType> bound_type;
+
+  static bound_type bind(pybind11::module& m, const std::string& space_id, const std::string& la_id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    bound_type c(m, std::string("DiscreteFunction__" + space_id + "__" + la_id).c_str());
+    c.def(py::init<const S&, V&, const std::string>(),
+          "space"_a,
+          "vector"_a,
+          "name"_a = "gdt.discretefunction",
+          py::keep_alive<1, 2>(),
+          py::keep_alive<1, 3>());
+    c.def("space", [](type& self) { return self.space(); });
+    c.def("vector", [](type& self) { return self.vector(); });
+    c.def("visualize",
+          [](type& self, const std::string filename, const bool subsampling) {
+            return self.visualize(filename, subsampling);
+          },
+          "filename"_a,
+          "subsampling"_a = (S::polOrder > 1));
+
+    m.def(
+        std::string("make_discrete_function").c_str(),
+        [](const S& space, V& vector, const std::string& name) { return make_discrete_function(space, vector, name); },
+        "space"_a,
+        "vector"_a,
+        "name"_a = "gdt.discretefunction",
+        py::keep_alive<0, 1>(),
+        py::keep_alive<0, 2>());
+
+    return c;
+  } // ... bind(...)
+
+}; // class DiscreteFunction
+
+
+#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(_prefix, _GRID, _LA)                                                \
+  _prefix class ConstDiscreteFunction<FV_SPACE(_GRID, leaf, gdt, 1, 1), _LA>;                                          \
+  _prefix class ConstDiscreteFunction<FV_SPACE(_GRID, level, gdt, 1, 1), _LA>;                                         \
+  _prefix class DiscreteFunction<FV_SPACE(_GRID, leaf, gdt, 1, 1), _LA>;                                               \
+  _prefix class DiscreteFunction<FV_SPACE(_GRID, level, gdt, 1, 1), _LA>
+
+#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(_prefix, _GRID, _LA)                                                \
+  _prefix class ConstDiscreteFunction<CG_SPACE(_GRID, leaf, fem, 1, 1, 1), _LA>;                                       \
+  _prefix class ConstDiscreteFunction<CG_SPACE(_GRID, level, fem, 1, 1, 1), _LA>;                                      \
+  _prefix class ConstDiscreteFunction<DG_SPACE(_GRID, leaf, fem, 1, 1, 1), _LA>;                                       \
+  _prefix class ConstDiscreteFunction<DG_SPACE(_GRID, level, fem, 1, 1, 1), _LA>;                                      \
+  _prefix class ConstDiscreteFunction<DG_SPACE(_GRID, leaf, fem, 2, 1, 1), _LA>;                                       \
+  _prefix class ConstDiscreteFunction<DG_SPACE(_GRID, level, fem, 2, 1, 1), _LA>;                                      \
+  _prefix class DiscreteFunction<CG_SPACE(_GRID, leaf, fem, 1, 1, 1), _LA>;                                            \
+  _prefix class DiscreteFunction<CG_SPACE(_GRID, level, fem, 1, 1, 1), _LA>;                                           \
+  _prefix class DiscreteFunction<DG_SPACE(_GRID, leaf, fem, 1, 1, 1), _LA>;                                            \
+  _prefix class DiscreteFunction<DG_SPACE(_GRID, level, fem, 1, 1, 1), _LA>;                                           \
+  _prefix class DiscreteFunction<DG_SPACE(_GRID, leaf, fem, 2, 1, 1), _LA>;                                            \
+  _prefix class DiscreteFunction<DG_SPACE(_GRID, level, fem, 2, 1, 1), _LA>
+
+
+#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(_prefix, _GRID, _LA)                                             \
+  _prefix class ConstDiscreteFunction<CG_SPACE(_GRID, leaf, pdelab, 1, 1, 1), _LA>;                                    \
+  _prefix class ConstDiscreteFunction<CG_SPACE(_GRID, level, pdelab, 1, 1, 1), _LA>;                                   \
+  _prefix class DiscreteFunction<CG_SPACE(_GRID, leaf, pdelab, 1, 1, 1), _LA>;                                         \
+  _prefix class DiscreteFunction<CG_SPACE(_GRID, level, pdelab, 1, 1, 1), _LA>
+
+
+// these lines have to match the corresponding ones in the .cc source file
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(extern template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(extern template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(extern template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_FEM
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_PDELAB
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(extern template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(extern template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_GDT(extern template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_FEM
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BINDINGS_HH
diff --git a/dune/gdt/functionals/base.pbh b/dune/gdt/functionals/base.pbh
new file mode 100644
index 0000000000000000000000000000000000000000..9694039fad490b824734a068c5f5b0b5d1f632b0
--- /dev/null
+++ b/dune/gdt/functionals/base.pbh
@@ -0,0 +1,52 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_FUNCTIONALS_BASE_PBH
+#define DUNE_GDT_FUNCTIONALS_BASE_PBH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include <dune/xt/la/container.hh>
+
+#include "base.hh"
+
+namespace Dune {
+namespace GDT {
+
+
+template <class FunctionalType>
+pybind11::class_<FunctionalType,
+                 SystemAssembler<typename FunctionalType::SpaceType, typename FunctionalType::GridViewType>>
+bind_vector_functional(pybind11::module& m, const std::string& class_id)
+{
+  namespace py = pybind11;
+  using namespace pybind11::literals;
+
+  typedef FunctionalType C;
+  typedef typename C::SpaceType S;
+  typedef SystemAssembler<typename FunctionalType::SpaceType, typename FunctionalType::GridViewType> I;
+  typedef typename C::VectorType V;
+
+  py::class_<C, I> c(m, std::string(class_id).c_str(), std::string(class_id).c_str());
+
+  c.def("vector", [](C& self) { return self.vector(); });
+  c.def("space", [](C& self) { return self.space(); });
+  c.def("apply", [](C& self, const V& source) { return self.apply(source); }, "source"_a);
+  c.def("apply", [](C& self, const ConstDiscreteFunction<S, V>& source) { return self.apply(source); }, "source"_a);
+
+  return c;
+} // ... bind_vector_functional(...)
+
+
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_FUNCTIONALS_BASE_PBH
diff --git a/dune/gdt/functionals/elliptic-ipdg.pbh b/dune/gdt/functionals/elliptic-ipdg.pbh
new file mode 100644
index 0000000000000000000000000000000000000000..1a7d392b088ef0cc845c3cd034603cd24351395e
--- /dev/null
+++ b/dune/gdt/functionals/elliptic-ipdg.pbh
@@ -0,0 +1,196 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_FUNCTIONALS_ELLIPTIC_IPDG_PBH
+#define DUNE_GDT_FUNCTIONALS_ELLIPTIC_IPDG_PBH
+//#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include "elliptic-ipdg.hh"
+#include "base.pbh"
+
+namespace Dune {
+namespace GDT {
+namespace internal {
+
+
+template <class DI, class DF, typename DT, LocalEllipticIpdgIntegrands::Method ipdg_method>
+struct elliptic_ipdg_dirichlet_vector_functional_bind_helper
+{
+  static std::string suffix()
+  {
+    return "diffusion_factor_and_tensor";
+  }
+
+  template <class C>
+  static void addbind_factory_methods(pybind11::module& m, const std::string& method_id, const std::string& la_id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    typedef typename C::SpaceType S;
+    typedef typename C::VectorType V;
+
+    m.def(std::string(method_id + "__" + la_id).c_str(),
+          [](const DI& dirichlet,
+             const DF& diffusion_factor,
+             const DT& diffusion_tensor,
+             const XT::Grid::BoundaryInfo<typename S::GridViewType::Intersection>& boundary_info,
+             const S& space,
+             const size_t over_integrate) {
+            return make_elliptic_ipdg_dirichlet_vector_functional<V, ipdg_method>(
+                       dirichlet, diffusion_factor, diffusion_tensor, boundary_info, space, over_integrate)
+                .release(); //   <- b.c. EllipticIpdgDirichletVectorFunctional is not movable, returning the raw pointer
+          }, //                                                                lets pybind11 correctly manage the memory
+          "dirichlet"_a,
+          "diffusion_factor"_a,
+          "diffusion_tensor"_a,
+          "boundary_info"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>(),
+          py::keep_alive<0, 4>(),
+          py::keep_alive<0, 5>());
+
+    m.def(std::string(method_id).c_str(),
+          [](const DI& dirichlet,
+             const DF& diffusion_factor,
+             const DT& diffusion_tensor,
+             const XT::Grid::BoundaryInfo<typename S::GridViewType::Intersection>& boundary_info,
+             V& vector,
+             const S& space,
+             const size_t over_integrate) {
+            return make_elliptic_ipdg_dirichlet_vector_functional<ipdg_method>(
+                       dirichlet, diffusion_factor, diffusion_tensor, boundary_info, vector, space, over_integrate)
+                .release(); //                                                                     <- s.a. for release()
+          },
+          "dirichlet"_a,
+          "diffusion_factor"_a,
+          "diffusion_tensor"_a,
+          "boundary_info"_a,
+          "vector"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>(),
+          py::keep_alive<0, 4>(),
+          py::keep_alive<0, 5>(),
+          py::keep_alive<0, 6>());
+  } // ... addbind_factory_methods(...)
+}; // struct elliptic_ipdg_dirichlet_vector_functional_bind_helper
+
+
+template <class DI, class D, LocalEllipticIpdgIntegrands::Method ipdg_method>
+struct elliptic_ipdg_dirichlet_vector_functional_bind_helper<DI, D, void, ipdg_method>
+{
+  static std::string suffix()
+  {
+    return "single_diffusion";
+  }
+
+  template <class C>
+  static void addbind_factory_methods(pybind11::module& m, const std::string& method_id, const std::string& la_id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    typedef typename C::SpaceType S;
+    typedef typename C::VectorType V;
+
+    m.def(std::string(method_id + "__" + la_id).c_str(),
+          [](const DI& dirichlet,
+             const D& diffusion,
+             const XT::Grid::BoundaryInfo<typename S::GridViewType::Intersection>& boundary_info,
+             const S& space,
+             const size_t over_integrate) {
+            return make_elliptic_ipdg_dirichlet_vector_functional<V, ipdg_method>(
+                       dirichlet, diffusion, boundary_info, space, over_integrate)
+                .release(); //   <- b.c. EllipticIpdgDirichletVectorFunctional is not movable, returning the raw pointer
+          }, //                                                                lets pybind11 correctly manage the memory
+          "dirichlet"_a,
+          "diffusion"_a,
+          "boundary_info"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>(),
+          py::keep_alive<0, 4>());
+
+    m.def(std::string(method_id).c_str(),
+          [](const DI& dirichlet,
+             const D& diffusion,
+             const XT::Grid::BoundaryInfo<typename S::GridViewType::Intersection>& boundary_info,
+             V& vector,
+             const S& space,
+             const size_t over_integrate) {
+            return make_elliptic_ipdg_dirichlet_vector_functional<ipdg_method>(
+                       dirichlet, diffusion, boundary_info, vector, space, over_integrate)
+                .release(); //                                                                     <- s.a. for release()
+          },
+          "dirichlet"_a,
+          "diffusion"_a,
+          "boundary_info"_a,
+          "vector"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>(),
+          py::keep_alive<0, 4>(),
+          py::keep_alive<0, 5>());
+  } // ... addbind_factory_methods(...)
+}; // struct elliptic_ipdg_dirichlet_vector_functional_bind_helper
+
+
+} // namespace internal
+
+template <class DI,
+          class DF,
+          class DT, // <- may be void
+          class S,
+          LocalEllipticIpdgIntegrands::Method method = LocalEllipticIpdgIntegrands::default_method,
+          class V = typename XT::LA::Container<typename S::RangeFieldType>::VectorType,
+          class GV = typename S::GridViewType,
+          class F = typename S::RangeFieldType>
+pybind11::class_<EllipticIpdgDirichletVectorFunctional<DI, DF, DT, S, method, V, GV, F>>
+bind_elliptic_ipdg_dirichlet_vector_functional(pybind11::module& m,
+                                               const std::string& space_id,
+                                               const std::string& la_id,
+                                               const std::string& method_id)
+{
+  static_assert(std::is_same<GV, typename S::GridViewType>::value, "Not tested yet!");
+
+  namespace py = pybind11;
+  using namespace pybind11::literals;
+
+  typedef EllipticIpdgDirichletVectorFunctional<DI, DF, DT, S, method, V, GV, F> C;
+  const std::string suffix =
+      la_id + "__" + space_id + "_"
+      + internal::elliptic_ipdg_dirichlet_vector_functional_bind_helper<DI, DF, DT, method>::suffix();
+
+  auto c = bind_vector_functional<C>(m, "Elliptic" + method_id + "DirichletVectorFunctional__" + suffix);
+
+  internal::elliptic_ipdg_dirichlet_vector_functional_bind_helper<DI, DF, DT, method>::
+      template addbind_factory_methods<C>(
+          m, "make_elliptic_" + XT::Common::to_lower(method_id) + "_dirichlet_vector_functional", la_id);
+
+  return c;
+} // ... bind_elliptic_ipdg_dirichlet_vector_functional(...)
+
+
+} // namespace GDT
+} // namespace Dune
+
+//#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_FUNCTIONALS_ELLIPTIC_IPDG_PBH
diff --git a/dune/gdt/functionals/l2.pbh b/dune/gdt/functionals/l2.pbh
new file mode 100644
index 0000000000000000000000000000000000000000..610d647162431033cf94c611e733f3f01d7a96bc
--- /dev/null
+++ b/dune/gdt/functionals/l2.pbh
@@ -0,0 +1,145 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_FUNCTIONALS_L2_PBH
+#define DUNE_GDT_FUNCTIONALS_L2_PBH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include "l2.hh"
+#include "base.pbh"
+
+namespace Dune {
+namespace GDT {
+
+
+template <class FunctionType,
+          class Space,
+          class Vector = typename XT::LA::Container<typename Space::RangeFieldType>::VectorType,
+          class GridView = typename Space::GridViewType,
+          class Field = typename Space::RangeFieldType>
+pybind11::class_<L2VolumeVectorFunctional<FunctionType, Space, Vector, GridView, Field>>
+bind_l2_volume_vector_functional(pybind11::module& m, const std::string& space_id, const std::string& la_id)
+{
+  static_assert(std::is_same<GridView, typename Space::GridViewType>::value, "Not tested yet!");
+
+  namespace py = pybind11;
+  using namespace pybind11::literals;
+
+  typedef L2VolumeVectorFunctional<FunctionType, Space, Vector, GridView, Field> C;
+
+  auto c = bind_vector_functional<C>(m, "L2VolumeVectorFunctional__" + la_id + "__" + space_id);
+
+  m.def(std::string("make_l2_volume_vector_functional__" + la_id).c_str(),
+        [](const FunctionType& function, const Space& space, const size_t over_integrate) {
+          return make_l2_volume_vector_functional<Vector>(function, space, over_integrate).release(); // b.c.
+        }, //      L2VolumeVectorFunctional is not movable, returning the raw pointer lets pybind11 correctly
+        "function"_a, //                                                                    manage the memory
+        "space"_a,
+        "over_integrate"_a = 0,
+        py::keep_alive<0, 1>(),
+        py::keep_alive<0, 2>());
+
+  m.def("make_l2_volume_vector_functional",
+        [](const FunctionType& function, Vector& vector, const Space& space, const size_t over_integrate) {
+          return make_l2_volume_vector_functional(function, vector, space, over_integrate).release(); // s.a.
+        },
+        "function"_a,
+        "vector"_a,
+        "space"_a,
+        "over_integrate"_a = 0,
+        py::keep_alive<0, 1>(),
+        py::keep_alive<0, 2>(),
+        py::keep_alive<0, 3>());
+
+  return c;
+
+} // ... bind_l2_volume_vector_functional(...)
+
+
+template <class FunctionType,
+          class Space,
+          class Vector = typename XT::LA::Container<typename Space::RangeFieldType>::VectorType,
+          class GridView = typename Space::GridViewType,
+          class Field = typename Space::RangeFieldType>
+pybind11::class_<L2FaceVectorFunctional<FunctionType, Space, Vector, GridView, Field>>
+bind_l2_face_vector_functional(pybind11::module& m, const std::string& space_id, const std::string& la_id)
+{
+  static_assert(std::is_same<GridView, typename Space::GridViewType>::value, "Not tested yet!");
+
+  namespace py = pybind11;
+  using namespace pybind11::literals;
+
+  typedef L2FaceVectorFunctional<FunctionType, Space, Vector, GridView, Field> C;
+
+  auto c = bind_vector_functional<C>(m, "L2FaceVectorFunctional__" + la_id + "__" + space_id);
+
+  m.def(std::string("make_l2_face_vector_functional__" + la_id).c_str(),
+        [](const FunctionType& function, const Space& space, const size_t over_integrate) {
+          return make_l2_face_vector_functional<Vector>(function, space, over_integrate).release(); // b.c.
+        }, //      L2FaceVectorFunctional is not movable, returning the raw pointer lets pybind11 correctly
+        "function"_a, //                                                                    manage the memory
+        "space"_a,
+        "over_integrate"_a = 0,
+        py::keep_alive<0, 1>(),
+        py::keep_alive<0, 2>());
+  m.def(std::string("make_l2_face_vector_functional__" + la_id).c_str(),
+        [](const FunctionType& function,
+           const Space& space,
+           const XT::Grid::ApplyOn::WhichIntersection<GridView>& which_intersections,
+           const size_t over_integrate) {
+          return make_l2_face_vector_functional<Vector>(function, space, over_integrate, which_intersections.copy())
+              .release(); // b.c.
+        }, //      L2FaceVectorFunctional is not movable, returning the raw pointer lets pybind11 correctly
+        "function"_a, //                                                                    manage the memory
+        "space"_a,
+        "which_intersections"_a,
+        "over_integrate"_a = 0,
+        py::keep_alive<0, 1>(),
+        py::keep_alive<0, 2>());
+
+  m.def("make_l2_face_vector_functional",
+        [](const FunctionType& function, Vector& vector, const Space& space, const size_t over_integrate) {
+          return make_l2_face_vector_functional(function, vector, space, over_integrate).release(); // s.a.
+        },
+        "function"_a,
+        "vector"_a,
+        "space"_a,
+        "over_integrate"_a = 0,
+        py::keep_alive<0, 1>(),
+        py::keep_alive<0, 2>(),
+        py::keep_alive<0, 3>());
+  m.def("make_l2_face_vector_functional",
+        [](const FunctionType& function,
+           Vector& vector,
+           const Space& space,
+           const XT::Grid::ApplyOn::WhichIntersection<GridView>& which_intersections,
+           const size_t over_integrate) {
+          return make_l2_face_vector_functional(function, vector, space, over_integrate, which_intersections.copy())
+              .release(); // s.a.
+        },
+        "function"_a,
+        "vector"_a,
+        "space"_a,
+        "which_intersections"_a,
+        "over_integrate"_a = 0,
+        py::keep_alive<0, 1>(),
+        py::keep_alive<0, 2>(),
+        py::keep_alive<0, 3>());
+
+  return c;
+} // ... bind_l2_face_vector_functional(...)
+
+
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_FUNCTIONALS_L2_PBH
diff --git a/dune/gdt/operators/base.bindings.hh b/dune/gdt/operators/base.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..d5ea88f88c65abdff35f2a82d90bea6aa666a493
--- /dev/null
+++ b/dune/gdt/operators/base.bindings.hh
@@ -0,0 +1,134 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_OPERATORS_BASE_BINDINGS_HH
+#define DUNE_GDT_OPERATORS_BASE_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include <dune/xt/la/container.hh>
+
+#include <dune/gdt/type_traits.hh>
+
+#include "base.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+template <class OperatorType>
+class MatrixOperatorBase
+{
+  static_assert(is_matrix_operator<OperatorType>::value, "");
+
+public:
+  typedef OperatorType type;
+  typedef GDT::SystemAssembler<typename OperatorType::RangeSpaceType,
+                               typename OperatorType::GridViewType,
+                               typename OperatorType::SourceSpaceType>
+      BaseType;
+  typedef pybind11::class_<type, BaseType> bound_type;
+
+  static bound_type bind(pybind11::module& m, const std::string& class_id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    typedef typename type::RangeSpaceType R;
+    typedef typename type::SourceSpaceType S;
+    typedef typename XT::LA::Container<typename type::RangeFieldType, type::MatrixType::vector_type>::VectorType V;
+
+    bound_type c(m, std::string(class_id).c_str(), std::string(class_id).c_str());
+
+    // from MatrixOperatorBase
+    c.def_static("pattern", [](const R& space) { return type::pattern(space); });
+
+    c.def("pattern", [](type& self) { return self.pattern(self.range_space()); });
+    c.def("matrix", [](type& self) { return self.matrix(); });
+    c.def("source_space", [](type& self) { return self.source_space(); });
+    c.def("range_space", [](type& self) { return self.range_space(); });
+    c.def("apply", [](type& self, const V& source, V& range) { self.apply(source, range); }, "source"_a, "range"_a);
+    c.def("apply",
+          [](type& self, const GDT::ConstDiscreteFunction<S, V>& source, GDT::DiscreteFunction<R, V>& range) {
+            self.apply(source, range);
+          },
+          "source"_a,
+          "range"_a);
+    c.def("apply2",
+          [](type& self, const V& range, const V& source) { return self.apply2(range, source); },
+          "range"_a,
+          "source"_a);
+    c.def("apply2",
+          [](type& self,
+             const GDT::ConstDiscreteFunction<R, V>& range,
+             const GDT::ConstDiscreteFunction<S, V>& source) { return self.apply2(range, source); },
+          "range"_a,
+          "source"_a);
+    c.def("apply_inverse",
+          [](type& self, const V& range, V& source, const XT::Common::Configuration& opts) {
+            self.apply_inverse(range, source, opts);
+          },
+          "range"_a,
+          "source"_a,
+          "opts"_a);
+    c.def("apply_inverse",
+          [](type& self,
+             const GDT::ConstDiscreteFunction<R, V>& range,
+             GDT::ConstDiscreteFunction<S, V>& source,
+             const XT::Common::Configuration& opts) { self.apply_inverse(range, source, opts); },
+          "range"_a,
+          "source"_a,
+          "opts"_a);
+    c.def("invert_options", [](type& self) { return self.invert_options(); });
+    c.def("invert_options", [](type& self, const std::string& type) { return self.invert_options(type); }, "type"_a);
+
+    // from OperatorInterface
+    c.def(
+        "apply_inverse",
+        [](type& self, const V& range, V& source, const std::string& type) { self.apply_inverse(range, source, type); },
+        "range"_a,
+        "source"_a,
+        "type"_a);
+    c.def("apply_inverse",
+          [](type& self,
+             const GDT::ConstDiscreteFunction<R, V>& range,
+             GDT::ConstDiscreteFunction<S, V>& source,
+             const std::string& type) { self.apply_inverse(range, source, type); },
+          "range"_a,
+          "source"_a,
+          "type"_a);
+    c.def("apply_inverse",
+          [](type& self, const V& range, V& source) { self.apply_inverse(range, source); },
+          "range"_a,
+          "source"_a);
+    c.def("apply_inverse",
+          [](type& self, const GDT::ConstDiscreteFunction<R, V>& range, GDT::ConstDiscreteFunction<S, V>& source) {
+            self.apply_inverse(range, source);
+          },
+          "range"_a,
+          "source"_a);
+    c.def("induced_norm", [](type& self, const V& range) { return self.induced_norm(range); }, "range"_a);
+    c.def("induced_norm",
+          [](type& self, const GDT::ConstDiscreteFunction<R, V>& range) { return self.induced_norm(range); },
+          "range"_a);
+
+    return c;
+  } // ... bind(...)
+
+}; // class MatrixOperatorBase
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_OPERATORS_BASE_BINDINGS_HH
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings.hh b/dune/gdt/operators/elliptic-ipdg.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..fb14a063c0a133b580e8f682948607781b711e0c
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings.hh
@@ -0,0 +1,319 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BINDINGS_HH
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include <dune/xt/common/string.hh>
+#include <dune/xt/grid/grids.bindings.hh>
+
+#include <dune/gdt/spaces.bindings.hh>
+
+#include "elliptic-ipdg.hh"
+#include "base.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+template <class DF,
+          typename DT, // may be void
+          class R,
+          LocalEllipticIpdgIntegrands::Method method,
+          class M = typename XT::LA::Container<typename R::RangeFieldType>::MatrixType /*,
+          class GV = typename R::GridViewType,
+          class S = R,
+          class F = typename R::RangeFieldType*/>
+class EllipticIpdgMatrixOperator
+{
+public:
+  typedef GDT::EllipticIpdgMatrixOperator<DF, DT, R, method, M /*, GV, S, F*/> type;
+  typedef pybind11::class_<type> bound_type;
+
+private:
+  template <bool single_diffusion = std::is_same<DT, void>::value, bool anything = false>
+  struct diffusion_switch
+  {
+    static std::string suffix()
+    {
+      return "diffusion_factor_and_tensor";
+    }
+
+    template <class C>
+    static void addbind_factory_methods(pybind11::module& m, const std::string& method_id, const std::string& la_id)
+    {
+      namespace py = pybind11;
+      using namespace pybind11::literals;
+
+      m.def(
+          std::string(method_id + "__" + la_id).c_str(),
+          [](const DF& diffusion_factor,
+             const DT& diffusion_tensor,
+             const XT::Grid::BoundaryInfo<typename R::GridViewType::Intersection>& boundary_info,
+             const R& space,
+             const size_t over_integrate) {
+            return make_elliptic_ipdg_matrix_operator<M, method>(
+                       diffusion_factor, diffusion_tensor, boundary_info, space, over_integrate)
+                .release(); //         <- b.c. EllipticIpdgMatrixOperator is not movable, returning the raw pointer lets
+          }, //                                                                     pybind11 correctly manage the memory
+          "diffusion_factor"_a,
+          "diffusion_tensor"_a,
+          "boundary_info"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>(),
+          py::keep_alive<0, 4>());
+
+      m.def(
+          std::string(method_id).c_str(),
+          [](const DF& diffusion_factor,
+             const DT& diffusion_tensor,
+             const XT::Grid::BoundaryInfo<typename R::GridViewType::Intersection>& boundary_info,
+             M& matrix,
+             const R& space,
+             const size_t over_integrate) {
+            return make_elliptic_ipdg_matrix_operator<method>(
+                       diffusion_factor, diffusion_tensor, boundary_info, matrix, space, over_integrate)
+                .release(); //                                                                     <- s.a. for release()
+          },
+          "diffusion_factor"_a,
+          "diffusion_tensor"_a,
+          "boundary_info"_a,
+          "matrix"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>(),
+          py::keep_alive<0, 4>(),
+          py::keep_alive<0, 5>());
+    } // ... addbind_factory_methods(...)
+
+  }; // struct diffusion_switch
+
+  template <bool anything>
+  struct diffusion_switch<true, anything>
+  {
+    static std::string suffix()
+    {
+      return "single_diffusion";
+    }
+
+    template <class C>
+    static void addbind_factory_methods(pybind11::module& m, const std::string& method_id, const std::string& la_id)
+    {
+      namespace py = pybind11;
+      using namespace pybind11::literals;
+
+      m.def(
+          std::string(method_id + "__" + la_id).c_str(),
+          [](const DF& diffusion,
+             const XT::Grid::BoundaryInfo<typename R::GridViewType::Intersection>& boundary_info,
+             const R& space,
+             const size_t over_integrate) {
+            return make_elliptic_ipdg_matrix_operator<M, method>(diffusion, boundary_info, space, over_integrate)
+                .release(); //                                                                     <- s.a. for release()
+          },
+          "diffusion"_a,
+          "boundary_info"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>());
+
+      m.def(
+          std::string(method_id).c_str(),
+          [](const DF& diffusion,
+             const XT::Grid::BoundaryInfo<typename R::GridViewType::Intersection>& boundary_info,
+             M& matrix,
+             const R& space,
+             const size_t over_integrate) {
+            return make_elliptic_ipdg_matrix_operator<method>(diffusion, boundary_info, matrix, space, over_integrate)
+                .release(); //                                                                     <- s.a. for release()
+          },
+          "diffusion"_a,
+          "boundary_info"_a,
+          "matrix"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>(),
+          py::keep_alive<0, 4>());
+    } // ... addbind_factory_methods(...)
+  }; // struct diffusion_switch<..., void>
+
+public:
+  static bound_type
+  bind(pybind11::module& m, const std::string& space_id, const std::string& la_id, const std::string& method_id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    const std::string suffix = la_id + "__" + space_id + "_" + diffusion_switch<>::suffix();
+
+    auto c = MatrixOperatorBase<type>::bind(m, "Elliptic" + method_id + "MatrixOperator__" + suffix);
+
+    diffusion_switch<>::template addbind_factory_methods<type>(
+        m, "make_elliptic_" + XT::Common::to_lower(method_id) + "_matrix_operator", la_id);
+
+    return c;
+  } // ... bind(...)
+
+}; // EllipticIpdgMatrixOperator
+
+
+// If everyone just had enough memory, we could just use a single line
+//     DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND(template);
+// in a source file to instantiate everything (together with
+//     DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND(extern template);
+// in this header. Alas, we can use the latter in this header, but need to distribute the load over several sources by
+// using the specialized macros below...
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic" // because of the extra ; in some places
+#endif
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND(_PRE)                                                                    \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_YASPGRID(_PRE);                                                                \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_ALUGRID(_PRE)
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_YASPGRID(_PRE)                                                           \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_LA(_PRE, YASP_2D_EQUIDISTANT_OFFSET)
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_ALUGRID(_PRE)                                                            \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_LA(_PRE, ALU_2D_SIMPLEX_CONFORMING)
+#else
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_ALUGRID(_PRE)
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_LA(_PRE, _GRID)                                                          \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_COMMON(_PRE, _GRID);                                                           \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_EIGEN(_PRE, _GRID);                                                            \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_ISTL(_PRE, _GRID)
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_COMMON(_PRE, _GRID)                                                      \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(_PRE, _GRID, common_dense);                                                \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(_PRE, _GRID, common_dense);                                                \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(_PRE, _GRID, common_dense)
+
+#if HAVE_EIGEN
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_EIGEN(_PRE, _GRID)                                                       \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(_PRE, _GRID, eigen_dense);                                                 \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(_PRE, _GRID, eigen_sparse);                                                \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(_PRE, _GRID, eigen_dense);                                                 \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(_PRE, _GRID, eigen_sparse);                                                \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(_PRE, _GRID, eigen_dense);                                              \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(_PRE, _GRID, eigen_sparse)
+#else
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_EIGEN(_PRE, _GRID)
+#endif
+
+#if HAVE_DUNE_ISTL
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_ISTL(_PRE, _GRID)                                                        \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(_PRE, _GRID, istl_dense);                                                  \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(_PRE, _GRID, istl_dense);                                                  \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(_PRE, _GRID, istl_dense)
+#else
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_ISTL(_PRE, _GRID)
+#endif
+
+#if HAVE_DUNE_FEM
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(_PRE, _GRID, _LA)                                                    \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, CG_SPACE(_GRID, leaf, fem, 1, 1, 1), _LA);                       \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, CG_SPACE(_GRID, level, fem, 1, 1, 1), _LA);                      \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, DG_SPACE(_GRID, leaf, fem, 1, 1, 1), _LA);                       \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, DG_SPACE(_GRID, level, fem, 1, 1, 1), _LA);                      \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, DG_SPACE(_GRID, leaf, fem, 2, 1, 1), _LA);                       \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, DG_SPACE(_GRID, level, fem, 2, 1, 1), _LA)
+#else // HAVE_DUNE_FEM
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(_PRE, _GRID)
+#endif
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(_PRE, _GRID, _LA)                                                    \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, FV_SPACE(_GRID, leaf, gdt, 1, 1), _LA);                          \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, FV_SPACE(_GRID, level, gdt, 1, 1), _LA)
+
+#if HAVE_DUNE_PDELAB
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(_PRE, _GRID, _LA)                                                 \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, CG_SPACE(_GRID, leaf, pdelab, 1, 1, 1), _LA);                    \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, CG_SPACE(_GRID, level, pdelab, 1, 1, 1), _LA)
+#else
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(_PRE, _GRID, _LA)
+#endif
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_METHODS(_PRE, _SPACE, _LA)                                               \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_(_PRE, _SPACE, sipdg, _LA);                                                    \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_(_PRE, _SPACE, swipdg, _LA);                                                   \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_(_PRE, _SPACE, swipdg_affine_factor, _LA);                                     \
+  DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_(_PRE, _SPACE, swipdg_affine_tensor, _LA)
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_(_PRE, _SPACE, _METHOD, _LA)                                             \
+  _PRE class EllipticIpdgMatrixOperator<XT::Functions::LocalizableFunctionInterface<typename _SPACE::EntityType,       \
+                                                                                    typename _SPACE::DomainFieldType,  \
+                                                                                    _SPACE::dimDomain,                 \
+                                                                                    typename _SPACE::RangeFieldType,   \
+                                                                                    1,                                 \
+                                                                                    1>,                                \
+                                        XT::Functions::LocalizableFunctionInterface<typename _SPACE::EntityType,       \
+                                                                                    typename _SPACE::DomainFieldType,  \
+                                                                                    _SPACE::dimDomain,                 \
+                                                                                    typename _SPACE::RangeFieldType,   \
+                                                                                    _SPACE::dimDomain,                 \
+                                                                                    _SPACE::dimDomain>,                \
+                                        _SPACE,                                                                        \
+                                        LocalEllipticIpdgIntegrands::Method::_METHOD,                                  \
+                                        typename XT::LA::Container<typename _SPACE::RangeFieldType,                    \
+                                                                   XT::LA::Backends::_LA>::MatrixType>;                \
+  _PRE class EllipticIpdgMatrixOperator<XT::Functions::LocalizableFunctionInterface<typename _SPACE::EntityType,       \
+                                                                                    typename _SPACE::DomainFieldType,  \
+                                                                                    _SPACE::dimDomain,                 \
+                                                                                    typename _SPACE::RangeFieldType,   \
+                                                                                    1,                                 \
+                                                                                    1>,                                \
+                                        void,                                                                          \
+                                        _SPACE,                                                                        \
+                                        LocalEllipticIpdgIntegrands::Method::_METHOD,                                  \
+                                        typename XT::LA::Container<typename _SPACE::RangeFieldType,                    \
+                                                                   XT::LA::Backends::_LA>::MatrixType>;                \
+  _PRE class EllipticIpdgMatrixOperator<XT::Functions::LocalizableFunctionInterface<typename _SPACE::EntityType,       \
+                                                                                    typename _SPACE::DomainFieldType,  \
+                                                                                    _SPACE::dimDomain,                 \
+                                                                                    typename _SPACE::RangeFieldType,   \
+                                                                                    _SPACE::dimDomain,                 \
+                                                                                    _SPACE::dimDomain>,                \
+                                        void,                                                                          \
+                                        _SPACE,                                                                        \
+                                        LocalEllipticIpdgIntegrands::Method::_METHOD,                                  \
+                                        typename XT::LA::Container<typename _SPACE::RangeFieldType,                    \
+                                                                   XT::LA::Backends::_LA>::MatrixType>
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND(extern template);
+
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+
+} // naemspace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BINDINGS_HH
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/alu_common_fem.cc b/dune/gdt/operators/elliptic-ipdg.bindings/alu_common_fem.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fe7bb2acc765f763391c981b61abe95b5fe078ae
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/alu_common_fem.cc
@@ -0,0 +1,24 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, common_dense);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+
+#endif // HAVE_DUNE_FEM
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/alu_common_gdt.cc b/dune/gdt/operators/elliptic-ipdg.bindings/alu_common_gdt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..79731c1203139a3c4044a6ca36751fdfa9c3c185
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/alu_common_gdt.cc
@@ -0,0 +1,21 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, common_dense);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/alu_common_pdelab.cc b/dune/gdt/operators/elliptic-ipdg.bindings/alu_common_pdelab.cc
new file mode 100644
index 0000000000000000000000000000000000000000..27e63eda46819c410a29301b86614beba37069ff
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/alu_common_pdelab.cc
@@ -0,0 +1,23 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_PDELAB
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, common_dense);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/alu_eigen_fem.cc b/dune/gdt/operators/elliptic-ipdg.bindings/alu_eigen_fem.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8b3e4b688af09c5fb98105e85e636f40042b53d5
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/alu_eigen_fem.cc
@@ -0,0 +1,27 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_EIGEN
+#if HAVE_DUNE_FEM
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, eigen_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+
+#endif // HAVE_DUNE_FEM
+#endif // HAVE_EIGEN
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/alu_eigen_gdt.cc b/dune/gdt/operators/elliptic-ipdg.bindings/alu_eigen_gdt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..24890e6ee09c53e5c1c0eee5f66cc34be28c90ea
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/alu_eigen_gdt.cc
@@ -0,0 +1,24 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_EIGEN
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, eigen_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_EIGEN
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/alu_eigen_pdelab.cc b/dune/gdt/operators/elliptic-ipdg.bindings/alu_eigen_pdelab.cc
new file mode 100644
index 0000000000000000000000000000000000000000..75aa407c0429757c93f76cc4045a9a02232c0f59
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/alu_eigen_pdelab.cc
@@ -0,0 +1,26 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_EIGEN
+#if HAVE_DUNE_PDELAB
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, eigen_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_EIGEN
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/alu_istl_fem.cc b/dune/gdt/operators/elliptic-ipdg.bindings/alu_istl_fem.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3a26b7573b162fdd8bfaecd6007f261e5b1246c3
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/alu_istl_fem.cc
@@ -0,0 +1,26 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_ISTL
+#if HAVE_DUNE_FEM
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, istl_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+
+#endif // HAVE_DUNE_FEM
+#endif // HAVE_DUNE_ISTL
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/alu_istl_gdt.cc b/dune/gdt/operators/elliptic-ipdg.bindings/alu_istl_gdt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..994c35559a0f335e1ee66c13d09453dab4749266
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/alu_istl_gdt.cc
@@ -0,0 +1,23 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_ISTL
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, istl_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_ISTL
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/alu_istl_pdelab.cc b/dune/gdt/operators/elliptic-ipdg.bindings/alu_istl_pdelab.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0c942528f4be824ed6191c810a44a78e733f0e13
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/alu_istl_pdelab.cc
@@ -0,0 +1,25 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_ISTL
+#if HAVE_DUNE_PDELAB
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, istl_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_DUNE_ISTL
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/yasp_common_fem.cc b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_common_fem.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f684916269c2ed14e31b9440fb1bca8afceeeda2
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_common_fem.cc
@@ -0,0 +1,22 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_DUNE_FEM
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, common_dense);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+
+#endif // HAVE_DUNE_FEM
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/yasp_common_gdt.cc b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_common_gdt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2f68e50b06881df4309344e3af723e42d003feea
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_common_gdt.cc
@@ -0,0 +1,19 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, common_dense);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/yasp_common_pdelab.cc b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_common_pdelab.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ea5b3984326332af91067d0ebe1b0d684e68c154
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_common_pdelab.cc
@@ -0,0 +1,21 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_DUNE_PDELAB
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, common_dense);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/yasp_eigen_fem.cc b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_eigen_fem.cc
new file mode 100644
index 0000000000000000000000000000000000000000..19c1262c126c60267750ad0249b8e059d370eb2d
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_eigen_fem.cc
@@ -0,0 +1,25 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_EIGEN
+#if HAVE_DUNE_FEM
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+
+#endif // HAVE_DUNE_FEM
+#endif // HAVE_EIGEN
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/yasp_eigen_gdt.cc b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_eigen_gdt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6fe9327fa63bf6a1f8c189fc240f7381cd9ff54d
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_eigen_gdt.cc
@@ -0,0 +1,22 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_EIGEN
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_EIGEN
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/yasp_eigen_pdelab.cc b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_eigen_pdelab.cc
new file mode 100644
index 0000000000000000000000000000000000000000..78c8789d44bb2e80c2cdce5157bb04d63fe28051
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_eigen_pdelab.cc
@@ -0,0 +1,24 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_EIGEN
+#if HAVE_DUNE_PDELAB
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_EIGEN
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/yasp_istl_fem.cc b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_istl_fem.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c5363d57ab288ffe0dcb8194c327f338e21b5578
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_istl_fem.cc
@@ -0,0 +1,24 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_DUNE_ISTL
+#if HAVE_DUNE_FEM
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, istl_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+
+#endif // HAVE_DUNE_FEM
+#endif // HAVE_DUNE_ISTL
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/yasp_istl_gdt.cc b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_istl_gdt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8d08b5a2f574af6cc7c831a1291d6d3b442a77c2
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_istl_gdt.cc
@@ -0,0 +1,21 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_DUNE_ISTL
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, istl_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_ISTL
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic-ipdg.bindings/yasp_istl_pdelab.cc b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_istl_pdelab.cc
new file mode 100644
index 0000000000000000000000000000000000000000..034b00594143f0314ea0623c78175d4c95a09fbf
--- /dev/null
+++ b/dune/gdt/operators/elliptic-ipdg.bindings/yasp_istl_pdelab.cc
@@ -0,0 +1,23 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+#if HAVE_DUNE_ISTL
+#if HAVE_DUNE_PDELAB
+
+#include "../elliptic-ipdg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+DUNE_GDT_OPERATORS_ELLIPTIC_IPDG_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, istl_sparse);
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_DUNE_ISTL
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic.bindings.hh b/dune/gdt/operators/elliptic.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..15681e7083e65dfa46a8985b0ca9079b778580b1
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings.hh
@@ -0,0 +1,269 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_OPERATORS_ELLIPTIC_BINDINGS_HH
+#define DUNE_GDT_OPERATORS_ELLIPTIC_BINDINGS_HH
+//#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include <dune/xt/grid/grids.bindings.hh>
+
+#include <dune/gdt/spaces.bindings.hh>
+
+#include "base.bindings.hh"
+#include "elliptic.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+template <class DF,
+          typename DT, // may be void
+          class R,
+          class M = typename XT::LA::Container<typename R::RangeFieldType>::MatrixType /*,
+          class GV = typename R::GridViewType,
+          class S = R,
+          class F = typename R::RangeFieldType*/>
+class EllipticMatrixOperator
+{
+public:
+  typedef GDT::EllipticMatrixOperator<DF, DT, R, M /*, GV, S, F*/> type;
+  typedef pybind11::class_<type> bound_type;
+
+private:
+  template <bool single_diffusion = std::is_same<DT, void>::value, bool anything = false>
+  struct diffusion_switch
+  {
+    static std::string suffix()
+    {
+      return "diffusion_factor_and_tensor";
+    }
+
+    template <class C>
+    static void addbind_factory_methods(pybind11::module& m, const std::string& method_id, const std::string& la_id)
+    {
+      namespace py = pybind11;
+      using namespace pybind11::literals;
+
+      m.def(
+          std::string(method_id + "__" + la_id).c_str(),
+          [](const DF& diffusion_factor, const DT& diffusion_tensor, const R& space, const size_t over_integrate) {
+            return make_elliptic_matrix_operator<M>(diffusion_factor, diffusion_tensor, space, over_integrate)
+                .release(); //    <- b.c. EllipticMatrixOperator is not movable, returning the raw pointer lets pybind11
+          }, //                                                                              correctly manage the memory
+          "diffusion_factor"_a,
+          "diffusion_tensor"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>());
+
+      m.def(
+          std::string(method_id).c_str(),
+          [](const DF& diffusion_factor,
+             const DT& diffusion_tensor,
+             M& matrix,
+             const R& space,
+             const size_t over_integrate) {
+            return make_elliptic_matrix_operator(diffusion_factor, diffusion_tensor, matrix, space, over_integrate)
+                .release(); //                                                                     <- s.a. for release()
+          },
+          "diffusion_factor"_a,
+          "diffusion_tensor"_a,
+          "matrix"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>());
+    } // ... addbind_factory_methods(...)
+  }; // struct diffusion_switch
+
+  template <bool anything>
+  struct diffusion_switch<true, anything>
+  {
+    static std::string suffix()
+    {
+      return "single_diffusion";
+    }
+
+    template <class C>
+    static void addbind_factory_methods(pybind11::module& m, const std::string& method_id, const std::string& la_id)
+    {
+      namespace py = pybind11;
+      using namespace pybind11::literals;
+
+      m.def(
+          std::string(method_id + "__" + la_id).c_str(),
+          [](const DF& diffusion, const R& space, const size_t over_integrate) {
+            return make_elliptic_matrix_operator<M>(diffusion, space, over_integrate).release(); // <- s.a. for
+          }, //                                                                                               .release()
+          "diffusion"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>());
+
+      m.def(
+          std::string(method_id).c_str(),
+          [](const DF& diffusion, M& matrix, const R& space, const size_t over_integrate) {
+            return make_elliptic_matrix_operator(diffusion, matrix, space, over_integrate).release(); //     <- s.a. for
+          }, //                                                                                               .release()
+          "diffusion"_a,
+          "matrix"_a,
+          "space"_a,
+          "over_integrate"_a = 0,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>());
+    } // ... addbind_factory_methods(...)
+  }; // struct diffusion_switch<..., void>
+
+public:
+  static bound_type bind(pybind11::module& m, const std::string& space_id, const std::string& la_id)
+  {
+
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    const std::string suffix = la_id + "__" + space_id + diffusion_switch<>::suffix();
+
+    auto c = MatrixOperatorBase<type>::bind(m, "EllipticMatrixOperator__" + suffix);
+
+    diffusion_switch<>::template addbind_factory_methods<type>(m, "make_elliptic_matrix_operator", la_id);
+
+    return c;
+  } // ... bind(...)
+}; // class EllipticMatrixOperator
+
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(_prefix, _GRID, _LA)                                                      \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, FV_SPACE(_GRID, leaf, gdt, 1, 1), _LA);                                   \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, FV_SPACE(_GRID, level, gdt, 1, 1), _LA)
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(_prefix, _GRID, _LA)                                                      \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, CG_SPACE(_GRID, leaf, fem, 1, 1, 1), _LA);                                \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, CG_SPACE(_GRID, level, fem, 1, 1, 1), _LA);                               \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, DG_SPACE(_GRID, leaf, fem, 1, 1, 1), _LA);                                \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, DG_SPACE(_GRID, level, fem, 1, 1, 1), _LA);                               \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, DG_SPACE(_GRID, leaf, fem, 2, 1, 1), _LA);                                \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, DG_SPACE(_GRID, level, fem, 2, 1, 1), _LA)
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(_prefix, _GRID, _LA)                                                   \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, CG_SPACE(_GRID, leaf, pdelab, 1, 1, 1), _LA);                             \
+  DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, CG_SPACE(_GRID, level, pdelab, 1, 1, 1), _LA)
+
+#define DUNE_GDT_OPERATORS_ELLIPTIC_BIND_(_prefix, _SPACE, _LA)                                                        \
+  _prefix class EllipticMatrixOperator<XT::Functions::LocalizableFunctionInterface<typename _SPACE::EntityType,        \
+                                                                                   typename _SPACE::DomainFieldType,   \
+                                                                                   _SPACE::dimDomain,                  \
+                                                                                   typename _SPACE::RangeFieldType,    \
+                                                                                   1,                                  \
+                                                                                   1>,                                 \
+                                       XT::Functions::LocalizableFunctionInterface<typename _SPACE::EntityType,        \
+                                                                                   typename _SPACE::DomainFieldType,   \
+                                                                                   _SPACE::dimDomain,                  \
+                                                                                   typename _SPACE::RangeFieldType,    \
+                                                                                   _SPACE::dimDomain,                  \
+                                                                                   _SPACE::dimDomain>,                 \
+                                       _SPACE,                                                                         \
+                                       typename XT::LA::Container<typename _SPACE::RangeFieldType,                     \
+                                                                  XT::LA::Backends::_LA>::MatrixType>;                 \
+  _prefix class EllipticMatrixOperator<XT::Functions::LocalizableFunctionInterface<typename _SPACE::EntityType,        \
+                                                                                   typename _SPACE::DomainFieldType,   \
+                                                                                   _SPACE::dimDomain,                  \
+                                                                                   typename _SPACE::RangeFieldType,    \
+                                                                                   1,                                  \
+                                                                                   1>,                                 \
+                                       void,                                                                           \
+                                       _SPACE,                                                                         \
+                                       typename XT::LA::Container<typename _SPACE::RangeFieldType,                     \
+                                                                  XT::LA::Backends::_LA>::MatrixType>;                 \
+  _prefix class EllipticMatrixOperator<XT::Functions::LocalizableFunctionInterface<typename _SPACE::EntityType,        \
+                                                                                   typename _SPACE::DomainFieldType,   \
+                                                                                   _SPACE::dimDomain,                  \
+                                                                                   typename _SPACE::RangeFieldType,    \
+                                                                                   _SPACE::dimDomain,                  \
+                                                                                   _SPACE::dimDomain>,                 \
+                                       void,                                                                           \
+                                       _SPACE,                                                                         \
+                                       typename XT::LA::Container<typename _SPACE::RangeFieldType,                     \
+                                                                  XT::LA::Backends::_LA>::MatrixType>
+
+
+// these lines have to match the corresponding ones in the .cc source file
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(extern template, YASP_2D_EQUIDISTANT_OFFSET, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(extern template, YASP_2D_EQUIDISTANT_OFFSET, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(extern template, YASP_2D_EQUIDISTANT_OFFSET, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(extern template, YASP_2D_EQUIDISTANT_OFFSET, istl_sparse);
+#endif
+#if HAVE_DUNE_FEM
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, istl_sparse);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, istl_sparse);
+#endif
+#endif // HAVE_DUNE_PDELAB
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(extern template, ALU_2D_SIMPLEX_CONFORMING, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(extern template, ALU_2D_SIMPLEX_CONFORMING, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(extern template, ALU_2D_SIMPLEX_CONFORMING, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(extern template, ALU_2D_SIMPLEX_CONFORMING, istl_sparse);
+#endif
+#if HAVE_DUNE_FEM
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, istl_sparse);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, istl_sparse);
+#endif
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+//#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_OPERATORS_ELLIPTIC_BINDINGS_HH
diff --git a/dune/gdt/operators/elliptic.bindings/common_fem.cc b/dune/gdt/operators/elliptic.bindings/common_fem.cc
new file mode 100644
index 0000000000000000000000000000000000000000..954684df23a15d63f4787b766acd1ed9232ce380
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings/common_fem.cc
@@ -0,0 +1,28 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_FEM
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, common_dense);
+#endif // HAVE_DUNE_FEM
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, common_dense);
+#endif // HAVE_DUNE_FEM
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic.bindings/common_gdt.cc b/dune/gdt/operators/elliptic.bindings/common_gdt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a27a62144985f14796bd86c6e07ccf015b6d4bd0
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings/common_gdt.cc
@@ -0,0 +1,24 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, common_dense);
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, common_dense);
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic.bindings/common_pdelab.cc b/dune/gdt/operators/elliptic.bindings/common_pdelab.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1bc4391565c308039174737e0db24e1bdc9b697b
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings/common_pdelab.cc
@@ -0,0 +1,28 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, common_dense);
+#endif // HAVE_DUNE_PDELAB
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, common_dense);
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic.bindings/eigen_fem.cc b/dune/gdt/operators/elliptic.bindings/eigen_fem.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ad4d50da2af5df0870db75ef07259075688d5f4f
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings/eigen_fem.cc
@@ -0,0 +1,34 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_FEM
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_sparse);
+#endif
+#endif // HAVE_DUNE_FEM
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, eigen_sparse);
+#endif
+#endif // HAVE_DUNE_FEM
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic.bindings/eigen_gdt.cc b/dune/gdt/operators/elliptic.bindings/eigen_gdt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..43279ba8d247fafb709afb8a4fed8188b1fe9683
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings/eigen_gdt.cc
@@ -0,0 +1,30 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_sparse);
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, eigen_sparse);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic.bindings/eigen_pdelab.cc b/dune/gdt/operators/elliptic.bindings/eigen_pdelab.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ddb007d93a1ea25f4201b7fa9cfd1327062cfff7
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings/eigen_pdelab.cc
@@ -0,0 +1,34 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_PDELAB
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, eigen_sparse);
+#endif
+#endif // HAVE_DUNE_PDELAB
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_PDELAB
+#if HAVE_EIGEN
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, eigen_dense);
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, eigen_sparse);
+#endif
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic.bindings/istl_fem.cc b/dune/gdt/operators/elliptic.bindings/istl_fem.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d7ac5b12ec7ae5ed26db914573dd40caeb3458b2
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings/istl_fem.cc
@@ -0,0 +1,32 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_FEM
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, istl_sparse);
+#endif
+#endif // HAVE_DUNE_FEM
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, istl_sparse);
+#endif
+#endif // HAVE_DUNE_FEM
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic.bindings/istl_gdt.cc b/dune/gdt/operators/elliptic.bindings/istl_gdt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fb9433d9f7eac4872b6aeb04f34f15e77ffdd305
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings/istl_gdt.cc
@@ -0,0 +1,28 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET, istl_sparse);
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING, istl_sparse);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/operators/elliptic.bindings/istl_pdelab.cc b/dune/gdt/operators/elliptic.bindings/istl_pdelab.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dbf5c91607d42e489790e28fbd7e0d94dc2a803c
--- /dev/null
+++ b/dune/gdt/operators/elliptic.bindings/istl_pdelab.cc
@@ -0,0 +1,32 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "../elliptic.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_PDELAB
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, istl_sparse);
+#endif
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_PDELAB
+#if HAVE_DUNE_ISTL
+DUNE_GDT_OPERATORS_ELLIPTIC_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, istl_sparse);
+#endif
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/projections/dirichlet.bindings.cc b/dune/gdt/projections/dirichlet.bindings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ee2b71e388fba03c330f10d12ed4f48601122ed9
--- /dev/null
+++ b/dune/gdt/projections/dirichlet.bindings.cc
@@ -0,0 +1,58 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "dirichlet.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_FEM
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_PDELAB
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/projections/dirichlet.bindings.hh b/dune/gdt/projections/dirichlet.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..83cfd1dd525f7694b2a513fc939dad924c75f7e7
--- /dev/null
+++ b/dune/gdt/projections/dirichlet.bindings.hh
@@ -0,0 +1,135 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_PROJECTIONS_DIRICHLET_BINDINGS_HH
+#define DUNE_GDT_PROJECTIONS_DIRICHLET_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include <dune/xt/grid/grids.bindings.hh>
+#include <dune/xt/la/container.bindings.hh>
+
+#include <dune/gdt/spaces.bindings.hh>
+
+#include "dirichlet.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+template <class GV, class S, class R, class F = double>
+class DirichletProjectionLocalizableOperator
+{
+public:
+  typedef GDT::DirichletProjectionLocalizableOperator<GV, S, R, F> type;
+
+private:
+  typedef XT::Grid::Walker<GV> BaseType;
+
+public:
+  typedef pybind11::class_<type, BaseType> bound_type;
+
+  static bound_type bind(pybind11::module& m, const std::string& space_id, const std::string& la_id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    bound_type c(m, std::string("DirichletProjectionLocalizableOperator__" + space_id + "__" + la_id).c_str());
+    c.def("apply", [](type& self) { self.apply(); });
+
+    m.def(std::string("make_localizable_dirichlet_projection_operator").c_str(),
+          [](const XT::Grid::BoundaryInfo<typename XT::Grid::Intersection<GV>::Type>& boundary_info,
+             const S& source,
+             R& range) {
+            return make_localizable_dirichlet_projection_operator(
+                       range.space().grid_view(), boundary_info, source, range)
+                .release();
+          },
+          "boundary_info"_a,
+          "source"_a,
+          "range"_a,
+          py::keep_alive<0, 1>(),
+          py::keep_alive<0, 2>(),
+          py::keep_alive<0, 3>());
+
+    return c;
+  } // ... bind(...)
+}; // class DirichletProjectionLocalizableOperator
+
+
+#define DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(_prefix, _GRID, _LA)                                                   \
+  _prefix DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_(CG_SPACE(_GRID, leaf, fem, 1, 1, 1), _LA);                              \
+  _prefix DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_(CG_SPACE(_GRID, level, fem, 1, 1, 1), _LA)
+
+#define DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(_prefix, _GRID, _LA)                                                \
+  _prefix DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_(CG_SPACE(_GRID, leaf, pdelab, 1, 1, 1), _LA);                           \
+  _prefix DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_(CG_SPACE(_GRID, level, pdelab, 1, 1, 1), _LA)
+
+#define DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_(_SPACE, _LA)                                                              \
+  class DirichletProjectionLocalizableOperator<                                                                        \
+      typename _SPACE::GridViewType,                                                                                   \
+      XT::Functions::LocalizableFunctionInterface<typename _SPACE::EntityType,                                         \
+                                                  typename _SPACE::DomainFieldType,                                    \
+                                                  _SPACE::dimDomain,                                                   \
+                                                  typename _SPACE::RangeFieldType,                                     \
+                                                  _SPACE::dimRange,                                                    \
+                                                  _SPACE::dimRangeCols>,                                               \
+      DiscreteFunction<_SPACE, _LA>>
+
+
+// these lines have to match the corresponding ones in the .cc source file
+#if HAVE_DUNE_FEM
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_PDELAB
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_FEM
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, COMMON_DENSE_VECTOR);
+#if HAVE_EIGEN
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, EIGEN_DENSE_VECTOR);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_PROJECTIONS_DIRICHLET_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING, ISTL_DENSE_VECTOR);
+#endif
+#endif // HAVE_DUNE_PDELAB
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_PROJECTIONS_DIRICHLET_BINDINGS_HH
diff --git a/dune/gdt/spaces.bindings.hh b/dune/gdt/spaces.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..84ba875982130d61ffc286b59b182a94d37cb4c7
--- /dev/null
+++ b/dune/gdt/spaces.bindings.hh
@@ -0,0 +1,11 @@
+#ifndef DUNE_GDT_SPACES_BINDINGS_HH
+#define DUNE_GDT_SPACES_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include "spaces/interface.bindings.hh"
+#include "spaces/cg.bindings.hh"
+#include "spaces/dg.bindings.hh"
+#include "spaces/fv.bindings.hh"
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_SPACES_BINDINGS_HH
diff --git a/dune/gdt/spaces.pbh b/dune/gdt/spaces.pbh
new file mode 100644
index 0000000000000000000000000000000000000000..72251ad6f50f6bd8b091ceddee9ebc669e8b74dc
--- /dev/null
+++ b/dune/gdt/spaces.pbh
@@ -0,0 +1,49 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_SPACES_PBH
+#define DUNE_GDT_SPACES_PBH
+
+#include <dune/pybindxi/pybind11.h>
+
+#include "spaces/interface.hh"
+
+namespace Dune {
+namespace GDT {
+
+
+template <class S>
+typename std::enable_if<is_space<S>::value, pybind11::class_<S>>::type bind_space(pybind11::module& m,
+                                                                                  const std::string& id)
+{
+  namespace py = pybind11;
+  using namespace pybind11::literals;
+
+  py::class_<S> c(m, id.c_str(), id.c_str(), py::metaclass());
+
+  c.def_property_readonly_static("dimDomain", [](const S& /*self*/) { return S::dimDomain; });
+  c.def_property_readonly_static("dimRange", [](const S& /*self*/) { return S::dimRange; });
+  c.def_property_readonly_static("dimRangeCols", [](const S& /*self*/) { return S::dimRangeCols; });
+  c.def_property_readonly_static("polOrder", [](const S& /*self*/) { return S::polOrder; });
+
+  c.def("size", [](const S& self) { return self.mapper().size(); });
+  c.def("visualize", [](const S& self, const std::string& filename) { self.visualize(filename); }, "filename"_a = "");
+  c.def("compute_pattern", [](const S& self) { return self.compute_pattern(); });
+  c.def("compute_volume_pattern", [](const S& self) { return self.compute_volume_pattern(); });
+  c.def("compute_face_pattern", [](const S& self) { return self.compute_face_pattern(); });
+  c.def("compute_face_and_volume_pattern", [](const S& self) { return self.compute_face_and_volume_pattern(); });
+
+  return c;
+} // ... bind_space(...)
+
+
+} // namespace GDT
+} // namespace Dune
+
+#endif // DUNE_GDT_SPACES_PBH
diff --git a/dune/gdt/spaces/cg.bindings.cc b/dune/gdt/spaces/cg.bindings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6ecdaf4ba60a7242a2fd8b6a9c4bc3ec22c461a7
--- /dev/null
+++ b/dune/gdt/spaces/cg.bindings.cc
@@ -0,0 +1,34 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "cg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_CG_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_SPACES_CG_BIND_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_CG_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_SPACES_CG_BIND_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/spaces/cg.bindings.hh b/dune/gdt/spaces/cg.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..31f7c36315b1e49f534baff5d4aca0f84d4a6575
--- /dev/null
+++ b/dune/gdt/spaces/cg.bindings.hh
@@ -0,0 +1,78 @@
+#ifndef DUNE_GDT_SPACES_CG_BINDINGS_HH
+#define DUNE_GDT_SPACES_CG_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/xt/grid/grids.bindings.hh>
+
+#include "cg.hh"
+#include "interface.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+#define _DEFINE_CG_SPACE(_G, _layer, _backend, _p, _r, _rC)                                                            \
+  typedef                                                                                                              \
+      typename CgSpaceProvider<_G, XT::Grid::Layers::_layer, ChooseSpaceBackend::_backend, _p, double, _r, _rC>::type  \
+          Cg_##_G##_##_layer##_to_##_r##x##_rC##_##p##_p##_##_backend##_Space
+
+#if HAVE_DUNE_FEM
+_DEFINE_CG_SPACE(YASP_2D_EQUIDISTANT_OFFSET, leaf, fem, 1, 1, 1);
+_DEFINE_CG_SPACE(YASP_2D_EQUIDISTANT_OFFSET, level, fem, 1, 1, 1);
+#endif
+#if HAVE_DUNE_PDELAB
+_DEFINE_CG_SPACE(YASP_2D_EQUIDISTANT_OFFSET, leaf, pdelab, 1, 1, 1);
+_DEFINE_CG_SPACE(YASP_2D_EQUIDISTANT_OFFSET, level, pdelab, 1, 1, 1);
+#endif
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+_DEFINE_CG_SPACE(ALU_2D_SIMPLEX_CONFORMING, leaf, fem, 1, 1, 1);
+_DEFINE_CG_SPACE(ALU_2D_SIMPLEX_CONFORMING, level, fem, 1, 1, 1);
+#endif
+#if HAVE_DUNE_PDELAB
+_DEFINE_CG_SPACE(ALU_2D_SIMPLEX_CONFORMING, leaf, pdelab, 1, 1, 1);
+_DEFINE_CG_SPACE(ALU_2D_SIMPLEX_CONFORMING, level, pdelab, 1, 1, 1);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+#undef _DEFINE_CG_SPACE
+
+
+// this is used by other headers
+#define CG_SPACE(_G, _layer, _backend, _p, _r, _rC) Cg_##_G##_##_layer##_to_##_r##x##_rC##_##p##_p##_##_backend##_Space
+
+
+#define DUNE_GDT_SPACES_CG_BIND_FEM(_prefix, _GRID)                                                                    \
+  _prefix class SpaceInterface<CG_SPACE(_GRID, leaf, fem, 1, 1, 1)>;                                                   \
+  _prefix class SpaceInterface<CG_SPACE(_GRID, level, fem, 1, 1, 1)>
+
+#define DUNE_GDT_SPACES_CG_BIND_PDELAB(_prefix, _GRID)                                                                 \
+  _prefix class SpaceInterface<CG_SPACE(_GRID, leaf, pdelab, 1, 1, 1)>;                                                \
+  _prefix class SpaceInterface<CG_SPACE(_GRID, level, pdelab, 1, 1, 1)>
+
+
+// these lines have to match the corresponding ones in the .cc source file
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_CG_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_SPACES_CG_BIND_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_CG_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_SPACES_CG_BIND_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_SPACES_CG_BINDINGS_HH
diff --git a/dune/gdt/spaces/constraints.bindings.cc b/dune/gdt/spaces/constraints.bindings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..88fb4bc79bca2b5e1769331ef9cfb349cf62dc0a
--- /dev/null
+++ b/dune/gdt/spaces/constraints.bindings.cc
@@ -0,0 +1,58 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "constraints.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .cc source file
+DUNE_GDT_SPACES_CONSTRAINTS_BIND(template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view);
+
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view, eigen_dense);
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view, istl_sparse);
+#endif
+
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_FEM(template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_PDELAB(template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_SPACES_CONSTRAINTS_BIND(template, ALU_2D_SIMPLEX_CONFORMING, leaf, view);
+DUNE_GDT_SPACES_CONSTRAINTS_BIND(template, ALU_2D_SIMPLEX_CONFORMING, level, view);
+
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(template, ALU_2D_SIMPLEX_CONFORMING, leaf, view, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(template, ALU_2D_SIMPLEX_CONFORMING, leaf, view, eigen_dense);
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(template, ALU_2D_SIMPLEX_CONFORMING, leaf, view, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(template, ALU_2D_SIMPLEX_CONFORMING, leaf, view, istl_sparse);
+#endif
+
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_FEM(template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_PDELAB(template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#endif
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/spaces/constraints.bindings.hh b/dune/gdt/spaces/constraints.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..fdf53eeb3032af697b0e7f82c24a8fc49676ab23
--- /dev/null
+++ b/dune/gdt/spaces/constraints.bindings.hh
@@ -0,0 +1,190 @@
+// This file is part of the dune-gdt project:
+//   https://github.com/dune-community/dune-gdt
+// Copyright 2010-2016 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 (2017)
+
+#ifndef DUNE_GDT_SPACES_CONSTRAINTS_BINDINGS_HH
+#define DUNE_GDT_SPACES_CONSTRAINTS_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <dune/pybindxi/pybind11.h>
+
+#include <dune/xt/common/exceptions.hh>
+#include <dune/xt/common/type_traits.hh>
+#include <dune/xt/grid/intersection.hh>
+#include <dune/xt/grid/grids.bindings.hh>
+
+#include <dune/xt/la/container.hh>
+#include <dune/xt/la/container.bindings.hh>
+
+#include <dune/gdt/assembler/system.hh>
+#include <dune/gdt/spaces/cg.bindings.hh>
+
+#include "constraints.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+template <class I>
+class DirichletConstraints
+{
+public:
+  typedef GDT::DirichletConstraints<I> type;
+  typedef pybind11::class_<type> bound_type;
+
+  static bound_type bind(pybind11::module& m, const std::string& intersection_id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    bound_type c(m, std::string("DirichletConstraints__" + intersection_id).c_str());
+    c.def("__init__",
+          [](type& self, const XT::Grid::BoundaryInfo<I>& boundary_info, const ssize_t size, const bool set) {
+            try {
+              new (&self) type(boundary_info, boost::numeric_cast<size_t>(size), set);
+            } catch (boost::bad_numeric_cast& ee) {
+              DUNE_THROW(XT::Common::Exceptions::wrong_input_given,
+                         "Given size has to be positive!\n\n The error in boost while converting '"
+                             << size
+                             << "' to '"
+                             << XT::Common::Typename<size_t>::value()
+                             << "' was: "
+                             << ee.what());
+            }
+          },
+          "boundary_info"_a,
+          "size"_a,
+          "set_diagonal_entries"_a = true,
+          py::keep_alive<1, 2>());
+    c.def("boundary_info", &type::boundary_info);
+    c.def("size", &type::size);
+
+    m.def(std::string("make_dirichlet_constraints").c_str(),
+          [](const XT::Grid::BoundaryInfo<I>& boundary_info, const ssize_t size, const bool set) {
+            size_t size__as_size_t = 0;
+            try {
+              size__as_size_t = boost::numeric_cast<size_t>(size);
+            } catch (boost::bad_numeric_cast& ee) {
+              DUNE_THROW(XT::Common::Exceptions::wrong_input_given,
+                         "Given size has to be positive!\n\n The error in boost while converting '"
+                             << size
+                             << "' to '"
+                             << XT::Common::Typename<size_t>::value()
+                             << "' was: "
+                             << ee.what());
+            }
+            return type(boundary_info, size__as_size_t, set);
+          },
+          "boundary_info"_a,
+          "size"_a,
+          "set_diagonal_entries"_a,
+          py::keep_alive<0, 1>());
+
+    return c;
+  } // ... bind(...)
+
+  template <XT::LA::Backends la_backend, class R = double>
+  static void addbind(bound_type& c)
+  {
+    typedef typename XT::LA::Container<R, la_backend>::MatrixType M;
+    typedef typename XT::LA::Container<R, la_backend>::VectorType V;
+    using namespace pybind11::literals;
+
+    c.def("apply", [](const type& self, M& matrix) { self.apply(matrix); }, "matrix"_a);
+    c.def("apply", [](const type& self, V& vector) { self.apply(vector); }, "vector"_a);
+    c.def("apply", [](const type& self, M& matrix, V& vector) { self.apply(matrix, vector); }, "matrix"_a, "vector"_a);
+  }
+
+  template <class T, class GV, class A>
+  static void addbind(pybind11::class_<GDT::SystemAssembler<T, GV, A>>& bound_system_assembler)
+  {
+    using namespace pybind11::literals;
+
+    bound_system_assembler.def("append",
+                               [](GDT::SystemAssembler<T, GV, A>& self,
+                                  GDT::DirichletConstraints<typename XT::Grid::Intersection<GV>::type>& constraints) {
+                                 self.append(constraints);
+                               },
+                               "dirichlet_constraints"_a);
+  } // ... addbind_to_SystemAssembler(...)
+}; // class addbind_to_SystemAssembler
+
+
+#define DUNE_GDT_SPACES_CONSTRAINTS_BIND(_prefix, _GRID, _layer, _backend)                                             \
+  _prefix class DirichletConstraints<typename XT::Grid::Intersection<                                                  \
+      typename XT::Grid::Layer<_GRID, XT::Grid::Layers::_layer, XT::Grid::Backends::_backend>::type>::type>
+
+#define DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(_prefix, _GRID, _layer, _backend, _la)                                  \
+  _prefix void DirichletConstraints<typename XT::Grid::Intersection<                                                   \
+      typename XT::Grid::Layer<_GRID, XT::Grid::Layers::_layer, XT::Grid::Backends::_backend>::type>::type>::          \
+      addbind<XT::LA::Backends::_la>(                                                                                  \
+          typename DirichletConstraints<typename XT::Grid::Intersection<                                               \
+              typename XT::Grid::Layer<_GRID, XT::Grid::Layers::_layer, XT::Grid::Backends::_backend>::type>::type>::  \
+              bound_type&)
+
+#define DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_FEM(_prefix, _GRID)                                              \
+  DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_(_prefix, CG_SPACE(_GRID, leaf, fem, 1, 1, 1));                        \
+  DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_(_prefix, CG_SPACE(_GRID, level, fem, 1, 1, 1))
+
+#define DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_PDELAB(_prefix, _GRID)                                           \
+  DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_(_prefix, CG_SPACE(_GRID, leaf, pdelab, 1, 1, 1));                     \
+  DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_(_prefix, CG_SPACE(_GRID, level, pdelab, 1, 1, 1))
+
+#define DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_(_prefix, _SPACE)                                                \
+  _prefix void DirichletConstraints<typename XT::Grid::Intersection<typename _SPACE::GridViewType>::type>::            \
+      addbind<_SPACE, typename _SPACE::GridViewType, _SPACE>(                                                          \
+          pybind11::class_<GDT::SystemAssembler<_SPACE, typename _SPACE::GridViewType, _SPACE>>&)
+
+
+// these lines have to match the corresponding ones in the .hh header file
+DUNE_GDT_SPACES_CONSTRAINTS_BIND(extern template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view);
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(extern template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(extern template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view, eigen_dense);
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(extern template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(extern template, YASP_2D_EQUIDISTANT_OFFSET, leaf, view, istl_sparse);
+#endif
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_PDELAB(extern template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_SPACES_CONSTRAINTS_BIND(extern template, ALU_2D_SIMPLEX_CONFORMING, leaf, view);
+DUNE_GDT_SPACES_CONSTRAINTS_BIND(extern template, ALU_2D_SIMPLEX_CONFORMING, level, view);
+DUNE_GDT_SPACES_CONSTRAINTS_BIND(extern template, ALU_2D_SIMPLEX_CONFORMING, leaf, view);
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(extern template, ALU_2D_SIMPLEX_CONFORMING, leaf, view, common_dense);
+#if HAVE_EIGEN
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(extern template, ALU_2D_SIMPLEX_CONFORMING, leaf, view, eigen_dense);
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(extern template, ALU_2D_SIMPLEX_CONFORMING, leaf, view, eigen_sparse);
+#endif
+#if HAVE_DUNE_ISTL
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_LA(extern template, ALU_2D_SIMPLEX_CONFORMING, leaf, view, istl_sparse);
+#endif
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#if HAVE_DUNE_PDELAB
+DUNE_GDT_SPACES_CONSTRAINTS_ADDBIND_ASSEMBLER_PDELAB(extern template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#endif
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_SPACES_CONSTRAINTS_BINDINGS_HH
diff --git a/dune/gdt/spaces/dg.bindings.cc b/dune/gdt/spaces/dg.bindings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..36e5da3b65d3c8aac4743f61403e1727941d6f9f
--- /dev/null
+++ b/dune/gdt/spaces/dg.bindings.cc
@@ -0,0 +1,28 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "dg.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_DG_BIND_FEM(template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_DG_BIND_FEM(template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/spaces/dg.bindings.hh b/dune/gdt/spaces/dg.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..9b770542aa10503a0d3ec1f1c0bba4184f9b55f4
--- /dev/null
+++ b/dune/gdt/spaces/dg.bindings.hh
@@ -0,0 +1,66 @@
+#ifndef DUNE_GDT_SPACES_DG_BINDINGS_HH
+#define DUNE_GDT_SPACES_DG_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/xt/grid/grids.bindings.hh>
+
+#include "dg.hh"
+#include "interface.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+#define _DEFINE_DG_SPACE(_G, _layer, _backend, _p, _r, _rC)                                                            \
+  typedef                                                                                                              \
+      typename DgSpaceProvider<_G, XT::Grid::Layers::_layer, ChooseSpaceBackend::_backend, _p, double, _r, _rC>::type  \
+          Dg_##_G##_##_layer##_to_##_r##x##_rC##_##p##_p##_##_backend##_Space
+
+#if HAVE_DUNE_FEM
+_DEFINE_DG_SPACE(YASP_2D_EQUIDISTANT_OFFSET, leaf, fem, 1, 1, 1);
+_DEFINE_DG_SPACE(YASP_2D_EQUIDISTANT_OFFSET, leaf, fem, 2, 1, 1);
+_DEFINE_DG_SPACE(YASP_2D_EQUIDISTANT_OFFSET, level, fem, 1, 1, 1);
+_DEFINE_DG_SPACE(YASP_2D_EQUIDISTANT_OFFSET, level, fem, 2, 1, 1);
+#endif
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+_DEFINE_DG_SPACE(ALU_2D_SIMPLEX_CONFORMING, leaf, fem, 1, 1, 1);
+_DEFINE_DG_SPACE(ALU_2D_SIMPLEX_CONFORMING, leaf, fem, 2, 1, 1);
+_DEFINE_DG_SPACE(ALU_2D_SIMPLEX_CONFORMING, level, fem, 1, 1, 1);
+_DEFINE_DG_SPACE(ALU_2D_SIMPLEX_CONFORMING, level, fem, 2, 1, 1);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+#undef _DEFINE_DG_SPACE
+
+
+// this is used by other headers
+#define DG_SPACE(_G, _layer, _backend, _p, _r, _rC) Dg_##_G##_##_layer##_to_##_r##x##_rC##_##p##_p##_##_backend##_Space
+
+
+#define DUNE_GDT_SPACES_DG_BIND_FEM(_prefix, _GRID)                                                                    \
+  _prefix class SpaceInterface<DG_SPACE(_GRID, leaf, fem, 1, 1, 1)>;                                                   \
+  _prefix class SpaceInterface<DG_SPACE(_GRID, level, fem, 1, 1, 1)>;                                                  \
+  _prefix class SpaceInterface<DG_SPACE(_GRID, leaf, fem, 2, 1, 1)>;                                                   \
+  _prefix class SpaceInterface<DG_SPACE(_GRID, level, fem, 2, 1, 1)>
+
+
+// these lines have to match the corresponding ones in the .cc source file
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_DG_BIND_FEM(extern template, YASP_2D_EQUIDISTANT_OFFSET);
+#endif
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+#if HAVE_DUNE_FEM
+DUNE_GDT_SPACES_DG_BIND_FEM(extern template, ALU_2D_SIMPLEX_CONFORMING);
+#endif
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_SPACES_DG_BINDINGS_HH
diff --git a/dune/gdt/spaces/fv.bindings.cc b/dune/gdt/spaces/fv.bindings.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d2a186edb30813ddd60d100043048644967ac7d7
--- /dev/null
+++ b/dune/gdt/spaces/fv.bindings.cc
@@ -0,0 +1,23 @@
+#include "config.h"
+
+#if HAVE_DUNE_PYBINDXI
+
+#include "fv.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+// these lines have to match the corresponding ones in the .hh header file
+DUNE_GDT_SPACES_FV_BIND_GDT(template, YASP_2D_EQUIDISTANT_OFFSET);
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_SPACES_FV_BIND_GDT(template, ALU_2D_SIMPLEX_CONFORMING);
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
diff --git a/dune/gdt/spaces/fv.bindings.hh b/dune/gdt/spaces/fv.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..09e7c75166a079740b07bc94b857cde2fa13cb84
--- /dev/null
+++ b/dune/gdt/spaces/fv.bindings.hh
@@ -0,0 +1,55 @@
+#ifndef DUNE_GDT_SPACES_FV_BINDINGS_HH
+#define DUNE_GDT_SPACES_FV_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/xt/grid/grids.bindings.hh>
+
+#include "fv.hh"
+#include "interface.bindings.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+#define _DEFINE_FV_SPACE(_G, _layer, _backend, _r, _rC)                                                                \
+  typedef typename FvSpaceProvider<_G, XT::Grid::Layers::_layer, ChooseSpaceBackend::_backend, double, _r, _rC>::type  \
+      Fv_##_G##_##_layer##_to_##_r##x##_rC##_##_backend##_Space
+
+_DEFINE_FV_SPACE(YASP_2D_EQUIDISTANT_OFFSET, leaf, gdt, 1, 1);
+_DEFINE_FV_SPACE(YASP_2D_EQUIDISTANT_OFFSET, leaf, gdt, 1, 1);
+_DEFINE_FV_SPACE(YASP_2D_EQUIDISTANT_OFFSET, level, gdt, 1, 1);
+_DEFINE_FV_SPACE(YASP_2D_EQUIDISTANT_OFFSET, level, gdt, 1, 1);
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+_DEFINE_FV_SPACE(ALU_2D_SIMPLEX_CONFORMING, leaf, gdt, 1, 1);
+_DEFINE_FV_SPACE(ALU_2D_SIMPLEX_CONFORMING, leaf, gdt, 1, 1);
+_DEFINE_FV_SPACE(ALU_2D_SIMPLEX_CONFORMING, level, gdt, 1, 1);
+_DEFINE_FV_SPACE(ALU_2D_SIMPLEX_CONFORMING, level, gdt, 1, 1);
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+#undef _DEFINE_FV_SPACE
+
+
+// this is used by other headers
+#define FV_SPACE(_G, _layer, _backend, _r, _rC) Fv_##_G##_##_layer##_to_##_r##x##_rC##_##_backend##_Space
+
+
+#define DUNE_GDT_SPACES_FV_BIND_GDT(_prefix, _GRID)                                                                    \
+  _prefix class SpaceInterface<FV_SPACE(_GRID, leaf, gdt, 1, 1)>;                                                      \
+  _prefix class SpaceInterface<FV_SPACE(_GRID, level, gdt, 1, 1)>
+
+
+// these lines have to match the corresponding ones in the .cc source file
+DUNE_GDT_SPACES_FV_BIND_GDT(extern template, YASP_2D_EQUIDISTANT_OFFSET);
+
+#if HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+DUNE_GDT_SPACES_FV_BIND_GDT(extern template, ALU_2D_SIMPLEX_CONFORMING);
+#endif // HAVE_ALUGRID || HAVE_DUNE_ALUGRID
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_SPACES_FV_BINDINGS_HH
diff --git a/dune/gdt/spaces/interface.bindings.hh b/dune/gdt/spaces/interface.bindings.hh
new file mode 100644
index 0000000000000000000000000000000000000000..437d873f82d63d6ae03824dd9c15630dc4a21168
--- /dev/null
+++ b/dune/gdt/spaces/interface.bindings.hh
@@ -0,0 +1,54 @@
+#ifndef DUNE_GDT_SPACES_INTERFACE_BINDINGS_HH
+#define DUNE_GDT_SPACES_INTERFACE_BINDINGS_HH
+#if HAVE_DUNE_PYBINDXI
+
+#include <dune/pybindxi/pybind11.h>
+
+#include "interface.hh"
+
+namespace Dune {
+namespace GDT {
+namespace bindings {
+
+
+template <class S>
+class SpaceInterface
+{
+  static_assert(is_space<S>::value, "");
+
+public:
+  typedef S type;
+  typedef pybind11::class_<type> bound_type;
+
+  static bound_type bind(pybind11::module& m, const std::string& id)
+  {
+    namespace py = pybind11;
+    using namespace pybind11::literals;
+
+    bound_type c(m, id.c_str(), id.c_str(), py::metaclass());
+
+    c.def_property_readonly_static("dimDomain", [](const type& /*self*/) { return S::dimDomain; });
+    c.def_property_readonly_static("dimRange", [](const type& /*self*/) { return S::dimRange; });
+    c.def_property_readonly_static("dimRangeCols", [](const type& /*self*/) { return S::dimRangeCols; });
+    c.def_property_readonly_static("polOrder", [](const type& /*self*/) { return S::polOrder; });
+
+    c.def("size", [](const type& self) { return self.mapper().size(); });
+    c.def("visualize",
+          [](const type& self, const std::string& filename) { self.visualize(filename); },
+          "filename"_a = "");
+    c.def("compute_pattern", [](const type& self) { return self.compute_pattern(); });
+    c.def("compute_volume_pattern", [](const type& self) { return self.compute_volume_pattern(); });
+    c.def("compute_face_pattern", [](const type& self) { return self.compute_face_pattern(); });
+    c.def("compute_face_and_volume_pattern", [](const type& self) { return self.compute_face_and_volume_pattern(); });
+
+    return c;
+  } // ... bind(...)
+}; // class SpaceInterface
+
+
+} // namespace bindings
+} // namespace GDT
+} // namespace Dune
+
+#endif // HAVE_DUNE_PYBINDXI
+#endif // DUNE_GDT_SPACES_INTERFACE_BINDINGS_HH
diff --git a/python/.gitignore b/python/.gitignore
index 0910e5ccaaa9042a80241414c310726e617504f0..1da2a8cfc6e9b0b40c6f847a20dfb68852b0d2cf 100644
--- a/python/.gitignore
+++ b/python/.gitignore
@@ -1,3 +1,4 @@
 build/
 dist/
 dune.gdt.egg-info/
+__pycache__
diff --git a/python/dune/gdt/__init__.py b/python/dune/gdt/__init__.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..896fb4b6fdb504772dd9cba0b59ed47e354e8ff0 100644
--- a/python/dune/gdt/__init__.py
+++ b/python/dune/gdt/__init__.py
@@ -0,0 +1,25 @@
+
+from importlib import import_module
+
+
+def init_logger(max_info_level=-1,
+                max_debug_level=-1,
+                enable_warnings=True,
+                enable_colors=True,
+                info_color='blue',
+                debug_color='darkgray',
+                warning_color='red'):
+    from ._gdt import init_logger as _init_logger
+    initializers = [_init_logger]
+    for module_name in ('xt.common', 'xt.grid', 'xt.functions', 'xt.la'):
+        try:
+            mm = import_module('dune.{}'.format(module_name))
+            initializers.append(mm.init_logger)
+        except ModuleNotFoundError:
+            pass
+    for initializer in initializers:
+        initializer(max_info_level, max_debug_level, enable_warnings, enable_colors, info_color, debug_color,
+                        warning_color)
+
+
+from ._gdt import *