Discontinuous Galerkin Library
#include "dg/algorithm.h"
extrapolation.h
Go to the documentation of this file.
1#pragma once
2
3#include "blas.h"
4#include "topology/operator.h"
5
6namespace dg
7{
8
36template<class ContainerType0, class ContainerType1>
37std::vector<double> least_squares( const std::vector<ContainerType0>& bs, const ContainerType1 & b)
38{
39 // Solve B^T B a = B^T b
40 unsigned size = bs.size();
41 dg::Operator<double> op( size, 0.); // B^T B
42 thrust::host_vector<double> rhs( size, 0.), opIi(rhs); // B^T b
43 std::vector<double> a(size,0.);
44 for( unsigned i=0; i<size; i++)
45 {
46 for( unsigned j=i; j<size; j++)
47 op(i,j) = dg::blas1::dot( bs[i], bs[j]);
48 for( unsigned j=0; j<i; j++)
49 op(i,j) = op(j,i);
50 rhs[i] = dg::blas1::dot( bs[i], b);
51 }
52 auto op_inv = dg::create::inverse( op);
53 // a = op_inv * rhs
54 for( unsigned i=0; i<size; i++)
55 {
56 for( unsigned j=0; j<size; j++)
57 opIi[j] = op_inv(i,j);
58 a[i] = dg::blas1::dot( rhs, opIi) ;
59 }
60 return a;
61}
62
85template<class ContainerType0, class ContainerType1>
87{
89 using container_type = ContainerType0;
90 LeastSquaresExtrapolation( ){ m_counter = 0; }
96 LeastSquaresExtrapolation( unsigned max, const ContainerType0& copyable0, const ContainerType1& copyable1) {
97 set_max(max, copyable0, copyable1);
98 }
100 void set_max( unsigned max, const ContainerType0& copyable0,
101 const ContainerType1& copyable1)
102 {
103 m_counter = 0;
104 m_x.assign( max, copyable0);
105 m_y.assign( max, copyable1);
106 m_max = max;
107 }
110 unsigned get_max( ) const{
111 return m_counter;
112 }
113
121 void extrapolate( double alpha, const ContainerType0& x, double beta,
122 ContainerType1& y) const{
123 unsigned size = m_counter;
124 thrust::host_vector<double> rhs( size, 0.), a(rhs), opIi(rhs); // B^T b
125 for( unsigned i=0; i<size; i++)
126 rhs[i] = dg::blas1::dot( m_x[i], x);
127 // a = op_inv * rhs
128 dg::blas1::scal( y, beta);
129 for( unsigned i=0; i<size; i++)
130 {
131 for( unsigned j=0; j<size; j++)
132 opIi[j] = m_op_inv(i,j);
133 a[i] = dg::blas1::dot( rhs, opIi) ;
134 dg::blas1::axpby( alpha*a[i], m_y[i], 1., y);
135 }
136 }
142 void extrapolate( const ContainerType0& x, ContainerType1& y) const{
143 extrapolate( 1., x, 0., y);
144 }
145
156 void update( const ContainerType0& x_new, const ContainerType1& y_new){
157 if( m_max == 0) return;
158 unsigned size = m_counter < m_max ? m_counter + 1 : m_max;
159 dg::Operator<double> op( size, 0.), op_inv( size, 0.); // B^T B
160 //i = 0
161 op(0,0) = dg::blas1::dot( x_new, x_new);
162 for( unsigned j=1; j<size; j++)
163 op(0,j) = op( j, 0) = dg::blas1::dot( x_new, m_x[j-1]);
164 // recursively fill in previous values
165 for( unsigned i=1; i<size; i++)
166 for( unsigned j=1; j<size; j++)
167 op(i,j) = m_op(i-1,j-1);
168 // test if new value is linearly independent or zero
169 try{
170 op_inv = dg::create::inverse( op);
171 }
172 catch ( std::runtime_error & e){
173 return;
174 }
175 m_op_inv = op_inv, m_op = op;
176 if( m_counter < m_max)
177 m_counter++;
178 //push out last value (keep track of what is oldest value
179 std::rotate( m_x.rbegin(), m_x.rbegin()+1, m_x.rend());
180 std::rotate( m_y.rbegin(), m_y.rbegin()+1, m_y.rend());
181 blas1::copy( x_new, m_x[0]);
182 blas1::copy( y_new, m_y[0]);
183 }
184
185 private:
186 unsigned m_max, m_counter;
187 std::vector<ContainerType0> m_x;
188 std::vector<ContainerType1> m_y;
189 dg::Operator<double> m_op, m_op_inv;
190};
191
214template<class ContainerType>
216{
218 using container_type = ContainerType;
221 Extrapolation( ){ m_counter = 0; }
229 Extrapolation( unsigned max, const ContainerType& copyable) {
230 set_max(max, copyable);
231 }
233 void set_max( unsigned max, const ContainerType& copyable)
234 {
235 m_counter = 0;
236 m_x.assign( max, copyable);
237 m_t.assign( max, 0);
238 m_max = max;
239 }
247 unsigned get_max( ) const{
248 return m_counter;
249 }
250
251
264 bool exists( value_type t)const{
265 if( m_max == 0) return false;
266 for( unsigned i=0; i<m_counter; i++)
267 if( fabs(t - m_t[i]) <1e-14)
268 return true;
269 return false;
270 }
271
282 template<class ContainerType0>
283 void extrapolate( value_type t, ContainerType0& new_x) const{
284 switch(m_counter)
285 {
286 case(0): dg::blas1::copy( 0, new_x);
287 break;
288 case(1): dg::blas1::copy( m_x[0], new_x);
289 break;
290 case(3): {
291 value_type f0 = (t-m_t[1])*(t-m_t[2])/(m_t[0]-m_t[1])/(m_t[0]-m_t[2]);
292 value_type f1 =-(t-m_t[0])*(t-m_t[2])/(m_t[0]-m_t[1])/(m_t[1]-m_t[2]);
293 value_type f2 = (t-m_t[0])*(t-m_t[1])/(m_t[2]-m_t[0])/(m_t[2]-m_t[1]);
295 f0, m_x[0], f1, m_x[1], f2, m_x[2]);
296 break;
297 }
298 default: {
299 value_type f0 = (t-m_t[1])/(m_t[0]-m_t[1]);
300 value_type f1 = (t-m_t[0])/(m_t[1]-m_t[0]);
301 dg::blas1::axpby( f0, m_x[0], f1, m_x[1], new_x);
302 }
303 }
304 }
305
319 template<class ContainerType0>
320 void derive( value_type t, ContainerType0& dot_x) const{
321 switch(m_counter)
322 {
323 case(0): dg::blas1::copy( 0, dot_x);
324 break;
325 case(1): dg::blas1::copy( 0, dot_x);
326 break;
327 case(3): {
328 value_type f0 =-(-2.*t+m_t[1]+m_t[2])/(m_t[0]-m_t[1])/(m_t[0]-m_t[2]);
329 value_type f1 = (-2.*t+m_t[0]+m_t[2])/(m_t[0]-m_t[1])/(m_t[1]-m_t[2]);
330 value_type f2 =-(-2.*t+m_t[0]+m_t[1])/(m_t[2]-m_t[0])/(m_t[2]-m_t[1]);
332 f0, m_x[0], f1, m_x[1], f2, m_x[2]);
333 break;
334 }
335 default: {
336 value_type f0 = 1./(m_t[0]-m_t[1]);
337 value_type f1 = 1./(m_t[1]-m_t[0]);
338 dg::blas1::axpby( f0, m_x[0], f1, m_x[1], dot_x);
339 }
340 }
341 }
342
349 template<class ContainerType0>
350 void extrapolate( ContainerType0& new_x) const{
351 value_type t = m_t[0] +1.;
352 extrapolate( t, new_x);
353 }
360 template<class ContainerType0>
361 void derive( ContainerType0& dot_x) const{
362 derive( m_t[0], dot_x);
363 }
364
371 template<class ContainerType0>
372 void update( value_type t_new, const ContainerType0& new_entry){
373 if( m_max == 0) return;
374 //check if entry is already there to avoid division by zero errors
375 for( unsigned i=0; i<m_counter; i++)
376 if( fabs(t_new - m_t[i]) <1e-14)
377 {
378 blas1::copy( new_entry, m_x[i]);
379 return;
380 }
381 if( m_counter < m_max) //don't update counter if Time entry was rejected
382 m_counter++;
383 //push out last value (keep track of what is oldest value
384 std::rotate( m_x.rbegin(), m_x.rbegin()+1, m_x.rend());
385 std::rotate( m_t.rbegin(), m_t.rbegin()+1, m_t.rend());
386 m_t[0] = t_new;
387 blas1::copy( new_entry, m_x[0]);
388 }
395 template<class ContainerType0>
396 void update( const ContainerType0& new_entry){
397 value_type t_new = m_t[0] + 1;
398 update( t_new, new_entry);
399 }
400
405 const ContainerType& head()const{
406 return m_x[0];
407 }
409 ContainerType& tail(){
410 return m_x[m_max-1];
411 }
413 const ContainerType& tail()const{
414 return m_x[m_max-1];
415 }
416
417 private:
418 unsigned m_max, m_counter;
419 std::vector<value_type> m_t;
420 std::vector<ContainerType> m_x;
421};
422
423
424}//namespace dg
void copy(const ContainerTypeIn &source, ContainerTypeOut &target)
Definition: blas1.h:164
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
Definition: blas1.h:231
void scal(ContainerType &x, get_value_type< ContainerType > alpha)
Definition: blas1.h:185
void evaluate(ContainerType &y, BinarySubroutine f, Functor g, const ContainerType0 &x0, const ContainerTypes &...xs)
Definition: blas1.h:556
get_value_type< ContainerType1 > dot(const ContainerType1 &x, const ContainerType2 &y)
Binary reproducible Euclidean dot product between two vectors
Definition: blas1.h:87
@ y
y direction
@ x
x direction
dg::Operator< T > inverse(const dg::Operator< T > &in)
Compute the inverse of a square matrix.
Definition: operator.h:483
std::vector< double > least_squares(const std::vector< ContainerType0 > &bs, const ContainerType1 &b)
Compute for given and .
Definition: extrapolation.h:37
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition: tensor_traits.h:38
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
Extrapolate a polynomial passing through up to three points.
Definition: extrapolation.h:216
void derive(value_type t, ContainerType0 &dot_x) const
Evaluate first derivative of interpolating polynomial
Definition: extrapolation.h:320
void extrapolate(value_type t, ContainerType0 &new_x) const
Extrapolate value to given time.
Definition: extrapolation.h:283
get_value_type< ContainerType > value_type
Definition: extrapolation.h:217
bool exists(value_type t) const
Check if time exists in current points.
Definition: extrapolation.h:264
unsigned get_max() const
Current extrapolation count.
Definition: extrapolation.h:247
Extrapolation(unsigned max, const ContainerType &copyable)
Set maximum extrapolation order and allocate memory.
Definition: extrapolation.h:229
void extrapolate(ContainerType0 &new_x) const
Extrapolate value (equidistant version)
Definition: extrapolation.h:350
ContainerType & tail()
DEPRECATED write access to tail value ( the one that will be deleted in the next update,...
Definition: extrapolation.h:409
void derive(ContainerType0 &dot_x) const
Evaluate first derivative of interpolating polynomial (equidistant version)
Definition: extrapolation.h:361
const ContainerType & tail() const
DEPRECATED read access to tail value ( the one that will be deleted in the next update,...
Definition: extrapolation.h:413
const ContainerType & head() const
return the current head (the one most recently inserted)
Definition: extrapolation.h:405
ContainerType container_type
Definition: extrapolation.h:218
void update(const ContainerType0 &new_entry)
insert a new entry
Definition: extrapolation.h:396
Extrapolation()
Leave values uninitialized.
Definition: extrapolation.h:221
void set_max(unsigned max, const ContainerType &copyable)
Set maximum extrapolation order and allocate memory.
Definition: extrapolation.h:233
void update(value_type t_new, const ContainerType0 &new_entry)
insert a new entry, deleting the oldest entry or update existing entry
Definition: extrapolation.h:372
Evaluate a least squares fit
Definition: extrapolation.h:87
void set_max(unsigned max, const ContainerType0 &copyable0, const ContainerType1 &copyable1)
Set maximum number of vectors and allocate memory.
Definition: extrapolation.h:100
void extrapolate(double alpha, const ContainerType0 &x, double beta, ContainerType1 &y) const
extrapolate value at a new unkown value
Definition: extrapolation.h:121
LeastSquaresExtrapolation(unsigned max, const ContainerType0 &copyable0, const ContainerType1 &copyable1)
Set maximum number of vectors and allocate memory.
Definition: extrapolation.h:96
void update(const ContainerType0 &x_new, const ContainerType1 &y_new)
insert a new entry / train the machine learning algorithm
Definition: extrapolation.h:156
unsigned get_max() const
Definition: extrapolation.h:110
LeastSquaresExtrapolation()
Definition: extrapolation.h:90
get_value_type< ContainerType0 > value_type
Definition: extrapolation.h:88
ContainerType0 container_type
Definition: extrapolation.h:89
void extrapolate(const ContainerType0 &x, ContainerType1 &y) const
extrapolate value at a new unkown value
Definition: extrapolation.h:142
Definition: subroutines.h:108
Definition: subroutines.h:22