PFASST++
pfasst_impl.hpp
Go to the documentation of this file.
2 
3 #include "pfasst/logging.hpp"
4 
5 
6 namespace pfasst
7 {
8  template<typename time>
9  void PFASST<time>::perform_sweeps(size_t level)
10  {
11  auto sweeper = this->get_level(level);
12  for (size_t s = 0; s < this->nsweeps[level]; s++) {
13  if (predict) {
14  sweeper->predict(predict);
15  sweeper->post_predict();
16  predict = false;
17  } else {
18  sweeper->sweep();
19  sweeper->post_sweep();
20  }
21  }
22  }
23 
29  template<typename time>
31  {
32  this->comm = comm;
33  }
34 
39  template<typename time>
41  {
42  if (this->comm->size() == 1) {
44  return;
45  }
46 
47  int nblocks = int(this->get_end_time() / this->get_step_size()) / comm->size();
48 
49  if (nblocks == 0) {
50  ML_CLOG(INFO, "Controller", "invalid duration: there are more time processors than time steps");
51  throw ValueError("invalid duration: there are more time processors than time steps");
52  }
53 
54  if (nblocks * comm->size() * this->get_step_size() < this->get_end_time()) {
55  ML_CLOG(INFO, "Controller", "invalid duration: mismatch between number of time processors and time steps");
56  throw ValueError("invalid duration: mismatch between number of time processors and time steps");
57  }
58 
59  for (int nblock = 0; nblock < nblocks; nblock++) {
60  this->set_step(nblock * comm->size() + comm->rank());
61 
62  predictor();
63 
64  ML_CLOG(DEBUG, "Controller", "iterating on step " << this->get_step()
65  << " (0/" << this->get_max_iterations() << ")");
66  for (this->set_iteration(0);
67  this->get_iteration() < this->get_max_iterations() && this->comm->status->keep_iterating();
68  this->advance_iteration()) {
69 
70  if (this->comm->status->previous_is_iterating()) {
71  post();
72  }
73  cycle_v(this->finest());
74  }
75  ML_CLOG(DEBUG, "Controller", "done iterating on step " << this->get_step()
76  << " (" << this->get_iteration() << "/"
77  << this->get_max_iterations() << ")");
78 
79  for (auto l = this->finest(); l >= this->coarsest(); --l) {
80  l.current()->post_step();
81  }
82 
83  if (nblock < nblocks - 1) {
84  broadcast();
85  }
86 
87  this->comm->status->clear();
88  }
89  }
90 
91  template<typename time>
93  {
94  auto fine = l.current();
95  auto crse = l.coarse();
96  auto trns = l.transfer();
97 
98  perform_sweeps(l.level);
99 
100  if (l == this->finest() && fine->converged()) {
101  this->comm->status->set_converged(true);
102  }
103 
104  fine->send(comm, tag(l), false);
105  trns->restrict(crse, fine, true);
106  trns->fas(this->get_step_size(), crse, fine);
107  crse->save();
108 
109  return l - 1;
110  }
111 
112  template<typename time>
114  {
115  auto fine = level_iter.current();
116  auto crse = level_iter.coarse();
117  auto trns = level_iter.transfer();
118 
119  trns->interpolate(fine, crse, true);
120  fine->recv(comm, tag(level_iter), false);
121  trns->interpolate_initial(fine, crse);
122 
123  if (level_iter < this->finest()) {
124  perform_sweeps(level_iter.level);
125  }
126 
127  return level_iter + 1;
128  }
129 
130  template<typename time>
132  {
133  auto crse = level_iter.current();
134 
135  if (this->comm->status->previous_is_iterating()) {
136  crse->recv(comm, tag(level_iter), true);
137  }
138  this->comm->status->recv(stag(level_iter));
139  this->perform_sweeps(level_iter.level);
140  crse->send(comm, tag(level_iter), true);
141  this->comm->status->set_converged(!this->comm->status->keep_iterating());
142  this->comm->status->send(stag(level_iter));
143  return level_iter + 1;
144  }
145 
146  template<typename time>
148  {
149  if (level_iter.level == 0) {
150  level_iter = cycle_bottom(level_iter);
151  } else {
152  level_iter = cycle_down(level_iter);
153  level_iter = cycle_v(level_iter);
154  level_iter = cycle_up(level_iter);
155  }
156  return level_iter;
157  }
158 
159  template<typename time>
161  {
162  this->get_finest()->spread();
163 
164  // restrict fine initial condition
165  for (auto l = this->finest() - 1; l >= this->coarsest(); --l) {
166  auto crse = l.current();
167  auto fine = l.fine();
168  auto trns = l.transfer();
169  trns->restrict_initial(crse, fine);
170  crse->spread();
171  crse->save();
172  }
173 
174  // perform sweeps on the coarse level based on rank
175  predict = true;
176  auto crse = this->coarsest().current();
177  for (int nstep = 0; nstep < comm->rank() + 1; nstep++) {
178  // XXX: set iteration and step?
179  perform_sweeps(0);
180  if (nstep < comm->rank()) {
181  crse->advance();
182  }
183  }
184 
185  // return to finest level, sweeping as we go
186  for (auto l = this->coarsest() + 1; l <= this->finest(); ++l) {
187  auto crse = l.coarse();
188  auto fine = l.current();
189  auto trns = l.transfer();
190 
191  trns->interpolate(fine, crse, true);
192  if (l < this->finest()) {
193  perform_sweeps(l.level);
194  }
195  }
196  }
197 
198  template<typename time>
200  {
201  this->get_finest()->broadcast(this->comm);
202  }
203 
211  template<typename time>
212  int PFASST<time>::tag(LevelIter level_iter)
213  {
214  return (level_iter.level+1) * 10000 + this->get_iteration();
215  }
216 
217  template<typename time>
219  {
220  return level_iter.level * 1000 + this->get_iteration();
221  }
222 
227  template<typename time>
229  {
230  if (this->comm->status->previous_is_iterating()) {
231  this->comm->status->post(0);
232  for (auto l = this->coarsest() + 1; l <= this->finest(); ++l) {
233  l.current()->post(comm, tag(l));
234  }
235  }
236  }
237 } // ::pfasst
virtual void run()
Solve ODE using MLSDC.
Definition: mlsdc_impl.hpp:62
virtual void broadcast()
Broadcast finest level to all processes of PFASST::comm.
LevelIter cycle_v(LevelIter level_iter)
Perform an MLSDC V-cycle.
shared_ptr< R > coarse()
Get the next coarser level based on LevelIter::current()
Definition: interface.hpp:365
Value exception.
Definition: interfaces.hpp:50
void perform_sweeps(size_t level)
Definition: pfasst_impl.hpp:9
Level (MLSDC/PFASST) iterator.
Definition: interface.hpp:306
#define ML_CLOG(level, logger_id, x)
same as CLOG(level, logger, x) from easylogging++
Definition: logging.hpp:117
LevelIter cycle_up(LevelIter level_iter)
Interpolate coarse correction to fine, sweep on current (fine).
virtual void predictor()
Predictor: restrict initial down, preform coarse sweeps, return to finest.
virtual void post()
Post current status and values to next processor.
shared_ptr< R > transfer()
Get transfer operator for current level.
Definition: interface.hpp:377
LevelIter cycle_down(LevelIter level_iter)
Sweep on current (fine), restrict to coarse.
Definition: pfasst_impl.hpp:92
virtual int stag(LevelIter level_iter)
virtual void set_comm(ICommunicator *comm)
Set communicator.
Definition: pfasst_impl.hpp:30
virtual int tag(LevelIter level_iter)
Generate a unique tag for level iterator.
shared_ptr< R > current()
Get level this iterator is currently pointing at.
Definition: interface.hpp:341
Abstract interface for communicators.
Definition: interfaces.hpp:70
LevelIter cycle_bottom(LevelIter level_iter)
Sweep on the current (coarsest) level.
virtual void run() override
Solve ODE using PFASST.
Definition: pfasst_impl.hpp:40