Skip to content
Snippets Groups Projects
fvector.hh 12.3 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:
    
    #ifndef DUNE_FVECTOR_HH
    #define DUNE_FVECTOR_HH
    
    #include <cmath>
    #include <cstddef>
    
    #include <cstdlib>
    
    Oliver Sander's avatar
    Oliver Sander committed
    #include <complex>
    
    #include <cstring>
    
    #include <dune/common/std/constexpr.hh>
    
    #include "typetraits.hh"
    
    Peter Bastian's avatar
    Peter Bastian committed
    #include "exceptions.hh"
    
    Oliver Sander's avatar
    Oliver Sander committed
    namespace Dune {
    
    
      /** @addtogroup DenseMatVec
    
    Markus Blatt's avatar
    Markus Blatt committed
      /*! \file
    
    Oliver Sander's avatar
    Oliver Sander committed
       * \brief Implements a vector constructed from a given type
    
    Markus Blatt's avatar
    Markus Blatt committed
         representing a field and a compile-time given size.
       */
    
    
      template< class K, int SIZE > class FieldVector;
      template< class K, int SIZE >
      struct DenseMatVecTraits< FieldVector<K,SIZE> >
      {
        typedef FieldVector<K,SIZE> derived_type;
        typedef Dune::array<K,SIZE> container_type;
        typedef K value_type;
        typedef typename container_type::size_type size_type;
      };
    
    
      template< class K, int SIZE >
      struct FieldTraits< FieldVector<K,SIZE> >
      {
        typedef typename FieldTraits<K>::field_type field_type;
        typedef typename FieldTraits<K>::real_type real_type;
      };
    
    
      /**
       * @brief TMP to check the size of a DenseVectors statically, if possible.
       *
       * If the implementation type of C is  a FieldVector, we statically check
       * whether its dimension is SIZE.
       * @tparam C The implementation of the other DenseVector
       * @tparam SIZE The size we need assume.
       */
      template<typename C, int SIZE>
      struct IsFieldVectorSizeCorrect
      {
        enum {
          /**
             *@param True if C is not of type FieldVector or its dimension
           * is not equal SIZE.
           */
          value = true
        };
      };
    
      template<typename T, int SIZE>
      struct IsFieldVectorSizeCorrect<FieldVector<T,SIZE>,SIZE>
      {
        enum {value = true};
      };
    
      template<typename T, int SIZE, int SIZE1>
      struct IsFieldVectorSizeCorrect<FieldVector<T,SIZE1>,SIZE>
      {
        enum {value = false};
      };
    
    
    
      /** \brief vector space out of a tensor product of fields.
    
       * \tparam K    the field type (use float, double, complex, etc)
       * \tparam SIZE number of components.
    
      template< class K, int SIZE >
    
      class FieldVector :
        public DenseVector< FieldVector<K,SIZE> >
    
        Dune::array<K,SIZE> _data;
        typedef DenseVector< FieldVector<K,SIZE> > Base;
    
    Oliver Sander's avatar
    Oliver Sander committed
      public:
        //! export size
    
        typedef typename Base::size_type size_type;
        typedef typename Base::value_type value_type;
    
        //! Constructor making default-initialized vector
        FieldVector()
          : _data{}
        {}
    
    Oliver Sander's avatar
    Oliver Sander committed
    
        //! Constructor making vector with identical coordinates
        explicit FieldVector (const K& t)
        {
    
        //! Constructor making vector with identical coordinates
    
        FieldVector (const FieldVector & x) : _data(x._data)
    
        FieldVector (std::initializer_list<K> const &l)
        {
    
          assert(l.size() == dimension);// Actually, this is not needed any more!
          std::copy_n(l.begin(), std::min(static_cast<std::size_t>(dimension),
                                          l.size()),
                     _data.begin());
    
    Oliver Sander's avatar
    Oliver Sander committed
         * \brief Copy constructor from a second vector of possibly different type
    
    Oliver Sander's avatar
    Oliver Sander committed
         * If the DenseVector type of the this constructor's argument
         * is implemented by a FieldVector, it is statically checked
    
         * if it has the correct size. If this is not the case
         * the constructor is removed from the overload set using SFINAE.
         *
         * \param[in]  x  A DenseVector with correct size.
         * \param[in]  dummy  A void* dummy argument needed by SFINAE.
         */
    
        FieldVector (const DenseVector<C> & x, typename Dune::enable_if<IsFieldVectorSizeCorrect<C,SIZE>::value>::type* dummy=0 )
    
          // do a run-time size check, for the case that x is not a FieldVector
    
          assert(x.size() == SIZE); // Actually this is not needed any more!
          std::copy_n(x.begin(), std::min(static_cast<std::size_t>(SIZE),x.size()), _data.begin());
    
        //! Constructor making vector with identical coordinates
        template<class K1, int SIZE1>
        explicit FieldVector (const FieldVector<K1,SIZE1> & x)
        {
    
          static_assert(SIZE1 == SIZE, "FieldVector in constructor has wrong size");
    
          for (size_type i = 0; i<SIZE; i++)
            _data[i] = x[i];
        }
    
        DUNE_CONSTEXPR size_type size () const { return vec_size(); }
    
    
        DUNE_CONSTEXPR size_type vec_size () const { return SIZE; }
    
        K & vec_access(size_type i) { return _data[i]; }
        const K & vec_access(size_type i) const { return _data[i]; }
    
      private:
        void fill(const K& t)
        {
          for (int i=0; i<SIZE; i++) _data[i]=t;
        }
    
      /** \brief Read a FieldVector from an input stream
       *  \relates FieldVector
       *
    
    Oliver Sander's avatar
    Oliver Sander committed
       *  \note This operator is STL compliant, i.e., the content of v is only
    
       *        changed if the read operation is successful.
       *
       *  \param[in]  in  std :: istream to read from
       *  \param[out] v   FieldVector to be read
       *
       *  \returns the input stream (in)
       */
    
      template<class K, int SIZE>
    
      inline std::istream &operator>> ( std::istream &in,
                                        FieldVector<K, SIZE> &v )
    
        FieldVector<K, SIZE> w;
        for( typename FieldVector<K, SIZE>::size_type i = 0; i < SIZE; ++i )
    
          in >> w[ i ];
    
    Christian Engwer's avatar
    Christian Engwer committed
    #ifndef DOXYGEN
    
      template< class K >
      struct DenseMatVecTraits< FieldVector<K,1> >
      {
        typedef FieldVector<K,1> derived_type;
        typedef K container_type;
        typedef K value_type;
        typedef size_t size_type;
      };
    
    
      /** \brief Vectors containing only one component
    
      class FieldVector<K, 1> :
        public DenseVector< FieldVector<K,1> >
    
        K _data;
        typedef DenseVector< FieldVector<K,1> > Base;
    
      public:
        //! export size
    
        typedef typename Base::size_type size_type;
    
        //===== construction
    
        /** \brief Default constructor */
    
    
        /** \brief Constructor with a given scalar */
    
        template<typename T,
                 typename EnableIf = typename std::enable_if<
                   std::is_convertible<T, K>::value &&
                   ! std::is_same<K, DenseVector<typename FieldTraits<T>::field_type>
                                  >::value
                   >::type
                 >
        FieldVector (const T& k) : _data(k) {}
    
        //! Constructor making vector with identical coordinates
        template<class C>
        FieldVector (const DenseVector<C> & x)
        {
    
          static_assert(((bool)IsFieldVectorSizeCorrect<C,1>::value), "FieldVectors do not match in dimension!");
    
        //! copy constructor
        FieldVector ( const FieldVector &other )
          : _data( other._data )
        {}
    
    
        //! Assignment operator for scalar
    
        template<typename T,
                 typename EnableIf = typename std::enable_if<
                   std::is_convertible<T, K>::value &&
                   ! std::is_same<K, DenseVector<typename FieldTraits<T>::field_type>
                                  >::value
                   >::type
                 >
        inline FieldVector& operator= (const T& k)
    
        DUNE_CONSTEXPR size_type size () const { return vec_size(); }
    
    
        //===== forward methods to container
    
        DUNE_CONSTEXPR size_type vec_size () const { return 1; }
    
        K & vec_access(size_type i)
        {
          assert(i == 0);
          return _data;
        }
        const K & vec_access(size_type i) const
        {
          assert(i == 0);
          return _data;
        }
    
    
        //===== conversion operator
    
        /** \brief Conversion operator */
    
    
        /** \brief Const conversion operator */
    
        operator const K& () const { return _data; }
    
      /* mostly not necessary as these operations are already covered via the cast operator */
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator> (const FieldVector<K,1>& a, const FieldVector<K,1>& b)
      {
        return a[0]>b[0];
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator>= (const FieldVector<K,1>& a, const FieldVector<K,1>& b)
      {
        return a[0]>=b[0];
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator< (const FieldVector<K,1>& a, const FieldVector<K,1>& b)
      {
        return a[0]<b[0];
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator<= (const FieldVector<K,1>& a, const FieldVector<K,1>& b)
      {
        return a[0]<=b[0];
      }
    
      //! Binary addition, when using FieldVector<K,1> like K
    
      inline FieldVector<K,1> operator+ (const FieldVector<K,1>& a, const K b)
    
      //! Binary subtraction, when using FieldVector<K,1> like K
    
      inline FieldVector<K,1> operator- (const FieldVector<K,1>& a, const K b)
    
      //! Binary multiplication, when using FieldVector<K,1> like K
    
      template<class K>
    
      inline FieldVector<K,1> operator* (const FieldVector<K,1>& a, const K b)
    
      //! Binary division, when using FieldVector<K,1> like K
    
      template<class K>
    
      inline FieldVector<K,1> operator/ (const FieldVector<K,1>& a, const K b)
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator> (const FieldVector<K,1>& a, const K b)
      {
        return a[0]>b;
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator>= (const FieldVector<K,1>& a, const K b)
      {
        return a[0]>=b;
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator< (const FieldVector<K,1>& a, const K b)
      {
        return a[0]<b;
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator<= (const FieldVector<K,1>& a, const K b)
      {
        return a[0]<=b;
      }
    
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator== (const FieldVector<K,1>& a, const K b)
      {
        return a[0]==b;
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator!= (const FieldVector<K,1>& a, const K b)
      {
        return a[0]!=b;
      }
    
      /* ----- scalar / FV ------ */
    
    
      //! Binary addition, when using FieldVector<K,1> like K
      template<class K>
      inline FieldVector<K,1> operator+ (const K a, const FieldVector<K,1>& b)
      {
    
      }
    
      //! Binary subtraction, when using FieldVector<K,1> like K
      template<class K>
      inline FieldVector<K,1> operator- (const K a, const FieldVector<K,1>& b)
      {
    
      //! Binary multiplication, when using FieldVector<K,1> like K
      template<class K>
      inline FieldVector<K,1> operator* (const K a, const FieldVector<K,1>& b)
      {
        return a*b[0];
      }
    
      //! Binary division, when using FieldVector<K,1> like K
      template<class K>
      inline FieldVector<K,1> operator/ (const K a, const FieldVector<K,1>& b)
      {
        return a/b[0];
      }
    
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator> (const K a, const FieldVector<K,1>& b)
      {
        return a>b[0];
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator>= (const K a, const FieldVector<K,1>& b)
      {
        return a>=b[0];
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator< (const K a, const FieldVector<K,1>& b)
      {
        return a<b[0];
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator<= (const K a, const FieldVector<K,1>& b)
      {
        return a<=b[0];
      }
    
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator== (const K a, const FieldVector<K,1>& b)
      {
        return a==b[0];
      }
    
      //! Binary compare, when using FieldVector<K,1> like K
      template<class K>
      inline bool operator!= (const K a, const FieldVector<K,1>& b)
      {
        return a!=b[0];
      }
    
    Oliver Sander's avatar
    Oliver Sander committed
      /** @} end documentation */
    
    } // end namespace
    
    #endif