diff --git a/dune/fem-dg/misc/Makefile.am b/dune/fem-dg/misc/Makefile.am
index 5417c1d5e48169fc732d65c20915e99b6785dbf2..969ed3789ad33df58d641e8d822cf5dade01bad2 100644
--- a/dune/fem-dg/misc/Makefile.am
+++ b/dune/fem-dg/misc/Makefile.am
@@ -1,4 +1,4 @@
 miscdir = $(includedir)/dune/fem-dg/misc
-misc_HEADERS = diagnostics.hh cons2prim.hh streams.hh
+misc_HEADERS = diagnostics.hh cons2prim.hh crs.hh streams.hh
 
 include $(top_srcdir)/am/global-rules
diff --git a/dune/fem-dg/misc/crs.hh b/dune/fem-dg/misc/crs.hh
new file mode 100644
index 0000000000000000000000000000000000000000..44ce49d4a8a7363a3c4ea9bbef3b4cdd08bf41bc
--- /dev/null
+++ b/dune/fem-dg/misc/crs.hh
@@ -0,0 +1,148 @@
+#ifndef DUNE_CRSMATRIX_HH
+#define DUNE_CRSMATRIX_HH
+
+#include <cmath>
+#include <cstddef>
+#include <iostream>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/fvector.hh>
+#include <dune/common/densematrix.hh>
+#include <dune/common/precision.hh>
+#include <dune/common/static_assert.hh>
+#include <dune/common/std/constexpr.hh>
+
+namespace Dune
+{
+
+  namespace Fem {
+
+
+  template<class K, int ROWS, int COLS>
+  class BlockCRSMatrix 
+  {
+    std::vector< double > data_;
+    std::vector< int > rows_;
+    std::vector< int > cols_;
+  public:
+
+    //! export size
+    enum {
+      //! The number of rows.
+      rows = ROWS,
+      //! The number of columns.
+      cols = COLS
+    };
+
+    typedef K Field; 
+    typedef K value_type ;
+
+    typedef std::vector< value_type > row_type ;
+
+    //===== constructors
+    /** \brief Default constructor
+     */
+    BlockCRSMatrix ()
+     : data_(), rows_(rows + 1, int(0) ), cols_() {}
+
+    BlockCRSMatrix ( const BlockCRSMatrix& other )
+     : data_( other.data_ ), rows_( other.rows_ ), cols_( other.cols_ ) {}
+
+    template <class Matrix>
+    void set( const Matrix& matrix ) 
+    {
+      data_.clear();
+      cols_.clear();
+
+      assert( matrix.size() == rows );
+
+      int count = 0;
+      for( int row=0; row<rows; ++row ) 
+        for( int col=0; col<cols; ++col )
+          if( std::abs( matrix[ row ][ col ] ) > 0.0 )
+            ++ count; 
+
+      data_.resize( count, Field( 0 ) );
+      cols_.resize( count, int( 0 ) );
+
+      count = 0 ;
+      for( int row=0; row<rows; ++row ) 
+      {
+        rows_[ row ] = count ;
+        for( int col=0; col<cols; ++col )
+        {
+          const Field val = matrix[ row ][ col ];
+          if( std::abs( val ) > 0.0 )
+          {
+            assert( count < int( data_.size() ) );
+            cols_[ count ] = col ;
+            data_[ count ] = val ;
+            ++ count ;
+          }
+        }
+      }
+      rows_[ rows ] = count ;
+    }
+
+    const int N () const { return rows; }
+    const int M () const { return cols; }
+
+    template <class X, class Y> 
+    void mv ( const X& x, Y& y ) const 
+    {
+      for( int row=0; row<rows; ++row ) 
+      {
+        Field sum = 0;
+        for( int c = rows_[ row ]; c < rows_[ row+1 ]; ++ c )
+        {
+          sum += data_[ c ] * x[ cols_[ c ] ];
+        }
+        y[ row ] = sum;
+      }
+    }
+
+    template <class X, class Y> 
+    void mvb( const int blockSize, const X& x, Y& y ) const 
+    {
+      // clear result
+      y.clear();
+
+      for( int row=0; row<rows; ++row ) 
+      {
+        for( int c = rows_[ row ]; c < rows_[ row+1 ]; ++ c )
+        {
+          Field matrix = data_[ c ];
+          for( int r=0, ir = row * blockSize, jr = cols_[ c ] * blockSize ;
+                r<blockSize; ++ r, ++ ir, ++ jr )
+          {
+            y[ ir ] += matrix * x[ jr ] ;
+          }
+        }
+      }
+    }
+
+    //! Multiplies M from the right to this matrix
+    template < class M > 
+    BlockCRSMatrix& rightmultiply (const M& )
+    {
+      abort();
+      return *this;
+    }
+
+    template < class M > 
+    BlockCRSMatrix& leftmultiply (const M& )
+    {
+      abort();
+      return *this;
+    }
+
+    void invert() 
+    {
+      abort();
+    }
+  };
+
+  } // end namespace Fem
+
+} // end namespace
+#endif
diff --git a/dune/fem-dg/pass/Makefile.am b/dune/fem-dg/pass/Makefile.am
index 51e4c605c86dac6189d207385c91aedb58d9d61e..ab5dde7ce7712fd62753fa0aad17d7791e0f18a5 100644
--- a/dune/fem-dg/pass/Makefile.am
+++ b/dune/fem-dg/pass/Makefile.am
@@ -1,3 +1,4 @@
 passdir = $(includedir)/dune/fem-dg/pass
-pass_HEADERS = assembleddiffusionpass.hh  dgmodelcaller.hh  dgpass.hh  ellipticmodelcaller.hh  threadhandle.hh  threadpass.hh
+pass_HEADERS = assembleddiffusionpass.hh  dgmodelcaller.hh  dgmasspass.hh \
+               dgpass.hh  ellipticmodelcaller.hh  threadhandle.hh  threadpass.hh
 include $(top_srcdir)/am/global-rules
diff --git a/dune/fem-dg/pass/dgmasspass.hh b/dune/fem-dg/pass/dgmasspass.hh
index 41b078985514289f01fc467378c989aadb61e16f..97ef309ccdc4058563d91421c42d794753c1f18f 100644
--- a/dune/fem-dg/pass/dgmasspass.hh
+++ b/dune/fem-dg/pass/dgmasspass.hh
@@ -12,6 +12,7 @@
 #include <dune/fem/pass/common/local.hh>
 #include <dune/fem/quadrature/cachingquadrature.hh>
 #include <dune/fem/pass/dginversemass.hh>
+#include <dune/fem-dg/misc/crs.hh>
 
 namespace Dune
 {
@@ -69,7 +70,8 @@ namespace Dune
 
     private:
       typedef typename ScalarDiscreteFunctionSpaceType :: RangeFieldType  ctype;
-      typedef Dune::FieldMatrix< ctype, numScalarBasis, numScalarBasis > LocalMatrixType ;
+      typedef Dune::FieldMatrix< ctype, numScalarBasis, numScalarBasis >         LocalMatrixType ;
+      typedef Dune::Fem::BlockCRSMatrix< ctype, numScalarBasis, numScalarBasis > SparseLocalMatrixType ;
 
       typedef Fem::CachingQuadrature< GridPartType, 0 > VolumeQuadratureType;
 
@@ -88,9 +90,9 @@ namespace Dune
 
       struct VectorEntry 
       {
-        LocalMatrixType  matrix_ ;
+        SparseLocalMatrixType  matrix_ ;
         GlobalCoordinate center_ ;
-        VectorEntry () : matrix_( 0 ), center_( std::numeric_limits< double > :: max() )
+        VectorEntry () : matrix_(), center_( std::numeric_limits< double > :: max() )
         {}
       };
 
@@ -223,13 +225,15 @@ namespace Dune
     protected:
       template < class ConstLocalFunction, class LocalFunctionType >
       void multiplyBlock( const int dimRange, 
-                          const LocalMatrixType& matrix, 
+                          const SparseLocalMatrixType& matrix, 
                           const ConstLocalFunction& arg, 
                           LocalFunctionType& dest ) const 
       {
         // clear destination
-        dest.clear();
+        // dest.clear();
+        matrix.mvb( dimRange, arg, dest );
         
+        /*
         static const int rows = LocalMatrixType::rows;
         static const int cols = LocalMatrixType::cols;
 
@@ -247,6 +251,7 @@ namespace Dune
             }
           }
         }
+        */
       }
 
       void setup() const
@@ -306,10 +311,10 @@ namespace Dune
                   const EntityType& entity, 
                   const Geometry& geo,
                   const BasisFunctionSetType& set,
-                  LocalMatrixType& matrix ) const
+                  SparseLocalMatrixType& storedMatrix ) const
       {
         // clear matrix 
-        matrix = 0;
+        LocalMatrixType matrix( 0 );
 
         // vector holding basis function evaluation 
         Dune::array< ScalarRangeType, numScalarBasis > phi ;
@@ -356,6 +361,9 @@ namespace Dune
         // if we are looking for the inverse, then invert matrix 
         if( inverse ) 
           matrix.invert();
+
+        // store matrix 
+        storedMatrix.set( matrix );
       }
 
     protected: