diff --git a/src/amdis/BiLinearForm.hpp b/src/amdis/BiLinearForm.hpp
index af41ef1e41741ac2d4ab52f224e636cb0269661a..ff1fda26299f625bd62f962bc52c530a2b0058ce 100644
--- a/src/amdis/BiLinearForm.hpp
+++ b/src/amdis/BiLinearForm.hpp
@@ -45,10 +45,12 @@ namespace AMDiS
     using ElementMatrix = FlatMatrix<CoefficientType>;
 
   public:
-    /// Constructor. Wraps the reference into a non-destroying shared_ptr or moves the basis into a new shared_ptr.
-    template <class RB_, class CB_, class Comm_>
-    BiLinearForm(RB_&& rowBasis, CB_&& colBasis, Comm_&& comm)
-      : Super(FWD(rowBasis), FWD(colBasis), FWD(comm))
+    /// Constructor. Wraps the reference into a non-destroying shared_ptr or moves
+    /// the basis into a new shared_ptr. The additional arguments can be the communication
+    /// object. If not provided, a new communication is created.
+    template <class RB_, class CB_, class... Args>
+    BiLinearForm(RB_&& rowBasis, CB_&& colBasis, Args&&... args)
+      : Super(FWD(rowBasis), FWD(colBasis), FWD(args)...)
     {
       operators_.init(*Super::rowBasis(), *Super::colBasis());
     }
@@ -63,7 +65,7 @@ namespace AMDiS
       elementMatrix_.resize(rowSize, colSize);
     }
 
-    /// \brief Associate a local operator with this DOFMatrix
+    /// \brief Associate a local operator with this BiLinearForm
     /**
      * Stores an operator in a list that gets assembled during a call to \ref assemble().
      * The operator may be assigned to a specific context, i.e. either an element
@@ -72,20 +74,36 @@ namespace AMDiS
      * functions the operator is applied to.
      *
      * \tparam ContextTag  One of \ref tag::element_operator, \ref tag::intersection_operator
-     *                     or \ref tag::boundary_operator indicating where to assemble this operator.
+     *                     or \ref tag::boundary_operator indicating where to assemble
+     *                     this operator.
      * \tparam Expr        An pre-operator that can be bound to a gridView, or a valid
-     *                      GridOperator.
-     * \tparam row  A tree-path for the RowBasis
-     * \tparam col  A tree-path for the ColBasis
+     *                     GridOperator.
+     * \tparam row         A tree-path for the RowBasis
+     * \tparam col         A tree-path for the ColBasis
      *
      * [[expects: row is valid tree-path in RowBasis]]
      * [[expects: col is valid tree-path in ColBasis]]
+     * @{
      **/
-    // TODO: add method without contextTag.
-    template <class ContextTag, class Expr,
-              class RowTreePath = RootTreePath, class ColTreePath = RootTreePath>
-    void addOperator(ContextTag contextTag, Expr const& expr,
-                     RowTreePath row = {}, ColTreePath col = {});
+    template <class ContextTag, class Expr, class Row, class Col>
+    void addOperator(ContextTag contextTag, Expr const& expr, Row row, Col col);
+
+    // Add an operator to be assembled on the elements of the grid
+    template <class Expr, class Row = RootTreePath, class Col = RootTreePath>
+    void addOperator(Expr const& expr, Row row = {}, Col col = {})
+    {
+      using E = typename RowLocalView::Element;
+      addOperator(tag::element_operator<E>{}, expr, row, col);
+    }
+
+    // Add an operator to be assembled on the intersections of the grid
+    template <class Expr, class Row = RootTreePath, class Col = RootTreePath>
+    void addIntersectionOperator(Expr const& expr, Row row = {}, Col col = {})
+    {
+      using I = typename RowLocalView::GridView::Intersection;
+      addOperator(tag::intersection_operator<I>{}, expr, row, col);
+    }
+    /// @}
 
     /// Assemble the matrix operators on the bound element.
     void assemble(RowLocalView const& rowLocalView,
@@ -103,6 +121,20 @@ namespace AMDiS
     MatrixOperators<RowBasis,ColBasis,ElementMatrix> operators_;
   };
 
+
+#if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
+  template <class RB, class CB, class... Args>
+  BiLinearForm(RB&&, CB&&, Args&&...)
+    -> BiLinearForm<Underlying_t<RB>, Underlying_t<CB>>;
+#endif
+
+  template <class RB, class CB, class... Args>
+  auto makeBiLinearForm(RB&& rowBasis, CB&& colBasis, Args&&... args)
+  {
+    using BLF = BiLinearForm<Underlying_t<RB>, Underlying_t<CB>>;
+    return BLF{FWD(rowBasis), FWD(colBasis), FWD(args)...};
+  }
+
 } // end namespace AMDiS
 
 #include <amdis/BiLinearForm.inc.hpp>
diff --git a/src/amdis/BiLinearForm.inc.hpp b/src/amdis/BiLinearForm.inc.hpp
index 940297e68d64aaaab1fd1c3894de778e62cde771..3e66984c131e9f50243c583a44a1c1165a09107d 100644
--- a/src/amdis/BiLinearForm.inc.hpp
+++ b/src/amdis/BiLinearForm.inc.hpp
@@ -75,7 +75,7 @@ assemble(SymmetryStructure symmetry)
       this->assemble(rowLocalView, colLocalView);
       colLocalView.unbind();
     }
-    rowLocalView.unbind(element);
+    rowLocalView.unbind();
   }
   this->finish();
 }
diff --git a/src/amdis/LinearForm.hpp b/src/amdis/LinearForm.hpp
index 2ecfb4c3817dd20959699c3cd0b3cf56f68fa638..a57ec0f1b0790cbee3bbd57f2382b80dea20bbbe 100644
--- a/src/amdis/LinearForm.hpp
+++ b/src/amdis/LinearForm.hpp
@@ -21,6 +21,7 @@ namespace AMDiS
       : public VectorBase<GB, VectorBackend<BackendTraits<GB,T>>>
   {
     using Super = VectorBase<GB, VectorBackend<BackendTraits<GB,T>>>;
+    using Self = LinearForm;
 
   public:
     using Backend = VectorBackend<BackendTraits<GB,T>>;
@@ -28,6 +29,7 @@ namespace AMDiS
 
     /// The type of the functionspace basis associated to this linearform
     using GlobalBasis = GB;
+    using LocalView = typename GlobalBasis::LocalView;
 
     /// A traits class collecting several parameters of the linear algebra backend
     using Traits = typename Backend::Traits;
@@ -40,9 +42,12 @@ namespace AMDiS
 
   public:
     /// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer.
-    template <class GB_, class Comm_>
-    LinearForm(GB_&& basis, Comm_&& comm)
-      : Super(FWD(basis), FWD(comm))
+    /// The additional arguments can be the communication object. If not provided,
+    /// a new communication is created.
+    template <class GB_, class... Args,
+      Dune::disableCopyMove<Self, GB_, Args...> = 0>
+    explicit LinearForm(GB_&& basis, Args&&... args)
+      : Super(FWD(basis), FWD(args)...)
     {
       operators_.init(*Super::basis());
     }
@@ -57,12 +62,47 @@ namespace AMDiS
       elementVector_.resize(localSize);
     }
 
-    /// Associate a local operator with this LinearForm
-    template <class ContextTag, class Expr, class TreePath = RootTreePath>
-    void addOperator(ContextTag contextTag, Expr const& expr, TreePath path = {});
+    /// \brief Associate a local operator with this LinearForm
+    /**
+     * Stores an operator in a list that gets assembled during a call to \ref assemble().
+     * The operator may be assigned to a specific context, i.e. either an element
+     * operator, an intersection operator, or a boundary operator.
+     * The \p path tree paths specify the sub-basis for test functions the operator
+     * is applied to.
+     *
+     * \tparam ContextTag  One of \ref tag::element_operator, \ref tag::intersection_operator
+     *                     or \ref tag::boundary_operator indicating where to assemble
+     *                     this operator.
+     * \tparam Expr        An pre-operator that can be bound to a gridView, or a valid
+     *                     GridOperator.
+     * \tparam path        A tree-path for the Basis
+     *
+     * [[expects: path is valid tree-path in Basis]]
+     * @{
+     **/
+    template <class ContextTag, class Expr, class TreePath>
+    void addOperator(ContextTag contextTag, Expr const& expr, TreePath path);
+
+    // Add an operator to be assembled on the elements of the grid
+    template <class Expr, class TreePath = RootTreePath>
+    void addOperator(Expr const& expr, TreePath path = {})
+    {
+      using E = typename LocalView::Element;
+      addOperator(tag::element_operator<E>{}, expr, path);
+    }
+
+    // Add an operator to be assembled on the intersections of the grid
+    template <class Expr, class TreePath = RootTreePath>
+    void addIntersectionOperator(Expr const& expr, TreePath path = {})
+    {
+      using I = typename LocalView::GridView::Intersection;
+      addOperator(tag::intersection_operator<I>{}, expr, path);
+    }
+    /// @}
+
 
     /// Assemble the vector operators on the bound element.
-    void assemble(typename GB::LocalView const& localView);
+    void assemble(LocalView const& localView);
 
     /// Assemble all vector operators added by \ref addOperator().
     void assemble();
@@ -75,12 +115,20 @@ namespace AMDiS
     VectorOperators<GlobalBasis,ElementVector> operators_;
   };
 
+
 #if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
-  template <class GB, class C>
-  LinearForm(GB&& basis, C const& comm)
-    -> LinearForm<Underlying_t<GB>, VectorBackend<BackendTraits<Underlying_t<GB>>> >;
+  template <class GB, class... Args>
+  LinearForm(GB&& basis, Args&&... args)
+    -> LinearForm<Underlying_t<GB>, double>;
 #endif
 
+  template <class T = double, class GB, class... Args>
+  auto makeLinearForm(GB&& basis, Args&&... args)
+  {
+    using LF = LinearForm<Underlying_t<GB>, T>;
+    return LF{FWD(basis), FWD(args)...};
+  }
+
 } // end namespace AMDiS
 
 #include <amdis/LinearForm.inc.hpp>
diff --git a/src/amdis/linearalgebra/MatrixBase.hpp b/src/amdis/linearalgebra/MatrixBase.hpp
index 9348984b6862b6799a8dc9ea5beb9fcafdcc3ce6..601330327a3f88fd5b8854ad1013bbbcb7308999 100644
--- a/src/amdis/linearalgebra/MatrixBase.hpp
+++ b/src/amdis/linearalgebra/MatrixBase.hpp
@@ -36,25 +36,41 @@ namespace AMDiS
     using ColBasis = CB;
     using ColLocalView = typename ColBasis::LocalView;
 
-    /// The Linear-Aglebra backend used to store the assembled coefficients
+    /// The Linear-Algebra backend used to store the assembled coefficients
     using Backend = B;
-
-  private:
     using Comm = typename B::Traits::Comm;
 
   public:
-    /// Constructor. Stores the shared_ptr to the bases.
-    MatrixBase(std::shared_ptr<RowBasis> rowBasis, std::shared_ptr<ColBasis> colBasis, std::shared_ptr<Comm> comm)
+    /// (1) Constructor. Stores the shared_ptr to the bases and the communication object.
+    MatrixBase(std::shared_ptr<RB> rowBasis, std::shared_ptr<CB> colBasis,
+               std::shared_ptr<Comm> comm)
       : rowBasis_(std::move(rowBasis))
       , colBasis_(std::move(colBasis))
       , backend_(std::move(comm))
     {}
 
-    /// Constructor. Wraps the reference into a non-destroying shared_ptr or moves the basis into a new shared_ptr.
+    /// (2) Constructor. Forwards to (1) by wraping reference into non-destroying
+    /// shared_ptr, see \ref Dune::wrap_or_move.
     template <class RB_, class CB_, class Comm_,
-      REQUIRES(Concepts::Similar<RB_,RB> && Concepts::Similar<CB_,CB> && Concepts::Similar<Comm_,Comm>)>
+      REQUIRES(Concepts::Similar<Types<RB_,CB_,Comm_>, Types<RB,CB,Comm>>)>
     MatrixBase(RB_&& rowBasis, CB_&& colBasis, Comm_&& comm)
-      : MatrixBase(Dune::wrap_or_move(FWD(rowBasis)), Dune::wrap_or_move(FWD(colBasis)), Dune::wrap_or_move(FWD(comm)))
+      : MatrixBase(Dune::wrap_or_move(FWD(rowBasis)),
+                   Dune::wrap_or_move(FWD(colBasis)),
+                   Dune::wrap_or_move(FWD(comm)))
+    {}
+
+    /// (3) Constructor. Forwards to (1) by creating a new communicator
+    MatrixBase(std::shared_ptr<RB> const& rowBasis, std::shared_ptr<CB> const& colBasis)
+      : MatrixBase(rowBasis, colBasis,
+                   std::shared_ptr<Comm>(CommunicationCreator<Comm>::create(*rowBasis)))
+    {}
+
+    /// (4) Constructor. Forwards to (3) by wrapping references into non-destroying
+    /// shared_ptr, see \ref Dune::wrap_or_move.
+    template <class RB_, class CB_,
+      REQUIRES(Concepts::Similar<Types<RB_,CB_>, Types<RB,CB>>)>
+    MatrixBase(RB_&& rowBasis, CB_&& colBasis)
+      : MatrixBase(Dune::wrap_or_move(FWD(rowBasis)), Dune::wrap_or_move(FWD(colBasis)))
     {}
 
     /// Return the row-basis \ref rowBasis of the matrix
@@ -69,20 +85,15 @@ namespace AMDiS
       return colBasis_;
     }
 
-    Backend& backend()
-    {
-      return backend_;
-    }
-
-    Backend const& backend() const
-    {
-      return backend_;
-    }
+    /// Return the underlying linear algebra backend
+    Backend const& backend() const { return backend_; }
+    Backend&       backend()       { return backend_; }
 
     /// \brief Initialize the matrix for insertion, i.e. allocate the non-zero pattern
     /**
      * With the optional parameter \p symmetry some additional information about the
-     * structure of the values or the sparsity pattern can be provided. See \ref SymmetryStructure.
+     * structure of the values or the sparsity pattern can be provided.
+     * See \ref SymmetryStructure.
      **/
     void init(SymmetryStructure symmetry = SymmetryStructure::unknown)
     {
@@ -111,7 +122,9 @@ namespace AMDiS
       assert(r.size() == localMatrix.rows());
       assert(c.size() == localMatrix.cols());
 
-      const bool optimized = std::is_same<RowLocalView,ColLocalView>::value && r.tree().treeIndex() == c.tree().treeIndex();
+      const bool optimized = std::is_same<RowLocalView,ColLocalView>::value
+        && r.tree().treeIndex() == c.tree().treeIndex();
+
       if (optimized)
         backend_.scatter(nodeIndices(r), localMatrix);
       else
diff --git a/src/amdis/linearalgebra/VectorBase.hpp b/src/amdis/linearalgebra/VectorBase.hpp
index 4f69608047c186d8fbebe5ed7b1e72b1f2560870..36a55ad16480943166b6f967d0f69b7512a5938b 100644
--- a/src/amdis/linearalgebra/VectorBase.hpp
+++ b/src/amdis/linearalgebra/VectorBase.hpp
@@ -26,8 +26,8 @@ namespace AMDiS
 {
   /// \brief The basic container that stores a base vector and a corresponding basis
   /**
-   * A vector storing all the assembled Operators indexed with DOF indices. The vector
-   * data is associated to a global basis.
+   * A vector storing all the assembled Operators indexed with DOF indices. The
+   * vector data is associated to a global basis.
    *
    * \tparam GB  Basis of the vector
    * \tparam B   A linear algebra backend implementing the storage and operations.
@@ -42,16 +42,15 @@ namespace AMDiS
     using GlobalBasis = GB;
     using LocalView = typename GlobalBasis::LocalView;
 
-    /// The Linear-Aglebra backend used to store the assembled coefficients
+    /// The Linear-Algebra backend used to store the assembled coefficients
     using Backend = B;
+    using Comm = typename B::Traits::Comm;
 
   private:
-    // proxy class redirecting the mutable element access to the inserValue method
+    // proxy class redirecting the mutable element access to the insertValue method
     template <class Index>
     struct AccessProxy;
 
-    using Comm = typename B::Traits::Comm;
-
     enum class VectorState
     {
       unknown = 0,
@@ -66,7 +65,7 @@ namespace AMDiS
       std::integral_constant<VectorState, VectorState::insert_values>>;
 
   public:
-    /// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer.
+    /// (1) Constructor. Stores the shared_ptr of the basis and communication object.
     VectorBase(std::shared_ptr<GB> basis, std::shared_ptr<Comm> comm)
       : basis_(std::move(basis))
       , comm_(std::move(comm))
@@ -75,15 +74,27 @@ namespace AMDiS
       resizeZero();
     }
 
-    /// Constructor. Wraps the reference into a non-destroying shared_ptr or moves
-    /// the basis into a new shared_ptr.
+    /// (2) Constructor. Forwards to (1) by wraping reference into non-destroying
+    /// shared_ptr.
     template <class GB_, class Comm_,
-      REQUIRES(Concepts::Similar<GB_,GB>),
-      REQUIRES(Concepts::Similar<Comm_,Comm>)>
+      REQUIRES(Concepts::Similar<Types<GB_,Comm_>, Types<GB,Comm>>)>
     VectorBase(GB_&& basis, Comm_&& comm)
       : VectorBase(Dune::wrap_or_move(FWD(basis)), Dune::wrap_or_move(FWD(comm)))
     {}
 
+    /// (3) Constructor. Forwards to (1) by creating a new communicator
+    explicit VectorBase(std::shared_ptr<GB> const& basis)
+      : VectorBase(basis, std::shared_ptr<Comm>(CommunicationCreator<Comm>::create(*basis)))
+    {}
+
+    /// (4) Constructor. Forwards to (3) by wrapping references into non-destroying
+    /// shared_ptr, see \ref Dune::wrap_or_move.
+    template <class GB_,
+      REQUIRES(Concepts::Similar<GB_,GB>)>
+    explicit VectorBase(GB_&& basis)
+      : VectorBase(Dune::wrap_or_move(FWD(basis)))
+    {}
+
     /// Return the basis \ref basis_ associated to the vector
     std::shared_ptr<GlobalBasis> const& basis() const { return basis_; }
     std::shared_ptr<GlobalBasis> const& basis()       { return basis_; }
@@ -157,7 +168,8 @@ namespace AMDiS
       return at(idx);
     }
 
-    /// Access the entry \p i of the \ref vector with write-access. Uses a proxy class the redirects to \ref insertValue.
+    /// Access the entry \p i of the \ref vector with write-access. Uses a proxy
+    /// class the redirects to \ref insertValue.
     template <class Index>
     AccessProxy<Index> DUNE_DEPRECATED_MSG("Do not use element-wise vector access")
     operator[](Index const& idx)
@@ -176,10 +188,10 @@ namespace AMDiS
 
     /// \brief Insert a single value into the matrix (add or overwrite to existing value)
     /**
-     * Inserts or adds a value into a certain location \p dof (given as dof multi-index) of a vector.
-     * The insertion mode is determined by the \p assign functor. Use \ref Assigner::plus_assign for
-     * adding values (default) or \ref Assigner::assign for overwriting (setting) values. Different
-     * insertion modes can not be mixed!
+     * Inserts or adds a value into a certain location \p dof (given as dof multi-index)
+     * of a vector. The insertion mode is determined by the \p assign functor. Use
+     * \ref Assigner::plus_assign for adding values (default) or \ref Assigner::assign
+     * for overwriting (setting) values. Different insertion modes can not be mixed!
      *
      * Insertion must be closed with a call to \ref finish().
      *
@@ -214,13 +226,15 @@ namespace AMDiS
     }
 
 
-    /// \brief Extract values from the vector referring to the given local indices and store it into a buffer
+    /// \brief Extract values from the vector referring to the given local indices
+    /// and store it into a buffer
     /**
-     * Collect value of indices and store them into a buffer. The buffer must be a vector-like container
-     * with `buffer.resize()` and `buffer.begin()`. The indices must be stored in an iterable container.
+     * Collect value of indices and store them into a buffer. The buffer must be
+     * a vector-like container with `buffer.resize()` and `buffer.begin()`. The
+     * indices must be stored in an iterable container.
      *
-     * If the vector is not in synchronized state, collects all necessary values possibly from
-     * neighbouring processors.
+     * If the vector is not in synchronized state, collects all necessary values
+     * possibly from neighbouring processors.
      *
      * [[expects: localView is bound to an element]]
      * [[expects: node is in localView.tree()]]
@@ -249,18 +263,19 @@ namespace AMDiS
 
     /// Insert a block of values into the vector (add or overwrite to existing values)
     /**
-     * Inserts or adds values into certain locations of a vector. Insertion indices are extracted from
-     * the given \p localView. The insertion mode is determined by the \p assign functor. Use
-     * \ref Assigner::plus_assign for adding values (default) or \ref Assigner::assign for overwriting
-     * (setting) values. Different insertion modes can not be mixed! The \p localVector is assumed
-     * to be a continuous memory container with a `data()` method to get a pointer to the beginning.
+     * Inserts or adds values into certain locations of a vector. Insertion indices
+     * are extracted from the given \p localView. The insertion mode is determined
+     * by the \p assign functor. Use \ref Assigner::plus_assign for adding values
+     * (default) or \ref Assigner::assign for overwriting (setting) values. Different
+     * insertion modes can not be mixed! The \p localVector is assumed to be a continuous
+     * memory container with a `data()` method to get a pointer to the beginning.
      *
-     * The \p mask models a boolean range with at least a `begin()` method. Must be forward iterable
-     * for at least `localVector.size()` elements. Does not need an `end()` method. See, e.g.
-     * \ref FakeContainer.
+     * The \p mask models a boolean range with at least a `begin()` method. Must
+     * be forward iterable for at least `localVector.size()` elements. Does not
+     * need an `end()` method. See, e.g. \ref FakeContainer.
      *
-     * Insertion must be closed with a call to \ref finish(). It is not allowed to switch insertion
-     * mode before calling `finish()`.
+     * Insertion must be closed with a call to \ref finish(). It is not allowed
+     * to switch insertion mode before calling `finish()`.
      *
      * [[expects: localView is bound to an element]]
      * [[expects: node is in localView.tree()]]
@@ -338,8 +353,8 @@ namespace AMDiS
 
     /// Apply \p func to each value at given indices \p localInd
     /**
-     * First, synchronizes the values of the vector, then applies the functor to each local value
-     * associated to the local indices \p localInd.
+     * First, synchronizes the values of the vector, then applies the functor to
+     * each local value associated to the local indices \p localInd.
      *
      * [[mutable]]
      **/
@@ -361,8 +376,8 @@ namespace AMDiS
 
     /// Apply \p func to each value at given indices \p localInd
     /**
-     * First, synchronizes the values of the vector, then applies the functor to each local value
-     * associated to the local indices \p localInd.
+     * First, synchronizes the values of the vector, then applies the functor to
+     * each local value associated to the local indices \p localInd.
      *
      * [[const]]
      **/
@@ -414,7 +429,8 @@ namespace AMDiS
     /// Data backend
     Backend backend_;
 
-    /// The current state of the vector, one of {synchronized, insert_values, add_values, unknown}
+    /// The current state of the vector, one of {synchronized, insert_values,
+    /// add_values, unknown}
     VectorState state_ = VectorState::unknown;
   };