PFASST++
imex_sweeper_impl.hpp
Go to the documentation of this file.
2 
3 #include <algorithm>
4 #include <cassert>
5 using namespace std;
6 
7 #include "pfasst/globals.hpp"
8 #include "pfasst/logging.hpp"
9 
10 
11 namespace pfasst
12 {
13  namespace encap
14  {
15  template<typename time>
17  {
18  vector<shared_ptr<Encapsulation<time>>> dst = { this->end_state };
19  dst[0]->copy(this->start_state);
20  dst[0]->mat_apply(dst, dt, this->quadrature->get_b_mat(), this->fs_expl, false);
21  dst[0]->mat_apply(dst, dt, this->quadrature->get_b_mat(), this->fs_impl, false);
22  }
23 
24  template<typename time>
25  void IMEXSweeper<time>::setup(bool coarse)
26  {
28 
29  auto const num_nodes = this->quadrature->get_num_nodes();
30  auto const num_s_integrals = this->quadrature->left_is_node() ? num_nodes - 1 : num_nodes;
31 
32  for (size_t m = 0; m < num_nodes; m++) {
33  this->fs_expl.push_back(this->get_factory()->create(pfasst::encap::function));
34  this->fs_impl.push_back(this->get_factory()->create(pfasst::encap::function));
35  }
36  for (size_t m = 0; m < num_s_integrals; m++) {
37  this->s_integrals.push_back(this->get_factory()->create(pfasst::encap::solution));
38  }
39 
40  if (! this->quadrature->left_is_node()) {
41  this->fs_expl_start = this->get_factory()->create(pfasst::encap::function);
42  }
43 
44  size_t nsteps = this->get_controller()->get_end_time() / this->get_controller()->get_step_size();
45  size_t digit_step = (this->get_controller()->get_step_size() > 0) ?
46  to_string(nsteps + 1).length() : 3;
47  size_t digit_iter = (this->get_controller()->get_max_iterations() > 0) ?
48  to_string(this->get_controller()->get_max_iterations() - 1).length() : 3;
49  this->FORMAT_STR = "step: %|" + to_string(digit_step) + "| iter: %|" + to_string(digit_iter) + "|"
50  + " n1: %|2| n2: %|3|"
51  + " residual: %10.4e" + " err: %10.4e";
52  }
53 
54  template<typename time>
55  void IMEXSweeper<time>::predict(bool initial)
56  {
57  if (this->quadrature->left_is_node()) {
58  this->predict_with_left(initial);
59  } else {
60  this->predict_without_left(initial);
61  }
62 
63  if (this->quadrature->right_is_node()) {
64  this->end_state->copy(this->state.back());
65  } else {
66  this->integrate_end_state(this->get_controller()->get_step_size());
67  }
68  }
69 
70  template<typename time>
72  {
73  if (this->quadrature->left_is_node()) {
74  this->sweep_with_left();
75  } else {
76  this->sweep_without_left();
77  }
78 
79  if (this->quadrature->right_is_node()) {
80  this->end_state->copy(this->state.back());
81  } else {
82  this->integrate_end_state(this->get_controller()->get_step_size());
83  }
84  }
85 
86  template<typename time>
88  {
89  this->start_state->copy(this->end_state);
90  if (this->quadrature->left_is_node() && this->quadrature->right_is_node()) {
91  this->state[0]->copy(this->start_state);
92  this->fs_expl.front()->copy(this->fs_expl.back());
93  this->fs_impl.front()->copy(this->fs_impl.back());
94  }
95  }
96 
97  template<typename time>
98  void IMEXSweeper<time>::reevaluate(bool initial_only)
99  {
100  time t0 = this->get_controller()->get_time();
101  time dt = this->get_controller()->get_step_size();
102  if (initial_only) {
103  if (this->quadrature->left_is_node()) {
104  this->f_expl_eval(this->fs_expl[0], this->state[0], t0);
105  this->f_impl_eval(this->fs_impl[0], this->state[0], t0);
106  } else {
107  throw NotImplementedYet("reevaluate");
108  }
109  } else {
110  for (size_t m = 0; m < this->quadrature->get_num_nodes(); m++) {
111  time t = t0 + dt * this->quadrature->get_nodes()[m];
112  this->f_expl_eval(this->fs_expl[m], this->state[m], t);
113  this->f_impl_eval(this->fs_impl[m], this->state[m], t);
114  }
115  }
116  }
117 
118  template<typename time>
119  void IMEXSweeper<time>::integrate(time dt, vector<shared_ptr<Encapsulation<time>>> dst) const
120  {
121  auto const q_mat = this->quadrature->get_q_mat();
122  dst[0]->mat_apply(dst, dt, q_mat, this->fs_expl, true);
123  dst[0]->mat_apply(dst, dt, q_mat, this->fs_impl, false);
124  }
125 
126  template<typename time>
127  void IMEXSweeper<time>::residual(time dt, vector<shared_ptr<Encapsulation<time>>> dst) const
128  {
129  for (size_t m = 0; m < this->quadrature->get_num_nodes(); m++) {
130  dst[m]->copy(this->start_state);
131  dst[m]->saxpy(-1.0, this->state[m]);
132  }
133  if (this->fas_corrections.size() > 0) {
134  // XXX: build a matrix and use mat_apply to do this
135  for (size_t m = 0; m < this->quadrature->get_num_nodes(); m++) {
136  for (size_t n = 0; n <= m; n++) {
137  dst[m]->saxpy(1.0, this->fas_corrections[n]);
138  }
139  }
140  }
141  dst[0]->mat_apply(dst, dt, this->quadrature->get_q_mat(), this->fs_expl, false);
142  dst[0]->mat_apply(dst, dt, this->quadrature->get_q_mat(), this->fs_impl, false);
143  }
144 
145  template<typename time>
147  shared_ptr<Encapsulation<time>> u_encap,
148  time t)
149  {
150  UNUSED(f_expl_encap); UNUSED(u_encap); UNUSED(t);
151  throw NotImplementedYet("imex (f_expl_eval)");
152  }
153 
154  template<typename time>
156  shared_ptr<Encapsulation<time>> u_encap,
157  time t)
158  {
159  UNUSED(f_impl_encap); UNUSED(u_encap); UNUSED(t);
160  throw NotImplementedYet("imex (f_impl_eval)");
161  }
162 
163  template<typename time>
165  shared_ptr<Encapsulation<time>> u_encap,
166  time t, time dt,
167  shared_ptr<Encapsulation<time>> rhs_encap)
168  {
169  UNUSED(f_encap); UNUSED(u_encap); UNUSED(t); UNUSED(dt); UNUSED(rhs_encap);
170  throw NotImplementedYet("imex (impl_solve)");
171  }
172 
173  template<typename time>
175  {
176  time dt = this->get_controller()->get_step_size();
177  time t = this->get_controller()->get_time();
178  ML_CVLOG(1, "Sweeper", "predicting step " << this->get_controller()->get_step() + 1
179  << " (t=" << t << ", dt=" << dt << ")");
180 
181  if (initial) {
182  this->state[0]->copy(this->start_state);
183  this->f_expl_eval(this->fs_expl[0], this->state[0], t);
184  this->f_impl_eval(this->fs_impl[0], this->state[0], t);
185  }
186 
187  shared_ptr<Encapsulation<time>> rhs = this->get_factory()->create(pfasst::encap::solution);
188 
189  auto const nodes = this->quadrature->get_nodes();
190 
191  // step across all nodes
192  for (size_t m = 0; m < nodes.size() - 1; ++m) {
193  time ds = dt * (nodes[m+1] - nodes[m]);
194  rhs->copy(this->state[m]);
195  rhs->saxpy(ds, this->fs_expl[m]);
196  this->impl_solve(this->fs_impl[m + 1], this->state[m + 1], t, ds, rhs);
197  this->f_expl_eval(this->fs_expl[m + 1], this->state[m + 1], t + ds);
198  t += ds;
199  }
200  }
201 
202  template<typename time>
204  {
205  UNUSED(initial);
206  time dt = this->get_controller()->get_step_size();
207  time t = this->get_controller()->get_time();
208  ML_CVLOG(1, "Sweeper", "predicting step " << this->get_controller()->get_step() + 1
209  << " (t=" << t << ", dt=" << dt << ")");
210  time ds;
211 
212  shared_ptr<Encapsulation<time>> rhs = this->get_factory()->create(pfasst::encap::solution);
213 
214  auto const nodes = this->quadrature->get_nodes();
215 
216  // step to first node
217  ds = dt * nodes[0];
218  this->f_expl_eval(this->fs_expl_start, this->start_state, t);
219  rhs->copy(this->start_state);
220  rhs->saxpy(ds, this->fs_expl_start);
221  this->impl_solve(this->fs_impl[0], this->state[0], t, ds, rhs);
222  this->f_expl_eval(this->fs_expl[0], this->state[0], t + ds);
223 
224  // step across all nodes
225  for (size_t m = 0; m < nodes.size() - 1; ++m) {
226  ds = dt * (nodes[m+1] - nodes[m]);
227  rhs->copy(this->state[m]);
228  rhs->saxpy(ds, this->fs_expl[m]);
229  this->impl_solve(this->fs_impl[m+1], this->state[m+1], t, ds, rhs);
230  this->f_expl_eval(this->fs_expl[m+1], this->state[m+1], t + ds);
231  t += ds;
232  }
233  }
234 
235  template<typename time>
237  {
238  auto const nodes = this->quadrature->get_nodes();
239  auto const dt = this->get_controller()->get_step_size();
240  auto const s_mat = this->quadrature->get_s_mat().block(1, 0, nodes.size()-1, nodes.size());
241  ML_CVLOG(1, "Sweeper", "sweeping on step " << this->get_controller()->get_step() + 1
242  << " in iteration " << this->get_controller()->get_iteration()
243  << " (dt=" << dt << ")");
244  time ds;
245 
246  this->s_integrals[0]->mat_apply(this->s_integrals, dt, s_mat, this->fs_expl, true);
247  this->s_integrals[0]->mat_apply(this->s_integrals, dt, s_mat, this->fs_impl, false);
248  for (size_t m = 0; m < nodes.size() - 1; ++m) {
249  ds = dt * (nodes[m+1] - nodes[m]);
250  this->s_integrals[m]->saxpy(-ds, this->fs_expl[m]);
251  this->s_integrals[m]->saxpy(-ds, this->fs_impl[m+1]);
252  }
253  if (this->fas_corrections.size() > 0) {
254  for (size_t m = 0; m < this->s_integrals.size(); m++) {
255  this->s_integrals[m]->saxpy(1.0, this->fas_corrections[m+1]);
256  }
257  }
258 
259  shared_ptr<Encapsulation<time>> rhs = this->get_factory()->create(pfasst::encap::solution);
260 
261  // step across all nodes
262  auto t = this->get_controller()->get_time();
263  for (size_t m = 0; m < nodes.size() - 1; ++m) {
264  ds = dt * (nodes[m+1] - nodes[m]);
265  rhs->copy(this->state[m]);
266  rhs->saxpy(ds, this->fs_expl[m]);
267  rhs->saxpy(1.0, this->s_integrals[m]);
268  this->impl_solve(this->fs_impl[m + 1], this->state[m + 1], t, ds, rhs);
269  this->f_expl_eval(this->fs_expl[m + 1], this->state[m + 1], t + ds);
270  t += ds;
271  }
272  }
273 
274  template<typename time>
276  {
277  auto const nodes = this->quadrature->get_nodes();
278  auto const dt = this->get_controller()->get_step_size();
279  auto const s_mat = this->quadrature->get_s_mat();
280  ML_CVLOG(1, "Sweeper", "sweeping on step " << this->get_controller()->get_step() + 1
281  << " in iteration " << this->get_controller()->get_iteration()
282  << " (dt=" << dt << ")");
283  time ds;
284 
285  this->s_integrals[0]->mat_apply(this->s_integrals, dt, s_mat, this->fs_expl, true);
286  this->s_integrals[0]->mat_apply(this->s_integrals, dt, s_mat, this->fs_impl, false);
287  ds = dt * nodes[0];
288  this->s_integrals[0]->saxpy(-ds, this->fs_expl_start);
289  this->s_integrals[0]->saxpy(-ds, this->fs_impl[0]);
290  for (size_t m = 0; m < nodes.size() - 1; ++m) {
291  ds = dt * (nodes[m+1] - nodes[m]);
292  this->s_integrals[m+1]->saxpy(-ds, this->fs_expl[m]);
293  this->s_integrals[m+1]->saxpy(-ds, this->fs_impl[m+1]);
294  }
295  if (this->fas_corrections.size() > 0) {
296  for (size_t m = 0; m < this->s_integrals.size(); m++) {
297  this->s_integrals[m]->saxpy(1.0, this->fas_corrections[m]);
298  }
299  }
300 
301  shared_ptr<Encapsulation<time>> rhs = this->get_factory()->create(pfasst::encap::solution);
302 
303  // step to first node
304  auto t = this->get_controller()->get_time();
305  ds = dt * nodes[0];
306  this->f_expl_eval(this->fs_expl_start, this->start_state, t);
307  rhs->copy(this->start_state);
308  rhs->saxpy(ds, this->fs_expl_start);
309  rhs->saxpy(1.0, this->s_integrals[0]);
310  this->impl_solve(this->fs_impl[0], this->state[0], t, ds, rhs);
311  this->f_expl_eval(this->fs_expl[0], this->state[0], t + ds);
312 
313  // step across all nodes
314  for (size_t m = 0; m < nodes.size() - 1; ++m) {
315  ds = dt * (nodes[m+1] - nodes[m]);
316  rhs->copy(this->state[m]);
317  rhs->saxpy(ds, this->fs_expl[m]);
318  rhs->saxpy(1.0, this->s_integrals[m+1]);
319  this->impl_solve(this->fs_impl[m+1], this->state[m+1], t, ds, rhs);
320  this->f_expl_eval(this->fs_expl[m+1], this->state[m+1], t + ds);
321  t += ds;
322  }
323  }
324  } // ::pfasst::encap
325 } // ::pfasst
Semi-implicit IMEX sweeper.
void setup(shared_ptr< WrapperInterface< scalar, time >> wrapper)
Not implemented yet exception.
Definition: interfaces.hpp:29
STL namespace.
virtual void setup(bool coarse) override
Setup (allocate etc) the sweeper.
Data/solution encapsulation.
#define ML_CVLOG(verbose_level, logger_id, x)
same as CVLOG(verbosity, logger, x) from easylogging++
Definition: logging.hpp:131
tuple t
Definition: plot.py:12
#define UNUSED(expr)
Denoting unused function parameters for omitting compiler warnings.
Definition: globals.hpp:32
virtual const vector< time > get_nodes() const
float dt
Definition: plot.py:10