Discontinuous Galerkin Library
#include "dg/algorithm.h"
operator.h
Go to the documentation of this file.
1#ifndef _DG_OPERATORS_DYN_
2#define _DG_OPERATORS_DYN_
3
4#include <vector>
5#include <algorithm>
6#include <cmath>
7#include <iterator>
8#include <stdexcept>
9#include <cassert>
10#include "dlt.h"
11#include "../blas1.h" // reproducible DOT products
12
13namespace dg{
14
26template< class T>
28{
29 public:
30 typedef T value_type;
34 Operator() = default;
40 explicit Operator( const unsigned n): n_(n), data_(n_*n_){}
47 Operator( const unsigned n, const T& value): n_(n), data_(n_*n_, value) {}
55 template< class InputIterator>
56 Operator( InputIterator first, InputIterator last, std::enable_if_t<!std::is_integral<InputIterator>::value>* = 0): data_(first, last)
57 {
58 unsigned n = std::distance( first, last);
59 n_ = (unsigned)sqrt( (double)n);
60 if( n_*n_!=n) throw Error( Message(_ping_)<<"Too few elements "<<n<<" need "<<n_*n_<<"\n");
61 }
67 Operator( const std::vector<T>& src): data_(src)
68 {
69 unsigned n = src.size();
70 n_ = (unsigned)sqrt( (double)n);
71 if( n_*n_!=n) throw Error( Message(_ping_)<<"Wrong number of elements "<<n<<" need "<<n_*n_<<"\n");
72 }
73
77 void zero() {
78 for( unsigned i=0; i<n_*n_; i++)
79 data_[i] = 0;
80 }
81
89 T& operator()(const size_t i, const size_t j){
90#ifdef DG_DEBUG
91 if(!(i<n_&&j<n_)) throw Error( Message(_ping_) << "You tried to access out of range "<<i<<" "<<j<<" size is "<<n_<<"\n");
92#endif
93 return data_[ i*n_+j];
94 }
101 const T& operator()(const size_t i, const size_t j) const {
102#ifdef DG_DEBUG
103 if(!(i<n_&&j<n_)) throw Error( Message(_ping_) << "You tried to access out of range "<<i<<" "<<j<<" size is "<<n_<<"\n");
104#endif
105 return data_[ i*n_+j];
106 }
107
113 unsigned size() const { return n_;}
120 void resize( unsigned m, T val = T()) {
121 n_ = m;
122 data_.resize( m*m, val);
123 }
124
130 const std::vector<value_type>& data() const {return data_;}
131
138 void swap_lines( const size_t i, const size_t k)
139 {
140 if(!( i< n_ && k<n_)) throw Error( Message(_ping_) << "Out of range "<<i<<" "<<k<<" range is "<<n_<<"\n");
141 for( size_t j = 0; j<n_; j++)
142 {
143 std::swap( data_[i*n_+j], data_[k*n_+j]);
144 }
145 }
146
153 {
154 Operator o(*this);
155 for( unsigned i=0; i<n_; i++)
156 for( unsigned j=0; j<i; j++)
157 {
158 std::swap( o.data_[i*n_+j], o.data_[j*n_+i]);
159 }
160 return o;
161 }
162
168 bool operator!=( const Operator& rhs) const{
169 for( size_t i = 0; i < n_*n_; i++)
170 if( data_[i] != rhs.data_[i])
171 return true;
172 return false;
173 }
174
180 bool operator==( const Operator& rhs) const {return !((*this != rhs));}
181
188 {
189 Operator temp(n_, 0.);
190 for( unsigned i=0; i<n_*n_; i++)
191 temp.data_[i] = -data_[i];
192 return temp;
193 }
202 {
203#ifdef DG_DEBUG
204 assert( op.size() == this->size());
205#endif//DG_DEBUG
206 for( unsigned i=0; i<n_*n_; i++)
207 data_[i] += op.data_[i];
208 return *this;
209 }
218 {
219#ifdef DG_DEBUG
220 assert( op.size() == this->size());
221#endif//DG_DEBUG
222 for( unsigned i=0; i<n_*n_; i++)
223 data_[i] -= op.data_[i];
224 return *this;
225 }
233 Operator& operator*=( const T& value )
234 {
235 for( unsigned i=0; i<n_*n_; i++)
236 data_[i] *= value;
237 return *this;
238 }
247 friend Operator operator+( const Operator& lhs, const Operator& rhs)
248 {
249 Operator temp(lhs);
250 temp+=rhs;
251 return temp;
252 }
261 friend Operator operator-( const Operator& lhs, const Operator& rhs)
262 {
263 Operator temp(lhs);
264 temp-=rhs;
265 return temp;
266 }
275 friend Operator operator*( const T& value, const Operator& rhs )
276 {
277 Operator temp(rhs);
278 temp*=value;
279 return temp;
280 }
281
290 friend Operator operator*( const Operator& lhs, const T& value)
291 {
292 return value*lhs;
293 }
294
303 friend Operator operator*( const Operator& lhs, const Operator& rhs)
304 {
305 unsigned n_ = lhs.n_;
306#ifdef DG_DEBUG
307 assert( lhs.size() == rhs.size());
308#endif//DG_DEBUG
309 Operator temp(n_, 0.);
310 for( unsigned i=0; i< n_; i++)
311 for( unsigned j=0; j<n_; j++)
312 {
313 temp.data_[i*n_+j] = (T)0;
314 for( unsigned k=0; k<n_; k++)
315 temp.data_[i*n_+j] += lhs.data_[i*n_+k]*rhs.data_[k*n_+j];
316 }
317 return temp;
318 }
319
327 template< class Ostream>
328 friend Ostream& operator<<(Ostream& os, const Operator& mat)
329 {
330 unsigned n_ = mat.n_;
331 for( size_t i=0; i < n_ ; i++)
332 {
333 for( size_t j = 0;j < n_; j++)
334 os << mat(i,j) << " ";
335 os << "\n";
336 }
337 return os;
338 }
339
349 template< class Istream>
350 friend Istream& operator>> ( Istream& is, Operator<T>& mat){
351 unsigned n_ = mat.n_;
352 for( size_t i=0; i<n_; i++)
353 for( size_t j=0; j<n_; j++)
354 is >> mat(i, j);
355 return is;
356 }
357
358 private:
359 unsigned n_;
360 std::vector<T> data_;
361};
362
363namespace create
364{
377template< class T>
378T lu_pivot( dg::Operator<T>& m, std::vector<unsigned>& p)
379{
380 //from numerical recipes
381 T pivot, determinant=(T)1;
382 unsigned pivotzeile, numberOfSwaps=0;
383 const size_t n = m.size();
384 p.resize( n);
385 for( size_t j = 0; j < n; j++) //gehe Spalten /Diagonale durch
386 {
387 //compute upper matrix except for the diagonal element (the pivot)
388 for( size_t i = 0; i< j; i++)
389 {
390 thrust::host_vector<T> mik(i), mkj(i);
391 for( size_t k=0; k<i; k++)
392 mik[k] = m(i,k), mkj[k] = m(k,j);
393 m(i,j) -= dg::blas1::dot( mik, mkj);
394 }
395 //compute canditates for pivot elements
396 for( size_t i = j; i< n; i++)
397 {
398 thrust::host_vector<T> mik(j), mkj(j);
399 for( size_t k=0; k<j; k++)
400 mik[k] = m(i,k), mkj[k] = m(k,j);
401 m(i,j) -= dg::blas1::dot( mik, mkj);
402 }
403 //search for absolute maximum of pivot candidates
404 pivot = m(j,j);
405 pivotzeile = j;
406 for( size_t i = j+1; i < n; i++)
407 if( fabs( m(i,j)) > fabs(pivot))
408 {
409 pivot = m(i,j), pivotzeile = i;
410 }
411
412 if( fabs(pivot) > 1e-15 )
413 {
414 if( pivotzeile != j)
415 {
416 m.swap_lines( pivotzeile, j);
417 numberOfSwaps++;
418 }
419 p[j] = pivotzeile;
420 //divide all elements below the diagonal by the pivot to get the lower matrix
421 for( size_t i=j+1; i<n; i++)
422 m(i,j) /= pivot;
423 determinant*=m(j,j);
424
425 }
426 else
427 throw std::runtime_error( "Matrix is singular!!");
428 }
429 if( numberOfSwaps % 2 != 0)
430 determinant*=-1.;
431 return determinant;
432
433}
434
444template<class T>
445void lu_solve( const dg::Operator<T>& lu, const std::vector<unsigned>& p, std::vector<T>& b)
446{
447 assert(p.size() == lu.size() && p.size() == b.size());
448 const size_t n = p.size();
449 // Vorwärtseinsetzen
450 for( size_t i = 0; i<n; i++)
451 {
452 //mache Zeilentausch
453 std::swap( b[ p[i] ], b[i]);
454 thrust::host_vector<T> lui(i), bi(i);
455 for( size_t j = 0; j < i; j++)
456 lui[j] = lu(i,j), bi[j] = b[j];
457 b[i] -= dg::blas1::dot( lui, bi);
458 }
459 // Rückwärtseinsetzen
460 for( int i = n-1; i>=0; i--)
461 {
462 thrust::host_vector<T> lui(n-(i+1)), bi(n-(i+1));
463 for( size_t j = i+1; j < n; j++)
464 lui[j-(i+1)] = lu(i,j), bi[j-(i+1)] = b[j];
465 b[i] -= dg::blas1::dot( lui, bi);
466 b[i] /= lu(i,i);
467 }
468}
469
470//
482template<class T>
484{
485 dg::Operator<T> out(in);
486 const unsigned n = in.size();
487 std::vector<unsigned> pivot( n);
488 dg::Operator<T> lu(in);
489 T determinant = lu_pivot( lu, pivot);
490 if( fabs(determinant ) < 1e-14)
491 throw std::runtime_error( "Determinant zero!");
492 for( unsigned i=0; i<n; i++)
493 {
494 std::vector<T> unit(n, 0);
495 unit[i] = 1;
496 lu_solve( lu, pivot, unit);
497 for( unsigned j=0; j<n; j++)
498 out(j,i) = unit[j];
499 }
500 return out;
501}
502
505
513template<class real_type>
515{
516 Operator<real_type> op(n, 0);
517 for( unsigned i=0; i<n; i++)
518 op( i,i) = 1.;
519 return op;
520}
528template<class real_type>
530{
531 Operator<real_type> op(n, 0);
532 for( unsigned i=0; i<n; i++)
533 op( i,i) = 2./(real_type)(2*i+1);
534 return op;
535}
543template<class real_type>
545{
546 Operator<real_type> op(n, 0);
547 for( unsigned i=0; i<n; i++)
548 op( i,i) = (real_type)(2*i+1)/2.;
549 return op;
550}
558template<class real_type>
560{
561 Operator<real_type> op(n, 0);
562 for( unsigned i=0; i<n; i++)
563 for( unsigned j=0; j<n; j++)
564 {
565 if( i < j)
566 {
567 if( (i+j)%2 != 0)
568 op( i, j) = 2;
569 }
570 }
571 return op;
572}
580template<class real_type>
582{
583 return Operator<real_type>( n, 1.);
584}
592template<class real_type>
594{
595 Operator<real_type> op( n, -1.);
596 for( unsigned i=0; i<n; i++)
597 for( unsigned j=0; j<n; j++)
598 if( j%2 == 0)
599 op( i,j) = 1.;
600 return op;
601}
609template<class real_type>
611 return rilj<real_type>( n).transpose();
612}
620template<class real_type>
622{
623 Operator<real_type> op( n, -1.);
624 for( unsigned i=0; i<n; i++)
625 for( unsigned j=0; j<n; j++)
626 if( ((i+j)%2) == 0)
627 op( i,j) = 1.;
628 return op;
629}
630
638template<class real_type>
640{
641 Operator<real_type> op( n, 0.);
642 for( int i=0; i<(int)n; i++)
643 for( int j=0; j<(int)n; j++)
644 {
645 if( i == j+1)
646 op( i,j) = 2./(2*i+1)/(2*j+1);
647 if( i == j-1)
648 op( i,j) = -2./(2*i+1)/(2*j+1);
649 }
650 op(0,0) = 2;
651 return op;
652}
653
654
662template<class real_type>
664{
665 unsigned n = dlt.weights().size();
666 Operator<real_type> op( n, 0);
667 for( unsigned i=0; i<n; i++)
668 op(i,i) = dlt.weights()[i];
669 return op;
670}
678template<class real_type>
680{
681 unsigned n = dlt.weights().size();
682 Operator<real_type> op( n, 0);
683 for( unsigned i=0; i<n; i++)
684 op(i,i) = 1./dlt.weights()[i];
685 return op;
686}
688}//namespace create
689
690
694template<class T>
696{
697 return dg::create::inverse(in);
698}
699
700} //namespace dg
701
702#endif //_DG_OPERATORS_DYN_
Struct holding coefficients for Discrete Legendre Transformation (DLT) related operations.
Definition: dlt.h:23
const std::vector< real_type > & weights() const
Return Gauss-Legendre weights.
Definition: dlt.h:42
class intended for the use in throw statements
Definition: exceptions.h:83
small class holding a stringstream
Definition: exceptions.h:29
A square nxn matrix.
Definition: operator.h:28
void zero()
Assign zero to all elements.
Definition: operator.h:77
T & operator()(const size_t i, const size_t j)
access operator
Definition: operator.h:89
Operator & operator*=(const T &value)
scalar multiply
Definition: operator.h:233
friend Operator operator-(const Operator &lhs, const Operator &rhs)
subtract
Definition: operator.h:261
Operator(const std::vector< T > &src)
Copy from existing data.
Definition: operator.h:67
friend Operator operator*(const Operator &lhs, const Operator &rhs)
matrix multiplication
Definition: operator.h:303
unsigned size() const
Size n of the Operator.
Definition: operator.h:113
T value_type
typically double or float
Definition: operator.h:30
friend Istream & operator>>(Istream &is, Operator< T > &mat)
Read values into a Matrix from given istream.
Definition: operator.h:350
void resize(unsigned m, T val=T())
Resize.
Definition: operator.h:120
Operator & operator-=(const Operator &op)
subtract
Definition: operator.h:217
bool operator==(const Operator &rhs) const
two Matrices are considered equal if elements are equal
Definition: operator.h:180
Operator(const unsigned n)
allocate storage for nxn matrix
Definition: operator.h:40
Operator()=default
Construct empty Operator.
friend Operator operator*(const Operator &lhs, const T &value)
scalar multiplication
Definition: operator.h:290
Operator operator-() const
subtract
Definition: operator.h:187
void swap_lines(const size_t i, const size_t k)
Swap two lines in the square matrix.
Definition: operator.h:138
const T & operator()(const size_t i, const size_t j) const
const access operator
Definition: operator.h:101
friend Operator operator*(const T &value, const Operator &rhs)
scalar multiplication
Definition: operator.h:275
Operator & operator+=(const Operator &op)
add
Definition: operator.h:201
friend Operator operator+(const Operator &lhs, const Operator &rhs)
add
Definition: operator.h:247
bool operator!=(const Operator &rhs) const
two Matrices are considered equal if elements are equal
Definition: operator.h:168
friend Ostream & operator<<(Ostream &os, const Operator &mat)
puts a matrix linewise in output stream
Definition: operator.h:328
const std::vector< value_type > & data() const
access underlying data
Definition: operator.h:130
Operator(InputIterator first, InputIterator last, std::enable_if_t<!std::is_integral< InputIterator >::value > *=0)
Construct from iterators.
Definition: operator.h:56
Operator transpose() const
Transposition.
Definition: operator.h:152
Operator(const unsigned n, const T &value)
Initialize elements.
Definition: operator.h:47
The discrete legendre trafo class.
#define _ping_
Definition: exceptions.h:12
get_value_type< ContainerType1 > dot(const ContainerType1 &x, const ContainerType2 &y)
Binary reproducible Euclidean dot product between two vectors
Definition: blas1.h:87
dg::Operator< T > inverse(const dg::Operator< T > &in)
Compute the inverse of a square matrix.
Definition: operator.h:483
T lu_pivot(dg::Operator< T > &m, std::vector< unsigned > &p)
LU Decomposition with partial pivoting.
Definition: operator.h:378
void lu_solve(const dg::Operator< T > &lu, const std::vector< unsigned > &p, std::vector< T > &b)
Solve the linear system with the LU decomposition.
Definition: operator.h:445
dg::Operator< T > invert(const dg::Operator< T > &in)
Alias for dg::create::inverse. Compute inverse of square matrix.
Definition: operator.h:695
MPI_Vector< thrust::host_vector< real_type > > weights(const aRealMPITopology2d< real_type > &g)
Nodal weight coefficients.
Definition: mpi_weights.h:22
MPI_Vector< thrust::host_vector< real_type > > inv_weights(const aRealMPITopology2d< real_type > &g)
inverse nodal weight coefficients
Definition: mpi_weights.h:29
Operator< real_type > lirj(unsigned n)
Create the LR-matrix.
Definition: operator.h:610
Operator< real_type > pipj(unsigned n)
Create the S-matrix.
Definition: operator.h:529
Operator< real_type > rirj(unsigned n)
Create the R-matrix.
Definition: operator.h:581
Operator< real_type > rilj(unsigned n)
Create the RL-matrix.
Definition: operator.h:593
Operator< real_type > delta(unsigned n)
Create the unit matrix.
Definition: operator.h:514
Operator< real_type > pidxpj(unsigned n)
Create the D-matrix.
Definition: operator.h:559
Operator< real_type > pipj_inv(unsigned n)
Create the T-matrix.
Definition: operator.h:544
Operator< real_type > lilj(unsigned n)
Create the L-matrix.
Definition: operator.h:621
Operator< real_type > ninj(unsigned n)
Create the N-matrix.
Definition: operator.h:639
ContainerType determinant(const SparseTensor< ContainerType > &t)
Definition: multiply.h:349
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...