diff --git a/dune/fem-dg/operator/dg/dgmasspass.hh b/dune/fem-dg/operator/dg/dgmasspass.hh
new file mode 100644
index 0000000000000000000000000000000000000000..db881ef8a7aecd754962aea33163922d11d2944f
--- /dev/null
+++ b/dune/fem-dg/operator/dg/dgmasspass.hh
@@ -0,0 +1,513 @@
+#ifndef DUNE_FEM_DG_MASS_INVERSE_PASS_HH
+#define DUNE_FEM_DG_MASS_INVERSE_PASS_HH
+
+#include <cassert>
+#include <iosfwd>
+#include <sstream>
+
+#include <dune/common/typetraits.hh>
+
+#include <dune/fem/common/tupleutility.hh>
+#include <dune/fem/pass/common/local.hh>
+#include <dune/fem/quadrature/cachingquadrature.hh>
+#include <dune/fem/pass/dginversemass.hh>
+
+namespace Dune
+{
+
+  namespace Fem
+  {
+
+    // DGMassInverseMassPass
+    // ---------------------
+
+    /** \brief Pass applying the local inverse mass matrix on each element
+     *
+     *  \tparam  functionalId   pass id of functional to convert
+     *  \tparam  PreviousPass   type of previous pass
+     *  \tparam  id             pass id
+     */
+    template< class ScalarDiscreteFunctionSpace, bool inverse >
+    class DGMassInverseMassImplementation
+    {
+    public:
+      dune_static_assert((ScalarDiscreteFunctionSpace::dimRange == 1), "dimRange of ScalarSpace > 1");
+      //! \brief discrete function space type
+      typedef ScalarDiscreteFunctionSpace ScalarDiscreteFunctionSpaceType ;
+      typedef typename ScalarDiscreteFunctionSpaceType::RangeType ScalarRangeType;
+      typedef typename ScalarDiscreteFunctionSpaceType::GridPartType GridPartType;
+
+      static const int numScalarBasis = ScalarDiscreteFunctionSpaceType :: localBlockSize ;
+
+      class Key
+      {
+      protected:  
+        const GridPartType & gridPart_;
+        const int numScalarBasis_;
+        const bool inverse_ ;
+      public:
+        //! constructor taking space 
+        Key(const GridPartType& gridPart)
+          : gridPart_(gridPart),
+            numScalarBasis_( numScalarBasis ),
+            inverse_( inverse ) {}
+
+        //! copy constructor  
+        //! returns true if indexSet pointer and numDofs are equal 
+        bool operator == (const Key& otherKey) const
+        {
+          // mapper of space is singleton 
+          return (&(gridPart_.indexSet()) == & (otherKey.gridPart_.indexSet()) ) 
+                 && ( numScalarBasis_ == otherKey.numScalarBasis_ ) && ( inverse_ == otherKey.inverse_ );
+        }
+
+        //! return reference to grid part for construction 
+        const GridPartType& gridPart() const { return gridPart_; }
+      };
+      typedef Key KeyType;
+
+    private:
+      typedef typename ScalarDiscreteFunctionSpaceType :: RangeFieldType  ctype;
+      typedef Dune::FieldMatrix< ctype, numScalarBasis, numScalarBasis > LocalMatrixType ;
+
+      typedef Fem::CachingQuadrature< GridPartType, 0 > VolumeQuadratureType;
+
+      typedef typename GridPartType::template Codim< 0 >::EntityType EntityType;
+
+      typedef typename ScalarDiscreteFunctionSpaceType :: BasisFunctionSetType  BasisFunctionSetType ;
+
+      typedef typename EntityType :: Geometry  Geometry ;
+      typedef typename Geometry :: GlobalCoordinate  GlobalCoordinate ;
+
+      typedef LocalMassMatrix< ScalarDiscreteFunctionSpaceType, VolumeQuadratureType > LocalMassMatrixType ;
+      typedef LocalMassMatrixImplementationDgOrthoNormal<
+            ScalarDiscreteFunctionSpaceType, VolumeQuadratureType >  DgOrthoNormalMassMatrixType ;
+
+      static const bool isOrthoNormal = false ; //Conversion< LocalMassMatrixType, DgOrthoNormalMassMatrixType > :: exists ; 
+
+      struct VectorEntry 
+      {
+        LocalMatrixType  matrix_ ;
+        GlobalCoordinate center_ ;
+        VectorEntry () : matrix_( 0 ), center_( std::numeric_limits< double > :: max() )
+        {}
+      };
+
+      typedef std::vector< VectorEntry* >      MatrixStorageType;
+
+    public:
+      template <class Key> 
+      explicit DGMassInverseMassImplementation ( const Key& key ) 
+      : scalarSpace_( const_cast< GridPartType& > (key.gridPart()) ),
+        volumeQuadratureOrder_( 2 * scalarSpace_.order() ),
+        matrices_( Fem :: ThreadManager :: maxThreads() ),
+        localMassMatrix_( scalarSpace_ ),
+        sequence_( -1 )
+      {
+        assert( Fem::ThreadManager::singleThreadMode() );
+        setup();
+      }
+
+      ~DGMassInverseMassImplementation () 
+      {
+        const int maxThreads = Fem :: ThreadManager :: maxThreads() ;
+        for( int thread = 0; thread < maxThreads ; ++ thread ) 
+        {
+          for( size_t i=0; i<matrices_[ thread ].size(); ++i ) 
+            delete matrices_[ thread ][ i ];
+        }
+      }
+
+      //! interface method 
+      template < class DestinationType >
+      void prepare( const DestinationType& argument, DestinationType &destination, const bool doSetup ) const
+      {
+        if( doSetup ) 
+          setup();
+      }
+
+      //! interface method 
+      template < class DestinationType >
+      void finalize( const DestinationType &argument, DestinationType &destination ) const
+      {
+      }
+
+      //! apply inverse mass matrix locally 
+      template < class DestinationType >
+      void applyLocal( const EntityType& entity, 
+                       const DestinationType& argument,
+                       DestinationType& destination ) const 
+      {
+        typedef typename DestinationType :: LocalFunctionType LocalFunctionType;
+        const Geometry& geometry = entity.geometry();
+        LocalFunctionType localDest = destination.localFunction( entity );
+        const LocalFunctionType localArg = argument.localFunction( entity );
+        if( isOrthoNormal && geometry.affine() )
+        {
+          // get inverse mass factor 
+          const double massFactorInv = localMassMatrix_.getAffineMassFactor( geometry );
+          const double factor = ( ! inverse ) ? massFactorInv : 1.0/massFactorInv ;
+
+          // apply factor * localArg and store in dest
+          localDest.axpy( factor, localArg );
+        }
+        else 
+        {
+          const int idx = scalarSpace_.gridPart().indexSet().index( entity );
+          const int thread = setup( idx, entity, geometry );
+          enum { dimRange = DestinationType :: DiscreteFunctionSpaceType :: dimRange };
+          assert( matrices_[ thread ][ idx ] );
+          multiplyBlock( dimRange, matrices_[ thread ][ idx ]->matrix_, localArg, localDest );
+        }
+      }
+
+      //! apply inverse mass matrix to local function 
+      template< class LocalFunction >
+      void applyInverse( LocalFunction& localDest ) const 
+      {
+        enum { dimRange = LocalFunction :: dimRange };
+        const EntityType& entity = localDest.entity();
+        const int idx = scalarSpace_.gridPart().indexSet().index( entity );
+        const Geometry& geometry = entity.geometry();
+
+        const int thread = setup( idx, entity, geometry );
+
+        static const int numBasis = dimRange * numScalarBasis ;
+        assert( localDest.numDofs() == numBasis );
+
+        // vector holding basis function evaluation 
+        Dune::array< ctype, numBasis > lfX;
+        for( int i=0; i<numBasis; ++i )
+          lfX[ i ] = localDest[ i ];
+
+        assert( matrices_[ thread ][ idx ] );
+        multiplyBlock( dimRange, matrices_[ thread ][ idx ]->matrix_, lfX, localDest );
+      }
+
+      template < class DestinationType >
+      void compute ( const DestinationType& argument, DestinationType &destination ) const
+      {
+        // make sure this method is not called in multi thread mode
+        assert( Fem :: ThreadManager :: singleThreadMode() );
+
+        // set pointer
+        prepare( argument, destination, true );
+
+        typedef typename GridPartType::template Codim< 0 >::template Partition< All_Partition >::IteratorType IteratorType;
+        const GridPartType &gridPart = scalarSpace_.gridPart();
+        const IteratorType end = gridPart.template end< 0, All_Partition >();
+        for( IteratorType it = gridPart.template begin< 0, All_Partition >(); it != end; ++it )
+        {
+          applyLocal( *it, argument, destination );
+        }
+
+        // remove pointer
+        finalize( argument, destination );
+      }
+    protected:
+      template < class ConstLocalFunction, class LocalFunctionType >
+      void multiplyBlock( const int dimRange, 
+                          const LocalMatrixType& matrix, 
+                          const ConstLocalFunction& arg, 
+                          LocalFunctionType& dest ) const 
+      {
+        // clear destination
+        dest.clear();
+        
+        static const int rows = LocalMatrixType::rows;
+        static const int cols = LocalMatrixType::cols;
+
+        assert( int(rows * dimRange) == dest.numDofs() );
+
+        // apply matrix to arg and store in dest 
+        for(int i=0; i<rows; ++i ) 
+        {
+          for(int j=0; j<cols; ++j ) 
+          {
+            for( int r=0, ir = i * dimRange, jr = j * dimRange ; 
+                 r<dimRange; ++ r, ++ ir, ++ jr )
+            {
+              dest[ ir ] += matrix[ i ][ j ] * arg[ jr ] ;
+            }
+          }
+        }
+      }
+
+      void setup() const
+      {
+        assert( Fem :: ThreadManager :: singleThreadMode() );
+        const int gpSequence = scalarSpace_.gridPart().sequence();
+        if( sequence_ != gpSequence ) 
+        {
+          const GridPartType &gridPart = scalarSpace_.gridPart();
+          const int gpSize = gridPart.indexSet().size( 0 ) ;
+          const int maxThreads = Fem :: ThreadManager :: maxThreads() ;
+          for( int thread = 0; thread < maxThreads ; ++ thread ) 
+          {
+            matrices_[ thread ].resize( gpSize, (VectorEntry *) 0 );
+          }
+          sequence_ = gpSequence ;
+        }
+      }
+
+      int setup( const int idx, 
+                 const EntityType& entity, 
+                 const Geometry& geometry ) const 
+      {
+        const int thread = Fem :: ThreadManager :: thread();
+        bool computeMatrix = false ;
+        if( matrices_[ thread ][ idx ] == 0 ) 
+        {
+          VectorEntry* entry = new VectorEntry();
+          matrices_[ thread ][ idx ] = entry;
+          entry->center_ = geometry.center();
+          computeMatrix = true ;
+
+        }
+        else 
+        {
+          VectorEntry* entry = matrices_[ thread ][ idx ] ;
+          const GlobalCoordinate center = geometry.center();
+          GlobalCoordinate diff ( center );
+          diff -= entry->center_;
+          // for cells on the boundary we have to compute this all the time 
+          computeMatrix = diff.infinity_norm() > 1e-12 ;
+          if( computeMatrix ) entry->center_ = center ;
+        }
+
+        if( computeMatrix )
+        {
+          VectorEntry* entry = matrices_[ thread ][ idx ];
+          setup( idx, entity, 
+                 geometry,
+                 scalarSpace_.basisFunctionSet( entity ), 
+                 entry->matrix_ );
+        }
+        return thread ;
+      }
+
+      void setup( const int idx, 
+                  const EntityType& entity, 
+                  const Geometry& geo,
+                  const BasisFunctionSetType& set,
+                  LocalMatrixType& matrix ) const
+      {
+        // clear matrix 
+        matrix = 0;
+
+        // vector holding basis function evaluation 
+        Dune::array< ScalarRangeType, numScalarBasis > phi ;
+
+        // make sure that the number of basis functions is correct 
+        assert( numScalarBasis == int(set.size()) );
+        
+        // create appropriate quadrature 
+        VolumeQuadratureType volQuad( entity, volumeQuadratureOrder_ );
+
+        const int volNop = volQuad.nop();
+        for(int qp=0; qp<volNop; ++qp)
+        {
+          // calculate integration weight
+          const double intel = ( volQuad.weight(qp) * geo.integrationElement(volQuad.point(qp)) );
+
+          // eval basis functions
+          set.evaluateAll(volQuad[ qp ], phi);
+
+          for(int m=0; m<numScalarBasis; ++m)
+          {
+            const ScalarRangeType& phi_m = phi[ m ];
+            const ctype val = intel * (phi_m * phi_m);
+            matrix[ m ][ m ] += val;
+
+            for(int k=m+1; k<numScalarBasis; ++k)
+            {
+              const ctype val = intel * (phi_m * phi[ k ]);
+              matrix[ m ][ k ] += val;
+              matrix[ k ][ m ] += val;
+            }
+          }
+        }
+
+        for(int m=0; m<numScalarBasis; ++m)
+        {
+          for(int k=0; k<numScalarBasis; ++k)
+          {
+            if( std::abs( matrix[ m ][ k ] ) < 1e-14 ) 
+              matrix[ m ][ k ] = 0;
+          }
+        }
+
+        // if we are looking for the inverse, then invert matrix 
+        if( inverse ) 
+          matrix.invert();
+      }
+
+    protected:
+      ScalarDiscreteFunctionSpaceType          scalarSpace_;
+      const int                                volumeQuadratureOrder_;
+      mutable std::vector< MatrixStorageType > matrices_;
+
+      LocalMassMatrixType                      localMassMatrix_;
+
+      mutable int                              sequence_ ;
+    };
+
+
+    /** \brief Pass applying the local inverse mass matrix on each element
+     *
+     *  \tparam  functionalId   pass id of functional to convert
+     *  \tparam  PreviousPass   type of previous pass
+     *  \tparam  id             pass id
+     */
+    template< int functionalId, class PreviousPass, int id, bool inverse >
+    class DGMassInverseMassPass
+    : public Dune::Fem::LocalPass< DGInverseMassPassDiscreteModel< functionalId, PreviousPass >, PreviousPass, id >
+    {
+      typedef DGMassInverseMassPass< functionalId, PreviousPass, id, inverse > ThisType;
+      typedef Dune::Fem::LocalPass< DGInverseMassPassDiscreteModel< functionalId, PreviousPass >, PreviousPass, id > BaseType;
+
+    public:
+      //! type of the discrete model used 
+      typedef DGInverseMassPassDiscreteModel< functionalId, PreviousPass > DiscreteModelType;
+
+      //! pass ids up to here (tuple of integral constants)
+      typedef typename BaseType::PassIds PassIds;
+
+      //! \brief argument type
+      typedef typename BaseType::TotalArgumentType TotalArgumentType;
+      //! \brief destination type
+      typedef typename BaseType::DestinationType DestinationType;
+
+      //! \brief discrete function space type
+      typedef typename DiscreteModelType::Traits::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
+
+      // type of communication manager object which does communication
+      typedef typename DiscreteFunctionSpaceType::template ToNewDimRange< 1 >::Type ScalarDiscreteFunctionSpaceType;
+      typedef DGMassInverseMassImplementation< ScalarDiscreteFunctionSpaceType, inverse > MassInverseMassType ;
+      typedef typename MassInverseMassType :: KeyType KeyType;
+      typedef Fem::SingletonList< KeyType, MassInverseMassType >  MassInverseMassProviderType;
+
+    private:
+      static const std::size_t functionalPosition = DiscreteModelType::functionalPosition;
+
+      typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
+      typedef typename GridPartType::template Codim< 0 >::EntityType EntityType;
+
+      typedef typename DestinationType :: LocalFunctionType    LocalFunctionType;
+
+    public:
+      using BaseType::passNumber;
+      using BaseType::space;
+
+      explicit DGMassInverseMassPass ( PreviousPass &previousPass,
+                                       const DiscreteFunctionSpaceType &spc )
+      : BaseType( previousPass, spc, "DGMassInverseMassPass" ),
+        massInverseMass_( MassInverseMassProviderType :: getObject( KeyType( spc.gridPart() ) ) ),
+        arg_( 0 ),
+        dest_( 0 )
+      {
+      }
+
+      //! constructor for use with thread pass 
+      DGMassInverseMassPass ( const DiscreteModelType& discreteModel, 
+                              PreviousPass &previousPass,
+                              const DiscreteFunctionSpaceType &spc,
+                              const int volQuadOrd  = -1, 
+                              const int faceQuadOrd = -1)
+      : BaseType( previousPass, spc, "DGMassInverseMassPass" ),
+        massInverseMass_( MassInverseMassProviderType :: getObject( KeyType( spc.gridPart() ) ) ),
+        arg_( 0 ),
+        dest_( 0 )
+      {
+      }
+
+      ~DGMassInverseMassPass() { MassInverseMassProviderType :: removeObject( massInverseMass_ ); }
+
+      void printTexInfo ( std::ostream &out ) const
+      {
+        BaseType::printTexInfo( out );
+        out << "DGMassInverseMassPassname() :" << "\\\\" << std::endl;
+      }
+
+      //! this pass needs no communication 
+      bool requireCommunication () const { return false ; }
+
+      //! interface method 
+      void prepare( const TotalArgumentType &argument, DestinationType &destination ) const
+      {
+        prepare( argument, destination, true );
+      }
+
+      //! prepare for ThreadPass 
+      void prepare( const TotalArgumentType &argument, DestinationType &destination, const bool doSetup ) const
+      {
+        arg_  = &argument ;
+        dest_ = &destination;
+        massInverseMass_.prepare( *(Dune::get< functionalPosition >( argument )), destination, doSetup );
+      }
+
+      //! finalize for ThreadPass 
+      void finalize( const TotalArgumentType &argument, DestinationType &destination, const bool ) const
+      {
+        finalize( argument, destination );
+      }
+
+      //! interface method 
+      void finalize( const TotalArgumentType &argument, DestinationType &destination ) const
+      {
+        massInverseMass_.finalize( *(Dune::get< functionalPosition >( argument )), destination );
+        arg_  = 0;
+        dest_ = 0;
+      }
+
+      //! apply inverse mass matrix locally 
+      void applyLocal( const EntityType& entity ) const 
+      {
+        assert( arg_  );
+        assert( dest_ );
+        massInverseMass_.applyLocal( entity, *(Dune::get< functionalPosition >( *arg_ )), *dest_ );
+      }
+
+      //! apply local with neighbor checker (not needed here)
+      template <class NBChecker>
+      void applyLocal( const EntityType& entity, const NBChecker& ) const 
+      {
+        applyLocal( entity );
+      }
+
+      /** \brief  apply local for all elements that do not need information from 
+       *          other processes (here all elements)
+       */         
+      template <class NBChecker>
+      void applyLocalInterior( const EntityType& entity, const NBChecker& ) const 
+      {
+        applyLocal( entity );
+      }
+
+      /** \brief  apply local for all elements that need information from 
+       *          other processes (here no elements)
+       */         
+      template <class NBChecker>
+      void applyLocalProcessBoundary( const EntityType& entity, const NBChecker& ) const 
+      {
+        DUNE_THROW(InvalidStateException,"DGInverseMassPass does not need a second phase for ThreadPass");
+      }
+
+    protected:
+      void compute ( const TotalArgumentType &argument, DestinationType &destination ) const
+      {
+        massInverseMass_.compute( *(Dune::get< functionalPosition >( argument )), destination );
+      }
+
+    protected:
+      MassInverseMassType& massInverseMass_ ;
+
+      mutable const TotalArgumentType* arg_ ;
+      mutable DestinationType*   dest_;
+    };
+
+  } // namespace Fem
+
+} // namespace Dune
+
+#endif // #ifndef DUNE_FEM_PASS_APPLYLOCALOPERATOR_HH