PFASST++
scalar_sweeper.hpp
Go to the documentation of this file.
1 
14 #ifndef _EXAMPLES__SCALAR__SCALAR_SWEEPER_HPP_
15 #define _EXAMPLES__SCALAR__SCALAR_SWEEPER_HPP_
16 
17 #include <complex>
18 #include <vector>
19 using namespace std;
20 
21 #include <pfasst/logging.hpp>
23 #include <pfasst/encap/vector.hpp>
24 
25 
26 namespace pfasst
27 {
28  namespace examples
29  {
40  namespace scalar
41  {
50  template<typename time = pfasst::time_precision>
52  : public encap::IMEXSweeper<time>
53  {
54  private:
56 
59 
61  complex<double> lambda, u0;
62 
64  const complex<double> i_complex = complex<double>(0, 1);
65 
67  double error;
68 
70  size_t n_f_expl_eval, n_f_impl_eval, n_impl_solve;
71 
72  public:
79  ScalarSweeper(const complex<double>& lambda, const complex<double>& u0)
80  : lambda(lambda)
81  , u0(u0)
82  , error(0.0)
83  , n_f_expl_eval(0)
84  , n_f_impl_eval(0)
85  , n_impl_solve(0)
86  {}
87 
91  virtual ~ScalarSweeper()
92  {
93  ML_LOG(INFO, "Final error: " << this->error);
94  ML_LOG(INFO, "Number of explicit evaluations:" << this->n_f_expl_eval);
95  ML_LOG(INFO, "Number of implicit evaluations:" << this->n_f_impl_eval);
96  ML_LOG(INFO, "Number of implicit solves: " << this->n_impl_solve);
97  }
98 
104  void echo_error(time t)
105  {
106  auto& qend = encap::as_vector<complex<double>, time>(this->get_end_state());
107 
108  complex_vector_type qex(qend.size());
109 
110  this->exact(qex, t);
111  double max_err = abs(qend[0] - qex[0]) / abs(qex[0]);
112  ML_LOG(INFO, "err:" << max_err);
113  this->error = max_err;
114  }
115 
119  double get_errors()
120  {
121  return this->error;
122  }
123 
127  void post_predict() override
128  {
129  time t = this->get_controller()->get_time();
130  time dt = this->get_controller()->get_step_size();
131  this->echo_error(t + dt);
132  }
133 
137  void post_sweep() override
138  {
139  time t = this->get_controller()->get_time();
140  time dt = this->get_controller()->get_step_size();
141  this->echo_error(t + dt);
142  }
143 
149  void exact(complex_vector_type& q, time t)
150  {
151  q[0] = this->u0 * exp(this->lambda * t);
152  }
153 
154  void exact(shared_ptr<encap_type> q_encap, time t)
155  {
156  auto& q = encap::as_vector<complex<double>, time>(q_encap);
157  this->exact(q, t);
158  }
159 
163  void f_expl_eval(shared_ptr<encap_type> f_encap,
164  shared_ptr<encap_type> q_encap, time t) override
165  {
166  UNUSED(t);
167  auto& f = encap::as_vector<complex<double>, time>(f_encap);
168  auto& q = encap::as_vector<complex<double>, time>(q_encap);
169 
170  // f_expl = multiply with imaginary part of lambda
171  f[0] = this->i_complex * imag(this->lambda) * q[0];
172 
173  this->n_f_expl_eval++;
174  }
175 
179  void f_impl_eval(shared_ptr<encap_type> f_encap,
180  shared_ptr<encap_type> q_encap, time t) override
181  {
182  UNUSED(t);
183  auto& f = encap::as_vector<complex<double>, time>(f_encap);
184  auto& q = encap::as_vector<complex<double>, time>(q_encap);
185 
186  // f_impl = multiply with real part of lambda
187  f[0] = real(this->lambda) * q[0];
188 
189  this->n_f_impl_eval++;
190  }
191 
197  void impl_solve(shared_ptr<encap_type> f_encap,
198  shared_ptr<encap_type> q_encap, time t, time dt,
199  shared_ptr<encap_type> rhs_encap) override
200  {
201  UNUSED(t);
202  auto& f = encap::as_vector<complex<double>, time>(f_encap);
203  auto& q = encap::as_vector<complex<double>, time>(q_encap);
204  auto& rhs = encap::as_vector<complex<double>, time>(rhs_encap);
205 
206  // invert f_impl = multiply with inverse of real part of lambda
207  double inv = 1.0 / (1.0 - double(dt) * real(this->lambda));
208  q[0] = inv * rhs[0];
209 
210  // compute f_impl_eval of q[0], i.e. multiply with real(lambda)
211  f[0] = real(this->lambda) * q[0];
212 
213  this->n_impl_solve++;
214  }
215  };
216  } // ::pfasst::examples::scalar
217  } // ::pfasst::examples
218 } // ::pfasst
219 
220 #endif // _EXAMPLES__SCALAR__SCALAR_SWEEPER_HPP_
Semi-implicit IMEX sweeper.
void post_sweep() override
post sweep, update error.
void echo_error(time t)
compute error between last state and exact solution at time tand print it to cout ...
void f_impl_eval(shared_ptr< encap_type > f_encap, shared_ptr< encap_type > q_encap, time t) override
evaluate the implicit part of the right hand side: Multiply with \( \text{real}(\lambda) \) ...
double error
error at the final time. For the scalar example, an analytical solution is known. ...
STL namespace.
double get_errors()
returns error, but does not update it!
encap::Encapsulation< time > encap_type
#define ML_LOG(level, x)
same as LOG(level, x) from easylogging++
Definition: logging.hpp:110
virtual ~ScalarSweeper()
upon destruction, report final error and number of function calls
void impl_solve(shared_ptr< encap_type > f_encap, shared_ptr< encap_type > q_encap, time t, time dt, shared_ptr< encap_type > rhs_encap) override
for given \( b \), solve \( \left( \mathbb{I}_d - \Delta t \text{real}(\lambda) \right) u = b \) for ...
void exact(complex_vector_type &q, time t)
computes the exact solution \( u_0 \exp \left( \lambda*t \right) \) at a given time t...
void exact(shared_ptr< encap_type > q_encap, time t)
void f_expl_eval(shared_ptr< encap_type > f_encap, shared_ptr< encap_type > q_encap, time t) override
evaluate the explicit part of the right hand side: Multiply with \( \text{imag}(\lambda) \) ...
ScalarSweeper(const complex< double > &lambda, const complex< double > &u0)
generic constructor; initialize all function call counters with zero.
Data/solution encapsulation.
tuple t
Definition: plot.py:12
#define UNUSED(expr)
Denoting unused function parameters for omitting compiler warnings.
Definition: globals.hpp:32
encap::VectorEncapsulation< complex< double > > complex_vector_type
define a type for a complex PFASST vector encapsulation.
void post_predict() override
post prediction step, update of error.
float dt
Definition: plot.py:10
Sweeper for scalar test equation.