Newer
Older
// -*- 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 "genericiterator.hh"
#ifdef DUNE_EXPRESSIONTEMPLATES
#include "exprtmpl.hh"
#endif
#ifndef DUNE_EXPRESSIONTEMPLATES
/** @defgroup DenseMatVec Dense Matrix and Vector Template Library
/*! \file
* \brief This file implements a vector constructed from a given type
representing a field and a compile-time given size.
*/
template<class K, int SIZE> class FieldVector;
#endif
#ifndef DUNE_EXPRESSIONTEMPLATES
template<class K>
inline double fvmeta_absreal (const K& k)
{
Oliver Sander
committed
return std::abs(k);
template<class K>
inline double fvmeta_absreal (const std::complex<K>& c)
{
return fvmeta_abs(c.real()) + fvmeta_abs(c.imag());
}
template<class K>
inline double fvmeta_abs2 (const K& k)
{
return k*k;
}
template<class K>
inline double fvmeta_abs2 (const std::complex<K>& c)
{
return c.real()*c.real() + c.imag()*c.imag();
}
//! Iterator class for sequential access to FieldVector and FieldMatrix
template<class C, class T>
class FieldIterator :
public Dune::RandomAccessIteratorFacade<FieldIterator<C,T>,T, T&, int>
{
friend class FieldIterator<typename remove_const<C>::type, typename remove_const<T>::type >;
friend class FieldIterator<const typename remove_const<C>::type, const typename remove_const<T>::type >;
public:
/**
* @brief The type of the difference between two positions.
*/
typedef std::ptrdiff_t DifferenceType;
// Constructors needed by the base iterators.
FieldIterator()
: container_(0), position_(0)
{}
FieldIterator(C& cont, DifferenceType pos)
: container_(&cont), position_(pos)
{}
FieldIterator(const FieldIterator<typename remove_const<C>::type, typename remove_const<T>::type >& other)
: container_(other.container_), position_(other.position_)
{}
FieldIterator(const FieldIterator<const typename remove_const<C>::type, const typename remove_const<T>::type >& other)
: container_(other.container_), position_(other.position_)
{}
#endif
#if 0
FieldIterator(const FieldIterator<C,T>& other)
: container_(other.container_), position_(other.position_)
{}
#endif
// Methods needed by the forward iterator
bool equals(const FieldIterator<typename remove_const<C>::type,typename remove_const<T>::type>& other) const
{
return position_ == other.position_ && container_ == other.container_;
}
bool equals(const FieldIterator<const typename remove_const<C>::type,const typename remove_const<T>::type>& other) const
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
{
return position_ == other.position_ && container_ == other.container_;
}
T& dereference() const {
return container_->operator[](position_);
}
void increment(){
++position_;
}
// Additional function needed by BidirectionalIterator
void decrement(){
--position_;
}
// Additional function needed by RandomAccessIterator
T& elementAt(DifferenceType i) const {
return container_->operator[](position_+i);
}
void advance(DifferenceType n){
position_=position_+n;
}
std::ptrdiff_t distanceTo(FieldIterator<const typename remove_const<C>::type,const typename remove_const<T>::type> other) const
{
assert(other.container_==container_);
return other.position_ - position_;
}
std::ptrdiff_t distanceTo(FieldIterator<typename remove_const<C>::type, typename remove_const<T>::type> other) const
{
assert(other.container_==container_);
return other.position_ - position_;
}
//! return index
{
return this->position_;
}
private:
C *container_;
DifferenceType position_;
};
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//! Type Traits for Vector::Iterator vs (const Vector)::ConstIterator
template<class T>
struct IteratorType
{
typedef typename T::Iterator type;
};
template<class T>
struct IteratorType<const T>
{
typedef typename T::ConstIterator type;
};
#ifdef DUNE_EXPRESSIONTEMPLATES
//! Iterator class for flat sequential access to a nested Vector
template<class V>
class FlatIterator :
public ForwardIteratorFacade<FlatIterator<V>,
typename Dune::FieldType<V>::type,
typename Dune::FieldType<V>::type&,
int>
{
public:
typedef typename IteratorType<V>::type BlockIterator;
typedef std::ptrdiff_t DifferenceType;
// typedef typename BlockIterator::DifferenceType DifferenceType;
typedef typename BlockType<V>::type block_type;
typedef typename FieldType<V>::type field_type;
typedef FlatIterator<block_type> SubBlockIterator;
FlatIterator(const BlockIterator & i) :
it(i), bit(i->begin()), bend(i->end()) {};
void increment ()
{
++bit;
if (bit == bend)
{
++it;
bit = it->begin();
bend = it->end();
}
}
bool equals (const FlatIterator & fit) const
{
return fit.it == it && fit.bit == bit;
}
field_type& dereference() const
{
return *bit;
}
//! return index
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
{
return bit.index();
}
private:
BlockIterator it;
SubBlockIterator bit;
SubBlockIterator bend;
};
//! Specialization for FieldVector
//! acts as the end of the recursive template
template<class K, int N>
class FlatIterator< FieldVector<K,N> > :
public ForwardIteratorFacade<FlatIterator< FieldVector<K,N> >,
K, K&, int>
{
public:
typedef typename FieldVector<K,N>::Iterator BlockIterator;
typedef std::ptrdiff_t DifferenceType;
// typedef typename BlockIterator::DifferenceType DifferenceType;
typedef typename FieldVector<K,N>::field_type field_type;
FlatIterator(const BlockIterator & i) : it(i) {};
void increment ()
{
++it;
}
bool equals (const FlatIterator & fit) const
{
return fit.it == it;
}
field_type& dereference() const
{
return *it;
}
//! return index
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
{
return it.index();
}
private:
BlockIterator it;
};
//! Specialization for const FieldVector
//! acts as the end of the recursive template
template<class K, int N>
class FlatIterator< const FieldVector<K,N> > :
public ForwardIteratorFacade<FlatIterator< const FieldVector<K,N> >,
const K, const K&, int>
{
public:
typedef typename FieldVector<K,N>::ConstIterator BlockIterator;
typedef std::ptrdiff_t DifferenceType;
// typedef typename BlockIterator::DifferenceType DifferenceType;
typedef typename FieldVector<K,N>::field_type field_type;
FlatIterator(const BlockIterator & i) : it(i) {};
void increment ()
{
++it;
}
bool equals (const FlatIterator & fit) const
{
return fit.it == it;
}
const field_type& dereference() const
{
return *it;
}
//! return index
{
return it.index();
}
private:
BlockIterator it;
};
#endif
/** \brief Construct a vector space out of a tensor product of fields.
*
* K is the field type (use float, double, complex, etc) and SIZE
* is the number of components.
*
* It is generally assumed that K is a numerical type compatible with double
* (E.g. norms are always computed in double precision).
*/
template< class K, int SIZE >
class FieldVector
#ifdef DUNE_EXPRESSIONTEMPLATES
: public Dune :: ExprTmpl :: Vector< FieldVector< K, SIZE > >
// remember size of vector
enum { dimension = SIZE };
// standard constructor and everything is sufficient ...
//===== type definitions and constants
//! export the type representing the field
typedef K field_type;
//! export the type representing the components
typedef K block_type;
//! The type used for the index access and size operation
typedef std::size_t size_type;
enum {
//! The number of block levels we contain
blocklevel = 1
};
enum {
//! The size of this vector.
size = SIZE
//! Constructor making uninitialized vector
FieldVector() {}
#ifndef DUNE_EXPRESSIONTEMPLATES
//! Constructor making vector with identical coordinates
explicit FieldVector (const K& t)
{
for (size_type i=0; i<SIZE; i++) p[i] = t;
//! Assignment operator for scalar
Oliver Sander
committed
//fvmeta_assignscalar<SIZE-1>::assignscalar(*this,k);
for (size_type i=0; i<SIZE; i++)
p[i] = k;
#else
//! Constructor making vector with identical coordinates
explicit FieldVector (const K& t)
{
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector Copy Constructor Scalar\n";
#endif
assignFrom(t);
}
//! Assignment operator for scalar
FieldVector& operator= (const K& k)
{
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector Assignment Operator Scalar\n";
#endif
return assignFrom(k);
}
template <class E>
FieldVector (Dune::ExprTmpl::Expression<E> op) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector Copy Constructor Expression\n";
assignFrom(op);
}
template <class V>
FieldVector (const Dune::ExprTmpl::Vector<V> & op) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector Copy Operator Vector\n";
assignFrom(op);
}
template <class E>
FieldVector& operator = (Dune::ExprTmpl::Expression<E> op) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector Assignment Operator Expression\n";
return assignFrom(op);
}
template <class V>
FieldVector& operator = (const Dune::ExprTmpl::Vector<V> & op) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector Assignment Operator Vector\n";
return assignFrom(op);
}
#endif
/** \brief copy constructor */
FieldVector ( const FieldVector &other )
{
for( size_type i = 0; i < SIZE; ++i )
p[ i ] = other[ i ];
}
/** \brief Assigment from other vector */
FieldVector& operator= (const FieldVector& other) {
for (size_type i=0; i<SIZE; i++)
p[i] = other[i];
}
//===== access to components
//! random access
K& operator[] (size_type i)
if (i<0 || i>=SIZE) DUNE_THROW(MathError,"index out of range");
#endif
return p[i];
}
//! same for read only access
const K& operator[] (size_type i) const
if (i<0 || i>=SIZE) DUNE_THROW(MathError,"index out of range");
#endif
return p[i];
}
//! Iterator class for sequential access
typedef FieldIterator<FieldVector<K,SIZE>,K> Iterator;
//! typedef for stl compliant access
typedef Iterator iterator;
//! begin iterator
Iterator begin ()
{
return Iterator(*this,0);
}
//! end iterator
Iterator end ()
{
return Iterator(*this,SIZE);
}
//! begin iterator
Iterator rbegin ()
{
return Iterator(*this,SIZE-1);
}
//! end iterator
Iterator rend ()
{
return Iterator(*this,-1);
}
//! return iterator to given element or end()
Iterator find (size_type i)
if (i<SIZE)
return Iterator(*this,i);
return Iterator(*this,SIZE);
}
//! ConstIterator class for sequential access
typedef FieldIterator<const FieldVector<K,SIZE>,const K> ConstIterator;
//! typedef for stl compliant access
typedef ConstIterator const_iterator;
//! begin ConstIterator
ConstIterator begin () const
{
return ConstIterator(*this,0);
}
//! end ConstIterator
ConstIterator end () const
{
return ConstIterator(*this,SIZE);
}
//! begin ConstIterator
ConstIterator rbegin () const
{
return ConstIterator(*this,SIZE-1);
}
//! end ConstIterator
ConstIterator rend () const
{
return ConstIterator(*this,-1);
}
//! return iterator to given element or end()
ConstIterator find (size_type i) const
if (i<SIZE)
return ConstIterator(*this,i);
return ConstIterator(*this,SIZE);
#ifndef DUNE_EXPRESSIONTEMPLATES
//===== vector space arithmetic
//! vector space addition
FieldVector& operator+= (const FieldVector& y)
{
Oliver Sander
committed
for (size_type i=0; i<SIZE; i++)
p[i] += y.p[i];
return *this;
}
//! vector space subtraction
FieldVector& operator-= (const FieldVector& y)
{
Oliver Sander
committed
for (size_type i=0; i<SIZE; i++)
p[i] -= y.p[i];
return *this;
}
//! Binary vector addition
FieldVector<K, size> operator+ (const FieldVector<K, size>& b) const
{
FieldVector<K, size> z = *this;
return (z+=b);
}
//! Binary vector subtraction
FieldVector<K, size> operator- (const FieldVector<K, size>& b) const
{
FieldVector<K, size> z = *this;
return (z-=b);
}
//! vector space add scalar to all comps
FieldVector& operator+= (const K& k)
{
Oliver Sander
committed
for (size_type i=0; i<SIZE; i++)
p[i] += k;
return *this;
}
//! vector space subtract scalar from all comps
FieldVector& operator-= (const K& k)
{
Oliver Sander
committed
for (size_type i=0; i<SIZE; i++)
p[i] -= k;
return *this;
}
//! vector space multiplication with scalar
FieldVector& operator*= (const K& k)
{
Oliver Sander
committed
for (size_type i=0; i<SIZE; i++)
p[i] *= k;
return *this;
}
//! vector space division by scalar
FieldVector& operator/= (const K& k)
{
Oliver Sander
committed
for (size_type i=0; i<SIZE; i++)
p[i] /= k;
//! Binary vector comparison
bool operator== (const FieldVector& y) const
{
Oliver Sander
committed
for (size_type i=0; i<SIZE; i++)
if (p[i]!=y.p[i])
return false;
return true;
//! Binary vector incomparison
bool operator!= (const FieldVector& y) const
{
return !operator==(y);
}
FieldVector& axpy (const K& a, const FieldVector& y)
{
#ifndef DUNE_EXPRESSIONTEMPLATES
Oliver Sander
committed
for (size_type i=0; i<SIZE; i++)
p[i] += a*y.p[i];
#ifndef DUNE_EXPRESSIONTEMPLATES
K operator* (const FieldVector& y) const
K result = 0;
for (int i=0; i<size; i++)
result += p[i]*y[i];
return result;
}
//===== norms
//! one norm (sum over absolute values of entries)
double one_norm() const {
double result = 0;
for (int i=0; i<size; i++)
result += std::abs(p[i]);
return result;
//! simplified one norm (uses Manhattan norm for complex values)
double one_norm_real () const
{
double result = 0;
for (int i=0; i<size; i++)
result += fvmeta_absreal(p[i]);
return result;
}
//! two norm sqrt(sum over squared values of entries)
double two_norm () const
{
double result = 0;
for (int i=0; i<size; i++)
result += fvmeta_abs2(p[i]);
return std::sqrt(result);
//! square of two norm (sum over squared values of entries), need for block recursion
double result = 0;
for (int i=0; i<size; i++)
result += fvmeta_abs2(p[i]);
return result;
}
//! infinity norm (maximum of absolute values of entries)
double infinity_norm () const
{
double result = 0;
for (int i=0; i<size; i++)
return result;
}
//! simplified infinity norm (uses Manhattan norm for complex values)
double infinity_norm_real () const
{
double result = 0;
for (int i=0; i<size; i++)
return result;
//===== sizes
//! number of blocks in the vector (are of size 1 here)
size_type N () const
return SIZE;
size_type dim () const
return SIZE;
}
private:
// the data, very simply a built in array
K p[(SIZE > 0) ? SIZE : 1];
/** \brief Write a FieldVector to an output stream
* \relates FieldVector
*
* \param[in] s std :: ostream to write to
* \param[in] v FieldVector to write
*
* \returns the output stream (s)
*/
Adrian Burri
committed
template<typename K, int n>
std::ostream& operator<< (std::ostream& s, const FieldVector<K,n>& v)
{
Oliver Sander
committed
for (typename FieldVector<K,n>::size_type i=0; i<n; i++)
s << ((i>0) ? " " : "") << v[i];
Adrian Burri
committed
return s;
}
/** \brief Read a FieldVector from an input stream
* \relates FieldVector
*
* \note This operator is STL compilant, 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 ];
if( in )
v = w;
return in;
}
// forward declarations
template<class K, int n, int m> class FieldMatrix;
/** \brief Vectors containing only one component
Christian Engwer
committed
*/
template< class K >
class FieldVector< K, 1 >
#ifdef DUNE_EXPRESSIONTEMPLATES
: public Dune :: ExprTmpl :: Vector< FieldVector< K, 1 > >
{
enum { n = 1 };
public:
friend class FieldMatrix<K,1,1>;
//===== type definitions and constants
//! export the type representing the field
typedef K field_type;
//! export the type representing the components
typedef K block_type;
//! The type for the index access and size operations.
//! We are at the leaf of the block recursion
enum {blocklevel = 1};
//! export size
enum {size = 1};
//! export size
enum {dimension = 1};
//===== construction
/** \brief Default constructor */
FieldVector ()
{ }
/** \brief Constructor with a given scalar */
FieldVector (const K& k)
{
p = k;
}
/** \brief Assignment from the base type */
FieldVector& operator= (const K& k)
{
p = k;
return *this;
}
#ifdef DUNE_EXPRESSIONTEMPLATES
template <class E>
FieldVector (Dune::ExprTmpl::Expression<E> op) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector<1> Copy Constructor Expression\n";
assignFrom(op);
}
template <class V>
FieldVector (const Dune::ExprTmpl::Vector<V> & op) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector<1> Copy Operator Vector\n";
assignFrom(op);
}
template <class E>
FieldVector& operator = (Dune::ExprTmpl::Expression<E> op) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector<1> Assignment Operator Expression\n";
return assignFrom(op);
}
template <class V>
FieldVector& operator = (const Dune::ExprTmpl::Vector<V> & op) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "FieldVector<1> Assignment Operator Vector\n";
return assignFrom(op);
}
#endif
//===== access to components
//! random access
K& operator[] (size_type i)
{
#ifdef DUNE_ISTL_WITH_CHECKING
if (i != 0) DUNE_THROW(MathError,"index out of range");
#endif
return p;
}
//! same for read only access
const K& operator[] (size_type i) const
{
#ifdef DUNE_ISTL_WITH_CHECKING
if (i != 0) DUNE_THROW(MathError,"index out of range");
#endif
return p;
}
//! Iterator class for sequential access
typedef FieldIterator<FieldVector<K,n>,K> Iterator;
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
//! typedef for stl compliant access
typedef Iterator iterator;
//! begin iterator
Iterator begin ()
{
return Iterator(*this,0);
}
//! end iterator
Iterator end ()
{
return Iterator(*this,n);
}
//! begin iterator
Iterator rbegin ()
{
return Iterator(*this,n-1);
}
//! end iterator
Iterator rend ()
{
return Iterator(*this,-1);
}
//! return iterator to given element or end()
Iterator find (size_type i)
if (i<n)
return Iterator(*this,i);
else
return Iterator(*this,n);
}
//! ConstIterator class for sequential access
typedef FieldIterator<const FieldVector<K,n>,const K> ConstIterator;
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
//! typedef for stl compliant access
typedef ConstIterator const_iterator;
//! begin ConstIterator
ConstIterator begin () const
{
return ConstIterator(*this,0);
}
//! end ConstIterator
ConstIterator end () const
{
return ConstIterator(*this,n);
}
//! begin ConstIterator
ConstIterator rbegin () const
{
return ConstIterator(*this,n-1);
}
//! end ConstIterator
ConstIterator rend () const
{
return ConstIterator(*this,-1);
}
//! return iterator to given element or end()
ConstIterator find (size_type i) const
if (i<n)
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
return ConstIterator(*this,i);
else
return ConstIterator(*this,n);
}
//===== vector space arithmetic
//! vector space add scalar to each comp
FieldVector& operator+= (const K& k)
{
p += k;
return *this;
}
//! vector space subtract scalar from each comp
FieldVector& operator-= (const K& k)
{
p -= k;
return *this;
}
//! vector space multiplication with scalar
FieldVector& operator*= (const K& k)
{
p *= k;
return *this;
}
//! vector space division by scalar
FieldVector& operator/= (const K& k)
{
p /= k;
return *this;
}
FieldVector& axpy (const K& a, const FieldVector& y)
{
p += a*y.p;
return *this;
}
inline K operator* ( const K & k ) const
//===== norms
//! one norm (sum over absolute values of entries)
double one_norm () const
{
Oliver Sander
committed
return std::abs(p);
}
//! simplified one norm (uses Manhattan norm for complex values)
double one_norm_real () const
{
return fvmeta_abs_real(p);
}
//! two norm sqrt(sum over squared values of entries)
double two_norm () const
{
return sqrt(fvmeta_abs2(p));
}
//! square of two norm (sum over squared values of entries), need for block recursion
double two_norm2 () const
{
return fvmeta_abs2(p);