Skip to content
Snippets Groups Projects
fmatrix.hh 14.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • Oliver Sander's avatar
    Oliver Sander committed
    // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
    // vi: set et ts=4 sw=2 sts=2:
    
    Oliver Sander's avatar
    Oliver Sander committed
    #ifndef DUNE_FMATRIX_HH
    #define DUNE_FMATRIX_HH
    
    
    #include <cmath>
    #include <cstddef>
    
    Oliver Sander's avatar
    Oliver Sander committed
    #include <iostream>
    
    Oliver Sander's avatar
    Oliver Sander committed
    
    
    #include <dune/common/exceptions.hh>
    #include <dune/common/fvector.hh>
    
    #include <dune/common/densematrix.hh>
    
    #include <dune/common/precision.hh>
    
    #include <dune/common/std/constexpr.hh>
    
    Oliver Sander's avatar
    Oliver Sander committed
    
      /**
    
    Martin Nolte's avatar
    Martin Nolte committed
          @addtogroup DenseMatVec
          @{
    
    Markus Blatt's avatar
    Markus Blatt committed
      /*! \file
    
    
    Oliver Sander's avatar
    Oliver Sander committed
         \brief  Implements a matrix constructed from a given type
    
    Markus Blatt's avatar
    Markus Blatt committed
         representing a field and compile-time given number of rows and columns.
       */
    
    
      template< class K, int ROWS, int COLS > class FieldMatrix;
    
      template< class K, int ROWS, int COLS >
      struct DenseMatVecTraits< FieldMatrix<K,ROWS,COLS> >
    
        typedef FieldMatrix<K,ROWS,COLS> derived_type;
    
    
        // each row is implemented by a field vector
    
        typedef FieldVector<K,COLS> row_type;
    
    
        typedef row_type &row_reference;
        typedef const row_type &const_row_reference;
    
    
        typedef Dune::array<row_type,ROWS> container_type;
        typedef K value_type;
        typedef typename container_type::size_type size_type;
      };
    
      template< class K, int ROWS, int COLS >
      struct FieldTraits< FieldMatrix<K,ROWS,COLS> >
    
        typedef typename FieldTraits<K>::field_type field_type;
        typedef typename FieldTraits<K>::real_type real_type;
      };
    
    Markus Blatt's avatar
    Markus Blatt committed
      /**
          @brief A dense n x m matrix.
    
         Matrices represent linear maps from a vector space V to a vector space W.
    
    Oliver Sander's avatar
    Oliver Sander committed
           This class represents such a linear map by storing a two-dimensional
    
    Oliver Sander's avatar
    Oliver Sander committed
           %array of numbers of a given field type K. The number of rows and
    
    Oliver Sander's avatar
    Oliver Sander committed
           columns is given at compile time.
       */
    
    Christian Engwer's avatar
    Christian Engwer committed
      template<class K, int ROWS, int COLS>
    
      class FieldMatrix : public DenseMatrix< FieldMatrix<K,ROWS,COLS> >
    
    Oliver Sander's avatar
    Oliver Sander committed
      {
    
        Dune::array< FieldVector<K,COLS>, ROWS > _data;
        typedef DenseMatrix< FieldMatrix<K,ROWS,COLS> > Base;
    
    Oliver Sander's avatar
    Oliver Sander committed
      public:
    
        //! export size
    
    Christian Engwer's avatar
    Christian Engwer committed
          rows = ROWS,
    
    Christian Engwer's avatar
    Christian Engwer committed
          cols = COLS
    
    Oliver Sander's avatar
    Oliver Sander committed
    
    
        typedef typename Base::size_type size_type;
        typedef typename Base::row_type row_type;
    
        typedef typename Base::row_reference row_reference;
        typedef typename Base::const_row_reference const_row_reference;
    
    
    Oliver Sander's avatar
    Oliver Sander committed
        //===== constructors
        /** \brief Default constructor
         */
        FieldMatrix () {}
    
        /** \brief Constructor initializing the whole matrix with a scalar
         */
    
        template< class Other >
        FieldMatrix ( const Other &other )
    
    Oliver Sander's avatar
    Oliver Sander committed
        {
    
          DenseMatrixAssigner< FieldMatrix< K, ROWS, COLS >, Other >::apply( *this, other );
    
        FieldMatrix (std::initializer_list<std::initializer_list<K> > const &ll)
        {
          assert(ll.size() == rows);
          size_t i = 0;
          for (typename std::initializer_list<std::initializer_list<K> >::
                 const_iterator lit = ll.begin(); lit != ll.end(); ++lit)
            _data[i++] = *lit;
        }
    
    
        //===== assignment
        using Base::operator=;
    
        //! Multiplies M from the left to this matrix, this matrix is not modified
        template<int l>
    
        FieldMatrix<K,l,cols> leftmultiplyany (const FieldMatrix<K,l,rows>& M) const
    
    Christian Engwer's avatar
    Christian Engwer committed
          FieldMatrix<K,l,cols> C;
    
    
          for (size_type i=0; i<l; i++) {
    
    Christian Engwer's avatar
    Christian Engwer committed
            for (size_type j=0; j<cols; j++) {
    
    Christian Engwer's avatar
    Christian Engwer committed
              for (size_type k=0; k<rows; k++)
    
                C[i][j] += M[i][k]*(*this)[k][j];
            }
          }
          return C;
        }
    
    
    Oliver Sander's avatar
    Oliver Sander committed
        //! Multiplies M from the right to this matrix
    
    Christian Engwer's avatar
    Christian Engwer committed
        FieldMatrix& rightmultiply (const FieldMatrix<K,cols,cols>& M)
    
    Oliver Sander's avatar
    Oliver Sander committed
        {
    
    Christian Engwer's avatar
    Christian Engwer committed
          FieldMatrix<K,rows,cols> C(*this);
    
    Christian Engwer's avatar
    Christian Engwer committed
          for (size_type i=0; i<rows; i++)
            for (size_type j=0; j<cols; j++) {
    
              for (size_type k=0; k<cols; k++)
    
    Oliver Sander's avatar
    Oliver Sander committed
          return *this;
        }
    
    
        //! Multiplies M from the right to this matrix, this matrix is not modified
        template<int l>
    
        FieldMatrix<K,rows,l> rightmultiplyany (const FieldMatrix<K,cols,l>& M) const
    
    Christian Engwer's avatar
    Christian Engwer committed
          FieldMatrix<K,rows,l> C;
    
    Christian Engwer's avatar
    Christian Engwer committed
          for (size_type i=0; i<rows; i++) {
    
            for (size_type j=0; j<l; j++) {
              C[i][j] = 0;
    
    Christian Engwer's avatar
    Christian Engwer committed
              for (size_type k=0; k<cols; k++)
    
                C[i][j] += (*this)[i][k]*M[k][j];
            }
          }
          return C;
        }
    
    
        // make this thing a matrix
    
        DUNE_CONSTEXPR size_type mat_rows() const { return ROWS; }
        DUNE_CONSTEXPR size_type mat_cols() const { return COLS; }
    
          assert(i < ROWS);
          return _data[i];
    
    Oliver Sander's avatar
    Oliver Sander committed
        }
    
    
        const_row_reference mat_access ( size_type i ) const
        {
    
          assert(i < ROWS);
          return _data[i];
    
    #ifndef DOXYGEN // hide specialization
    
      /** \brief Special type for 1x1 matrices
       */
      template<class K>
    
      class FieldMatrix<K,1,1> : public DenseMatrix< FieldMatrix<K,1,1> >
    
        FieldVector<K,1> _data;
        typedef DenseMatrix< FieldMatrix<K,1,1> > Base;
    
      public:
        // standard constructor and everything is sufficient ...
    
        //===== type definitions and constants
    
    
        //! The type used for index access and size operations
    
        typedef typename Base::size_type size_type;
    
        //! We are at the leaf of the block recursion
        enum {
          //! The number of block levels we contain.
          //! This is always one for this type.
          blocklevel = 1
        };
    
    
        typedef typename Base::row_type row_type;
    
        typedef typename Base::row_reference row_reference;
        typedef typename Base::const_row_reference const_row_reference;
    
    
        //! export size
        enum {
          //! \brief The number of rows.
          //! This is always one for this type.
          rows = 1,
          //! \brief The number of columns.
          //! This is always one for this type.
    
        //===== constructors
        /** \brief Default constructor
         */
        FieldMatrix () {}
    
        /** \brief Constructor initializing the whole matrix with a scalar
         */
    
        FieldMatrix (const K& k)
    
          _data[0] = k;
    
    
        template< class Other >
        FieldMatrix ( const Other &other )
    
          DenseMatrixAssigner< FieldMatrix< K, 1, 1 >, Other >::apply( *this, other );
    
        //! Multiplies M from the left to this matrix, this matrix is not modified
        template<int l>
        FieldMatrix<K,l,1> leftmultiplyany (const FieldMatrix<K,l,1>& M) const
        {
          FieldMatrix<K,l,1> C;
          for (size_type j=0; j<l; j++)
    
            C[j][0] = M[j][0]*(*this)[0][0];
    
        //! left multiplication
        FieldMatrix& rightmultiply (const FieldMatrix& M)
        {
    
          _data[0] *= M[0][0];
    
        //! Multiplies M from the right to this matrix, this matrix is not modified
        template<int l>
        FieldMatrix<K,1,l> rightmultiplyany (const FieldMatrix<K,1,l>& M) const
        {
          FieldMatrix<K,1,l> C;
    
          for (size_type j=0; j<l; j++)
    
            C[0][j] = M[0][j]*_data[0];
    
          return C;
        }
    
        // make this thing a matrix
    
        DUNE_CONSTEXPR size_type mat_rows() const { return 1; }
        DUNE_CONSTEXPR size_type mat_cols() const { return 1; }
    
          assert(i == 0);
          return _data;
    
    
        const_row_reference mat_access ( size_type i ) const
        {
    
          assert(i == 0);
          return _data;
    
        //! add scalar
        FieldMatrix& operator+= (const K& k)
        {
          _data[0] += k;
          return (*this);
        }
    
        //! subtract scalar
        FieldMatrix& operator-= (const K& k)
        {
          _data[0] -= k;
          return (*this);
        }
    
        //! multiplication with scalar
        FieldMatrix& operator*= (const K& k)
        {
          _data[0] *= k;
          return (*this);
        }
    
        //! division by scalar
        FieldMatrix& operator/= (const K& k)
        {
          _data[0] /= k;
          return (*this);
        }
    
    
        //===== conversion operator
    
    
        operator K () const { return _data[0]; }
    
    
      /** \brief Sends the matrix to an output stream */
      template<typename K>
      std::ostream& operator<< (std::ostream& s, const FieldMatrix<K,1,1>& a)
      {
        s << a[0][0];
        return s;
      }
    
    
    Christian Engwer's avatar
    Christian Engwer committed
    #endif // DOXYGEN
    
    
      namespace FMatrixHelp {
    
        //! invert scalar without changing the original matrix
        template <typename K>
        static inline K invertMatrix (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
        {
    
    Oliver Sander's avatar
    Oliver Sander committed
          inverse[0][0] = 1.0/matrix[0][0];
          return matrix[0][0];
    
        //! invert scalar without changing the original matrix
        template <typename K>
        static inline K invertMatrix_retTransposed (const FieldMatrix<K,1,1> &matrix, FieldMatrix<K,1,1> &inverse)
        {
          return invertMatrix(matrix,inverse);
        }
    
    
    
        //! invert 2x2 Matrix without changing the original matrix
        template <typename K>
        static inline K invertMatrix (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
        {
          // code generated by maple
          K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
          K det_1 = 1.0/det;
          inverse[0][0] =   matrix[1][1] * det_1;
          inverse[0][1] = - matrix[0][1] * det_1;
          inverse[1][0] = - matrix[1][0] * det_1;
          inverse[1][1] =   matrix[0][0] * det_1;
          return det;
        }
    
    
        //! invert 2x2 Matrix without changing the original matrix
        //! return transposed matrix
        template <typename K>
        static inline K invertMatrix_retTransposed (const FieldMatrix<K,2,2> &matrix, FieldMatrix<K,2,2> &inverse)
        {
          // code generated by maple
          K det = (matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]);
          K det_1 = 1.0/det;
          inverse[0][0] =   matrix[1][1] * det_1;
          inverse[1][0] = - matrix[0][1] * det_1;
          inverse[0][1] = - matrix[1][0] * det_1;
          inverse[1][1] =   matrix[0][0] * det_1;
          return det;
        }
    
    
        //! invert 3x3 Matrix without changing the original matrix
        template <typename K>
        static inline K invertMatrix (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
        {
          // code generated by maple
          K t4  = matrix[0][0] * matrix[1][1];
          K t6  = matrix[0][0] * matrix[1][2];
          K t8  = matrix[0][1] * matrix[1][0];
          K t10 = matrix[0][2] * matrix[1][0];
          K t12 = matrix[0][1] * matrix[2][0];
          K t14 = matrix[0][2] * matrix[2][0];
    
          K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
                   t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
          K t17 = 1.0/det;
    
          inverse[0][0] =  (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
          inverse[0][1] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
          inverse[0][2] =  (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
          inverse[1][0] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
          inverse[1][1] =  (matrix[0][0] * matrix[2][2] - t14) * t17;
          inverse[1][2] = -(t6-t10) * t17;
          inverse[2][0] =  (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
          inverse[2][1] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
          inverse[2][2] =  (t4-t8) * t17;
    
          return det;
        }
    
    
        //! invert 3x3 Matrix without changing the original matrix
        template <typename K>
        static inline K invertMatrix_retTransposed (const FieldMatrix<K,3,3> &matrix, FieldMatrix<K,3,3> &inverse)
        {
          // code generated by maple
          K t4  = matrix[0][0] * matrix[1][1];
          K t6  = matrix[0][0] * matrix[1][2];
          K t8  = matrix[0][1] * matrix[1][0];
          K t10 = matrix[0][2] * matrix[1][0];
          K t12 = matrix[0][1] * matrix[2][0];
          K t14 = matrix[0][2] * matrix[2][0];
    
          K det = (t4*matrix[2][2]-t6*matrix[2][1]-t8*matrix[2][2]+
                   t10*matrix[2][1]+t12*matrix[1][2]-t14*matrix[1][1]);
          K t17 = 1.0/det;
    
          inverse[0][0] =  (matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1])*t17;
          inverse[1][0] = -(matrix[0][1] * matrix[2][2] - matrix[0][2] * matrix[2][1])*t17;
          inverse[2][0] =  (matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1])*t17;
          inverse[0][1] = -(matrix[1][0] * matrix[2][2] - matrix[1][2] * matrix[2][0])*t17;
          inverse[1][1] =  (matrix[0][0] * matrix[2][2] - t14) * t17;
          inverse[2][1] = -(t6-t10) * t17;
          inverse[0][2] =  (matrix[1][0] * matrix[2][1] - matrix[1][1] * matrix[2][0]) * t17;
          inverse[1][2] = -(matrix[0][0] * matrix[2][1] - t12) * t17;
          inverse[2][2] =  (t4-t8) * t17;
    
          return det;
        }
    
    
        //! calculates ret = A * B
        template< class K, int m, int n, int p >
        static inline void multMatrix ( const FieldMatrix< K, m, n > &A,
                                        const FieldMatrix< K, n, p > &B,
                                        FieldMatrix< K, m, p > &ret )
        {
          typedef typename FieldMatrix< K, m, p > :: size_type size_type;
    
          for( size_type i = 0; i < m; ++i )
          {
            for( size_type j = 0; j < p; ++j )
            {
              ret[ i ][ j ] = K( 0 );
              for( size_type k = 0; k < n; ++k )
                ret[ i ][ j ] += A[ i ][ k ] * B[ k ][ j ];
            }
          }
        }
    
    
        template <typename K, int rows, int cols>
    
        static inline void multTransposedMatrix(const FieldMatrix<K,rows,cols> &matrix, FieldMatrix<K,cols,cols>& ret)
        {
          typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
    
          for(size_type i=0; i<cols; i++)
            for(size_type j=0; j<cols; j++)
    
    Christian Engwer's avatar
    Christian Engwer committed
            {
              ret[i][j]=0.0;
    
              for(size_type k=0; k<rows; k++)
    
    Christian Engwer's avatar
    Christian Engwer committed
                ret[i][j]+=matrix[k][i]*matrix[k][j];
            }
    
        using Dune::DenseMatrixHelp::multAssign;
    
        //! calculates ret = matrix^T * x
        template <typename K, int rows, int cols>
        static inline void multAssignTransposed( const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x, FieldVector<K,cols> & ret)
    
          typedef typename FieldMatrix<K,rows,cols>::size_type size_type;
    
          for(size_type i=0; i<cols; ++i)
    
          {
            ret[i] = 0.0;
    
            for(size_type j=0; j<rows; ++j)
    
              ret[i] += matrix[j][i]*x[j];
          }
        }
    
    
        template <typename K, int rows, int cols>
    
        static inline FieldVector<K,rows> mult(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,cols> & x)
    
          FieldVector<K,rows> ret;
    
        //! calculates ret = matrix^T * x
    
        template <typename K, int rows, int cols>
    
        static inline FieldVector<K,cols> multTransposed(const FieldMatrix<K,rows,cols> &matrix, const FieldVector<K,rows> & x)
    
          multAssignTransposed( matrix, x, ret );
    
    Oliver Sander's avatar
    Oliver Sander committed
      /** @} end documentation */
    
    } // end namespace
    
    
    #include "fmatrixev.hh"
    
    Oliver Sander's avatar
    Oliver Sander committed
    #endif